在Python中使用numpy/scipy高效计数数组中的唯一元素

16 投票
4 回答
14061 浏览
提问于 2025-04-16 06:11

我有一个scipy数组,比如说:

a = array([[0, 0, 1], [1, 1, 1], [1, 1, 1], [1, 0, 1]])

我想统计数组中每个独特元素出现的次数。比如,对于上面的数组a,我想知道[0, 0, 1]出现了1次,[1, 1, 1]出现了2次,还有[1, 0, 1]出现了1次。

我想到的一个方法是:

from collections import defaultdict
d = defaultdict(int)

for elt in a:
  d[elt] += 1

有没有更好或者更高效的方法呢?

谢谢。

4 个回答

1

适用于 Python 2.6 及更早版本

import itertools

data_array = [[0, 0, 1], [1, 1, 1], [1, 1, 1], [1, 0, 1]]

dict_ = {}

for list_, count in itertools.groupby(data_array):
    dict_.update({tuple(list_), len(list(count))})
4

你可以通过逐行对数组进行字典序排序,然后找出行变化的地方:

In [1]: a = array([[0, 0, 1], [1, 1, 1], [1, 1, 1], [1, 0, 1]])

In [2]: b = a[lexsort(a.T)]

In [3]: b
Out[3]: 
array([[0, 0, 1],
       [1, 0, 1],
       [1, 1, 1],
       [1, 1, 1]])

...


In [5]: (b[1:] - b[:-1]).any(-1)
Out[5]: array([ True,  True, False], dtype=bool)

最后的数组显示前面三行是不同的,而第三行出现了两次。

对于只包含0和1的数组,你可以对这些值进行编码:

In [6]: bincount(dot(a, array([4,2,1])))
Out[6]: array([0, 1, 0, 0, 0, 1, 0, 2])

字典也可以用来处理这些数据。哪种方法最快,取决于你实际使用的数组类型。

8

如果你不介意使用Python 2.7(或者3.1),而且这两个版本中的任何一个对你来说都可以用的话,或许你可以试试新的collections.Counter。这个工具特别适合用在像元组这样的可哈希元素上:

>>> from collections import Counter
>>> c = Counter([(0,0,1), (1,1,1), (1,1,1), (1,0,1)])
>>> c
Counter({(1, 1, 1): 2, (0, 0, 1): 1, (1, 0, 1): 1})

不过,我还没有对这两种方法进行性能测试。

撰写回答