多次更新python numpy数组列

时间:2017-06-07 09:59:39

标签: python numpy vectorization

假设我有一个2x3矩阵A

1 2 3   
4 5 6  

和长度为4的向量y

0 1 2 1

以及另一个4x2矩阵B

0 0  
1 1   
2 2   
3 3 

我希望通过添加A行来多次更新B列。 要更新的A列的索引由y给出。

使用for循环,可以这样做:

for i in np.arange(4):
  A[:,y[i]] += B[i,:]

我使用ufunc.at实现了这个:

np.add.at(A.T,y,B)  

但是,ufunc.at的效果几乎与使用for循环一样糟糕。

如何获得不同的矢量化实现?

使用A[:,y]+=B.T进行更新似乎只会更新每列一次。

1 个答案:

答案 0 :(得分:1)

方法#1

以下是使用np.add.reduceat -

的间隔使用汇总的一种方法
def reduceat_app(A, y, B):
    idx = y.argsort()
    y0 = y[idx]
    sep_idx = np.concatenate(([0], np.flatnonzero(y0[1:] != y0[:-1])+1))
    A += np.add.reduceat(B[idx],sep_idx).T

方法#2

A中的行数相对较少,我们也可以使用np.bincount以迭代的方式为每一行执行基于bin的求和,如下所示 -

def bincount_loopy_app(A, y, B): 
    n = A.shape[1]
    for i,a in enumerate(A):
        a += np.bincount(y,B[:,i],minlength=n).astype(A.dtype)

方法#3

我们可以通过为所有元素创建2D ybincount索引/二进制网格来矢量化以前的方法,这样对于每一行,我们都会有偏移的二进制数。通过该偏移,def bincount_vectorized_app(A, y, B): m,n = A.shape IDs = y[:,None] + n*np.arange(B.shape[1]) vals = np.bincount(IDs.ravel(), B.ravel(), minlength=m*n) A += vals.astype(A.dtype).reshape((m,n)) 可用于以矢量化方式跨所有行执行基于bin的求和。

因此,实施将是 -

ItemTemplate