numpy求和矩阵 - 按索引排列

Jon*_*Nir 6 python numpy vectorization

我有3个矩阵(np数组):
A是形状(n,m); B的形状为(m,k); 和C的形状(n,k)

矩阵C只有集合{-1,0,1}中的值,它是某种类型的"指标":如果C [i,j] == 1那么我想将第i行添加到b的第j列; 如果C [i,j] ==( - 1)则减去(0不做任何事).

它可以很容易地用循环来完成,但我想知道是否有一种矢量化的方式可以做得更快?

示例代码:

C = np.array([[-1,  0,  0,  0,  1],
              [ 0,  0,  0,  0, -1],
              [ 0,  0,  0,  0, -1],
              [-1,  0,  0,  1,  1]])
a,b = np.where(C==1)
#here a=[0,3,3] and b=[4,3,4]
A[a,:] = [[0, 1, 2, 3, 4, 5, 6],
          [3, 3, 3, 3, 3, 3, 3],
          [3, 3, 3, 3, 3, 3, 3]]
B[:,b] += A[a]  #B is all 0.0 before  
Run Code Online (Sandbox Code Playgroud)

预期结果:

array([[ 0.,  0.,  0.,  3.,  3.],
       [ 0.,  0.,  0.,  3.,  4.],
       [ 0.,  0.,  0.,  3.,  5.],
       [ 0.,  0.,  0.,  3.,  6.],
       [ 0.,  0.,  0.,  3.,  7.],
       [ 0.,  0.,  0.,  3.,  8.],
       [ 0.,  0.,  0.,  3.,  9.]])
Run Code Online (Sandbox Code Playgroud)

实际结果:

array([[ 0.,  0.,  0.,  3.,  3.],
       [ 0.,  0.,  0.,  3.,  3.],
       [ 0.,  0.,  0.,  3.,  3.],
       [ 0.,  0.,  0.,  3.,  3.],
       [ 0.,  0.,  0.,  3.,  3.],
       [ 0.,  0.,  0.,  3.,  3.],
       [ 0.,  0.,  0.,  3.,  3.]])
Run Code Online (Sandbox Code Playgroud)

Div*_*kar 2

我们可以简单地使用np.add.at转置视图B-

np.add.at(B.T, b, A[a])
Run Code Online (Sandbox Code Playgroud)

样本运行 -

In [39]: C = np.array([[-1,  0,  0,  0,  1],
    ...:               [ 0,  0,  0,  0, -1],
    ...:               [ 0,  0,  0,  0, -1],
    ...:               [-1,  0,  0,  1,  1]])
    ...: a,b = np.where(C==1)
    ...: A = np.zeros((4,7),dtype=int)
    ...: A[a,:] = np.array([[0, 1, 2, 3, 4, 5, 6],
    ...:           [3, 3, 3, 3, 3, 3, 3],
    ...:           [3, 3, 3, 3, 3, 3, 3]])

In [40]: # Initialize B
    ...: B = np.zeros((7,5),dtype=int)

In [41]: np.add.at(B.T, b, A[a])

In [42]: B
Out[42]: 
array([[0, 0, 0, 3, 3],
       [0, 0, 0, 3, 4],
       [0, 0, 0, 3, 5],
       [0, 0, 0, 3, 6],
       [0, 0, 0, 3, 7],
       [0, 0, 0, 3, 8],
       [0, 0, 0, 3, 9]])
Run Code Online (Sandbox Code Playgroud)

作为commented by @DSM,我们还可以使用矩阵乘法,从而避免获取索引的步骤C==1 -

A.T.dot(C==1)
Run Code Online (Sandbox Code Playgroud)