在Numpy数组中累加常数值

5

我想给一个numpy数组的某些特定单元格加1,但是我找不到任何不使用缓慢循环的方法:

coords = np.array([[1,2],[1,2],[1,2],[0,0]])
X      = np.zeros((3,3))

for i,j in coords:
  X[i,j] +=1 

导致:
X = [[ 1.  0.  0.]
     [ 0.  0.  3.]
     [ 0.  0.  0.]]

X[coords[:,0],coords[:,1] += 1 返回结果如下:

X = [[ 1.  0.  0.]
     [ 0.  0.  1.]
     [ 0.  0.  0.]]

有需要帮忙的吗?
3个回答

5

numpy.at 专为这些情况而设计。

In [1]: np.add.at(X,tuple(coords.T),1)

In [2]: X
Out[2]: 
array([[ 1.,  0.,  0.],
       [ 0.,  0.,  3.],
       [ 0.,  0.,  0.]])

这很不错,但是在numba中使用for循环会快80倍 :/ https://stackoverflow.com/q/57561500/125507 - endolith
删除的问题? - Tejas Kale

4
您可以使用 np.bincount,例如 -
out_shape = (3,3) # Input param

# Get linear indices corresponding to coords with the output array shape.
# These form the IDs for accumulation in the next step.
ids = np.ravel_multi_index(coords.T,out_shape)

# Use bincount to get 1-weighted accumulations. Since bincount assumes 1D
# array, we need to do reshaping before and after for desired output.
out = np.bincount(ids,minlength=np.prod(out_shape)).reshape(out_shape)

如果您想要分配除了1s以外的其他值,可以使用额外的输入参数将权重提供给np.bincount

示例运行 -

In [2]: coords
Out[2]: 
array([[1, 2],
       [1, 2],
       [1, 2],
       [0, 0]])

In [3]: out_shape = (3,3) # Input param
   ...: ids = np.ravel_multi_index(coords.T,out_shape)
   ...: out = np.bincount(ids,minlength=np.prod(out_shape)).reshape(out_shape)
   ...: 

In [4]: out
Out[4]: 
array([[1, 0, 0],
       [0, 0, 3],
       [0, 0, 0]], dtype=int64)

1
谢谢,我没有想到这一点。我本来期望numpy能够为这样一个微不足道的操作提供更简单的解决方案。 - memecs
2
@memecs:在我看来,无论是微不足道的问题还是不是,我认为它并不是那么常见,而当我们实现简单的解决方案时,这才是最重要的。;-) - Peque

2

另一个选择是np.histogramdd

bins = [np.arange(d + 1) for d in X.shape]
out, edges = np.histogramdd(coords, bins)

print(out)
# [[ 1.  0.  0.]
#  [ 0.  0.  3.]
#  [ 0.  0.  0.]]

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