Object 对象数据类型重新排列中值的计数频率

Object 对象数据类型重新排列中值的计数频率,object,numpy,types,frequency,recarray,Object,Numpy,Types,Frequency,Recarray,以下是我的意见: data = np.array ([( 'a1' , np.NaN , 'a2' ), ( 'a1' , 'b2' , 'b1' ), ( 'c1' , 'c1' , np.NaN )], dtype = [( 'A' , object ), ( 'B' , object ),

以下是我的意见:

data = np.array ([( 'a1' , np.NaN , 'a2' ), 
                  ( 'a1' , 'b2' , 'b1' ),  
                  ( 'c1' , 'c1' , np.NaN )], 
                 dtype = [( 'A' , object ), 
                          ( 'B' , object ), 
                          ( 'C' , object )] ).view (np.recarray)
我想计算一个变量取的每个值的频率,我想让输出看起来像(比如对于输入
freq('a')
):


我尝试了
np.bincounts()
,但显然它对对象数据类型不起作用。有没有办法用NumPy实现这一点

您可以使用
np.unique
数据['A']
中的每个对象指定一个整数“标签”。然后您可以将
np.bincount
应用于
标签
s:

In [18]: uniq, label = np.unique(data['A'], return_inverse=True)

In [19]: np.column_stack([uniq, np.bincount(label)])
Out[19]: 
array([['a1', 2],
       ['c1', 1]], dtype=object)
请注意,在dtype
object
的NumPy数组上的操作并不比在列表上的等效操作快(通常慢)。(您需要将数组与本机NumPy(即非对象)数据类型一起使用,才能享受比纯Python更快的速度优势。)例如,如果您对
数据使用列表,并使用
集合计算频率,则计算速度可能会更快。计数器

In [21]: data = {'A':['a1','a1','c1']}

In [22]: import collections

In [23]: collections.Counter(data['A'])
Out[23]: Counter({'a1': 2, 'c1': 1})

正如hpaulj指出的,当
data
也是一个重新排列时,可以使用
collection.Counter(data['A'])
。它比上面显示的
np.unique
/
np.bincount
方法更快。因此,如果必须使用对象的重新排列,这可能是您的最佳选择


以下是显示相对速度的基准:

data = np.random.choice(['a','b','c'], size=(300,)).astype(
    [('A', object), ('B', object), ('C', object)]).view(np.recarray)
data2 = {key:data[key].tolist() for key in ['A','B','C']}
在列表中使用
计数器
最快:

In [92]: %timeit collections.Counter(data2['A'])
100000 loops, best of 3: 13.7 µs per loop
对数据类型
对象
数组使用
计数器
是第二快的:

In [91]: %timeit collections.Counter(data['A'])
10000 loops, best of 3: 29.1 µs per loop
我最初的建议非常慢(尽管这是一个苹果对桔子的比较,因为它返回一个数组,而不是一个dict):


计数器(数据['A'])
在数据为重新排列时工作。换句话说,它适用于一维对象数组<代码>计数器(np.array(data.tolist(),object).ravel())
用于计算整个数组(即转换为二维对象数组并展平)。谢谢,@hpaulj。这肯定比我建议的
unique/bincount
方法要好。
In [91]: %timeit collections.Counter(data['A'])
10000 loops, best of 3: 29.1 µs per loop
In [93]: %%timeit 
   ....: uniq, label = np.unique(data['A'], return_inverse=True)
   ....: np.column_stack([uniq, np.bincount(label)])
   ....: 
10000 loops, best of 3: 118 µs per loop