numpy求和矩阵 - 按索引排列

时间:2018-05-03 14:40:40

标签: 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  

预期结果:

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.]])

实际结果:

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.]])

2 个答案:

答案 0 :(得分:2)

我们可以在np.add.at -

的转置视图上使用B
np.add.at(B.T, b, A[a])

示例运行 -

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]])

作为commented by @DSM,我们也可以使用矩阵 - 多重复制,从而避免获取C==1的索引的步骤 -

A.T.dot(C==1)

答案 1 :(得分:1)

我把这一切都记在脑子里有点麻烦,但我相信这就是你要做的事情:

import numpy as np

n, m, k = 2, 3, 4 

# A is full of 1s
A = np.ones((n,m))
# B is full of 0s
B = np.zeros((m,k))
# C is...  that
C = np.array([
    [ 0,  0, -1,  1],
    [ 0, -1,  1,  0]
])

# Where to add A to B
add_x, add_y = np.where(C==1)
# Where to subtract A to B
sub_x, sub_y = np.where(C==-1)

# Select columns of B and += rows of A 
# (using .T to transpose A so it's the same shape)
B[:,add_y] += A[add_x,:].T
# ditto thing above, but for -=
B[:,sub_y] -= A[sub_x,:].T
print(B)

输出:

[[ 0. -1.  0.  1.]
 [ 0. -1.  0.  1.]
 [ 0. -1.  0.  1.]]