计算numpy数组中的出现次数

时间:2014-11-07 14:30:45

标签: python arrays numpy

我有两个相同维度的标签和标签类别的数组。我想根据类别对标签进行分组并计算标签的出现次数。

正如您所看到的,标签可以共享相同的类别(' world',' hello')。

我知道这可以通过循环轻松完成,但我确定numpy有一些很好的方法可以更有效地完成它。任何帮助将不胜感激。

# Tag category
A = [10, 10, 20, 10, 10, 10, 20, 10, 20, 20]
# Tags
B = ['hello', 'world', 'how', 'are', 'you', 'world', 'you', 'how', 'hello', 'hello']

预期结果:

[(10, (('hello', 1), ('are', 1), ('you', 1), ('world', 2))), (20, (('how', 1), ('you', 1), ('hello', 2)))]

5 个答案:

答案 0 :(得分:2)

您可以使用嵌套collections.defaultdict

这里我们将使用A中的整数作为外部词典的键,并且对于每个内部词典,我们将使用B中的单词作为键,并且它们的值将是它们的计数。

>>> from collections import defaultdict
>>> from pprint import pprint
>>> d = defaultdict(lambda: defaultdict(int))
>>> for k, v in zip(A, B):
        d[k][v] += 1

现在d包含(我将其转换为普通字典,因为它的输出不那么混乱):

>>> pprint({k: dict(v) for k, v in d.items()})
{10: {'are': 1, 'hello': 1, 'how': 1, 'world': 2, 'you': 1},
 20: {'hello': 2, 'how': 1, 'you': 1}}

现在我们需要遍历外部字典并在外部列表上调用tuple(.iteritems())以获得所需的输出:

>>> pprint([(k, tuple(v.iteritems())) for k, v in d.items()])
[(10, (('world', 2), ('you', 1), ('hello', 1), ('how', 1), ('are', 1))),
 (20, (('how', 1), ('you', 1), ('hello', 2)))]

答案 1 :(得分:2)

由于已经提到过,这里有一种用Pandas聚合值的方法。

设置DataFrame ...

>>> import pandas as pd
>>> df = pd.DataFrame({'A': A, 'B': B})
>>> df
    A      B
0  10  hello
1  10  world
2  20    how
3  10    are
4  10    you
5  10  world
6  20    you
7  10    how
8  20  hello
9  20  hello

透视聚合价值......

>>> table = pd.pivot_table(df, rows='B', cols='A', aggfunc='size')
>>> table
A      10  20
B            
are     1 NaN
hello   1   2
how     1   1
world   2 NaN
you     1   1

转换回字典......

>>> table.to_dict()
{10: {'are': 1.0, 'hello': 1.0, 'how': 1.0, 'world': 2.0, 'you': 1.0},
 20: {'are': nan, 'hello': 2.0, 'how': 1.0, 'world': nan, 'you': 1.0}}

从这里你可以使用Python将字典调整为所需的格式(例如列表)。

答案 2 :(得分:0)

这是一种方式:

>>> from collections import Counter
>>> A = np.array([10, 10, 20, 10, 10, 10, 20, 10, 20, 20])
>>> B = np.array(['hello', 'world', 'how', 'are', 'you', 'world', 'you', 'how', 'hello','hello'])
>>> [(i,Counter(B[np.where(A==i)]).items()) for i in set(A)]
[(10, [('world', 2), ('you', 1), ('hello', 1), ('how', 1), ('are', 1)]), (20, [('how', 1), ('you', 1), ('hello', 2)])]

答案 3 :(得分:0)

  

但我确定numpy有一些更有效的方式来更有效地做到这一点

,你是对的!以下是代码

# convert to integer
category_lookup, categories = numpy.unique(A, return_inverse=True)
tag_lookup, tags = numpy.unique(B, return_inverse=True)

statistics = numpy.zeros([len(category_lookup), len(tag_lookup)])
numpy.add.at(statistics, [categories, tags], 1)

result = {}
for category, stat in zip(category_lookup, statistics):
    result[category] = dict(zip(tag_lookup[stat != 0], stat[stat != 0]))

有关说明,请参阅numpy tips and tricks。这给出了预期的答案:

  

{10:{'是':1.0,'你好':1.0,'怎么':1.0,'世界':2.0 ,'你':1.0},   20:{'你好':2.0,'怎么':1.0,'你':1.0}}

我承认,这不是最明确的方法(参见pandas解决方案),但是当你拥有大量数据时它真的很快。

答案 4 :(得分:0)

Python:NumPy简化了计数次数:

#import NumPy

将numpy导入为np

arr = np.array([0,1,2,2,3,3,7,3,4,0,4,4,0,4,5,0,5,9,5,9, 5,8,5]) print(np.sum(arr == 4))#测试数字4的出现

唯一,计数= np.unique(arr,return_counts = True) 打印(唯一,计数)

[0 1 2 3 4 5 7 8 9] [4 1 2 3 4 5 1 1 2]

上面是输出