在 numpy 数组中计算列出现次数

6
给定一个2 x d维的numpy数组M,我想要计算M的每一列出现的次数。也就是说,我正在寻找bincount的通用版本。
我尝试过的方法:(1)将列转换为元组(2)通过hash将元组哈希化为自然数(3)使用numpy.bincount
这似乎相当笨拙。有人知道更优雅和高效的方法吗?

有趣的问题。期待看到任何解决方案,因为我的第一个和唯一的想法正是你所做的。 - Reti43
所以您希望得到一个独特列及其计数的列表?这些列的顺序需要保留吗? - ilyas patanam
请展示您尝试的代码。 - Mike Müller
2个回答

5
您可以使用collections.Counter
>>> import numpy as np
>>> a = np.array([[ 0,  1,  2,  4,  5,  1,  2,  3],
...               [ 4,  5,  6,  8,  9,  5,  6,  7],
...               [ 8,  9, 10, 12, 13,  9, 10, 11]])
>>> from collections import Counter
>>> Counter(map(tuple, a.T))
Counter({(2, 6, 10): 2, (1, 5, 9): 2, (4, 8, 12): 1, (5, 9, 13): 1, (3, 7, 11):
1, (0, 4, 8): 1})

如果这是一个三维数组,我该怎么做呢?基本上,我有一张三通道图像,所以不是上面例子中的每个元素,而是有三个数字。 - keshav

2

假设:

a = np.array([[ 0,  1,  2,  4,  5,  1,  2,  3],
              [ 4,  5,  6,  8,  9,  5,  6,  7],
              [ 8,  9, 10, 12, 13,  9, 10, 11]])
b = np.transpose(a)
  1. A more efficient solution than hashing (still requires manipulation):

    I create a view of the array with the flexible data type np.void (see here) such that each row becomes a single element. Converting to this shape will allow np.unique to operate on it.

    %%timeit    
    c = np.ascontiguousarray(b).view(np.dtype((np.void, b.dtype.itemsize*b.shape[1])))
    _, index, counts = np.unique(c, return_index = True, return_counts = True)
    #counts are in the last column, remember original array is transposed
    >>>np.concatenate((b[idx], cnt[:, None]), axis = 1)
    array([[ 0,  4,  8,  1],
           [ 1,  5,  9,  2],
           [ 2,  6, 10,  2],
           [ 3,  7, 11,  1],
           [ 4,  8, 12,  1],
           [ 5,  9, 13,  1]])
    10000 loops, best of 3: 65.4 µs per loop
    

    The counts appended to the unique columns of a.

  2. Your hashing solution.

    %%timeit
    array_hash = [hash(tuple(row)) for row in b]
    uniq, index, counts = np.unique(array_hash, return_index= True, return_counts = True)
    np.concatenate((b[idx], cnt[:, None]), axis = 1)
    10000 loops, best of 3: 89.5 µs per loop
    

更新: Eph的解决方案是最有效和优雅的。

%%timeit
Counter(map(tuple, a.T))
10000 loops, best of 3: 38.3 µs per loop

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接