numpy: most efficient frequency counts for unique

2019-01-02 14:47发布

In numpy / scipy, is there an efficient way to get frequency counts for unique values in an array?

Something along these lines:

x = array( [1,1,1,2,2,2,5,25,1,1] )
y = freq_count( x )
print y

>> [[1, 5], [2,3], [5,1], [25,1]]

( For you, R users out there, I'm basically looking for the table() function )

14条回答
查无此人
2楼-- · 2019-01-02 15:35

from collections import Counter Counter(x)

查看更多
人间绝色
3楼-- · 2019-01-02 15:36

I was also interested in this, so I did a little performance comparison (using perfplot, a pet project of mine). Result:

 y = np.bincount(a)
 ii = np.nonzero(y)[0]
 out = np.vstack((ii, y[ii])).T

is by far the fastest. (Note the log-scaling.)

enter image description here


Code to generate the plot:

import numpy as np
import pandas as pd
import perfplot
from scipy.stats import itemfreq


def bincount(a):
    y = np.bincount(a)
    ii = np.nonzero(y)[0]
    return np.vstack((ii, y[ii])).T


def unique(a):
    unique, counts = np.unique(a, return_counts=True)
    return np.asarray((unique, counts)).T


def unique_count(a):
    unique, inverse = np.unique(a, return_inverse=True)
    count = np.zeros(len(unique), np.int)
    np.add.at(count, inverse, 1)
    return np.vstack((unique, count)).T


def pandas_value_counts(a):
    out = pd.value_counts(pd.Series(a))
    out.sort_index(inplace=True)
    out = np.stack([out.keys().values, out.values]).T
    return out


perfplot.show(
    setup=lambda n: np.random.randint(0, 1000, n),
    kernels=[bincount, unique, itemfreq, unique_count, pandas_value_counts],
    n_range=[2**k for k in range(26)],
    logx=True,
    logy=True,
    xlabel='len(a)'
    )
查看更多
登录 后发表回答