从矩阵B的每一行减去矩阵A的每一行而没有循环

时间:2018-01-20 17:27:30

标签: python numpy matrix linear-algebra numpy-broadcasting

给定两个数组A(形状:MXC)和B(形状:NXC),有没有办法从每行{{1}中减去A的每一行没有使用循环?最终输出将是形状(M N X C)。

实施例

B

期望的结果(可以有其他形状)(已编辑):

A = np.array([[  1,   2,   3], 
              [100, 200, 300]])

B = np.array([[  10,   20,   30],
              [1000, 2000, 3000],
              [ -10,  -20,   -2]])

(循环太慢,“外部”减去每个元素而不是每行)

2 个答案:

答案 0 :(得分:5)

可以通过利用broadcasting来有效地完成这项工作(不使用任何循环):

In [28]: (A[:, np.newaxis] - B).reshape(-1, A.shape[1])
Out[28]: 
array([[   -9,   -18,   -27],
       [ -999, -1998, -2997],
       [   11,    22,     5],
       [   90,   180,   270],
       [ -900, -1800, -2700],
       [  110,   220,   302]])

或者,对于比broadcasting快一点的解决方案,我们必须使用numexpr之类的:

In [31]: A_3D = A[:, np.newaxis]
In [32]: import numexpr as ne

# pass the expression for subtraction as a string to `evaluate` function
In [33]: ne.evaluate('A_3D - B').reshape(-1, A.shape[1])
Out[33]: 
array([[   -9,   -18,   -27],
       [ -999, -1998, -2997],
       [   11,    22,     5],
       [   90,   180,   270],
       [ -900, -1800, -2700],
       [  110,   220,   302]], dtype=int64)

另一种效率最低的方法是使用np.repeatnp.tile来匹配两个数组的形状。但请注意,这是效率最低的,因为它在尝试匹配形状时会生成副本

In [27]: np.repeat(A, B.shape[0], 0) - np.tile(B, (A.shape[0], 1))
Out[27]: 
array([[   -9,   -18,   -27],
       [ -999, -1998, -2997],
       [   11,    22,     5],
       [   90,   180,   270],
       [ -900, -1800, -2700],
       [  110,   220,   302]])

答案 1 :(得分:0)

使用Kronecker productnumpy.kron):

>>> import numpy as np
>>> A = np.array([[  1,   2,   3], 
...               [100, 200, 300]])
>>> B = np.array([[  10,   20,   30],
...               [1000, 2000, 3000],
...               [ -10,  -20,   -2]])
>>> (m,c) = A.shape
>>> (n,c) = B.shape
>>> np.kron(A,np.ones((n,1))) - np.kron(np.ones((m,1)),B)
array([[   -9.,   -18.,   -27.],
       [ -999., -1998., -2997.],
       [   11.,    22.,     5.],
       [   90.,   180.,   270.],
       [ -900., -1800., -2700.],
       [  110.,   220.,   302.]])