沿numpy数组中的值轴的元素计数

时间:2017-11-06 05:14:53

标签: python numpy scipy

如何沿着给定轴获得每个元素在numpy数组中出现次数的元素计数?通过"元素方式,"我的意思是应该将数组的每个值转换为它出现的次数。

简单的2D输入:

[[1, 1, 1],
 [2, 2, 2],
 [3, 4, 5]]

应输出:

[[3, 3, 3],
 [3, 3, 3],
 [1, 1, 1]]

解决方案还需要相对于给定轴工作。例如,如果我的输入数组a具有形状(4, 2, 3, 3),我认为它是" 3x3矩阵的3x3矩阵,"运行solution(a)应该吐出上述表单的(4, 2, 3, 3)解决方案,其中每个3x3"子矩阵"包含相对于该子矩阵的相应元素的计数,而不是整个numpy数组。

更复杂的示例:假设我将示例输入放在a上方并调用skimage.util.shape.view_as_windows(a, (2, 2))。这为我提供了形状为b的数组(2, 2, 2, 2)

[[[[1 1]
   [2 2]]

  [[1 1]
   [2 2]]]


 [[[2 2]
   [3 4]]

  [[2 2]
   [4 5]]]]

然后solution(b)应输出:

[[[[2 2]
   [2 2]]

  [[2 2]
   [2 2]]]


 [[[2 2]
   [1 1]]

  [[2 2]
   [1 1]]]]

因此,即使值1在a中出现3次,在b中出现4次,但在每个2x2窗口中仅出现两次。

1 个答案:

答案 0 :(得分:3)

开始接近

我们可以使用np.unique来获取出现次数,并从0开始标记每个元素,让我们使用所需输出的标记索引这些计数,如下所示 -

In [43]: a
Out[43]: 
array([[1, 1, 1],
       [2, 2, 2],
       [3, 4, 5]])

In [44]: _,ids,c = np.unique(a, return_counts=1, return_inverse=1)

In [45]: c[ids].reshape(a.shape)
Out[45]: 
array([[3, 3, 3],
       [3, 3, 3],
       [1, 1, 1]])

对于输入数组中的正整数,我们也可以使用np.bincount -

In [73]: c = np.bincount(a.ravel())

In [74]: c[a]
Out[74]: 
array([[3, 3, 3],
       [3, 3, 3],
       [1, 1, 1]])

对于负整数数字,只需偏移其中的最小值。

扩展到通用n-dims

让我们使用bincount -

In [107]: ar
Out[107]: 
array([[[1, 1, 1],
        [2, 2, 2],
        [3, 4, 5]],

       [[2, 3, 5],
        [4, 3, 4],
        [3, 1, 2]]])

In [104]: ar2D = ar.reshape(-1,ar.shape[-2]*ar.shape[-1])

# bincount2D_vectorized from https://stackoverflow.com/a/46256361/ @Divakar
In [105]: c = bincount2D_vectorized(ar2D)

In [106]: c[np.arange(ar2D.shape[0])[:,None], ar2D].reshape(ar.shape)
Out[106]: 
array([[[3, 3, 3],
        [3, 3, 3],
        [1, 1, 1]],

       [[2, 3, 1],
        [2, 3, 2],
        [3, 1, 2]]])