【问题标题】:Subtracting Row From Column in NumPy从 NumPy 中的列中减去行
【发布时间】:2025-12-21 14:55:07
【问题描述】:

我有一个 m 维 NumPy 数组 A 和一个 n 维 NumPy 数组 B
我想创建一个 m x n 矩阵 C 使得 C[i, j] = B[j] - A[i]
在 NumPy 中是否有一种高效/矢量化的方式来执行此操作?

目前我正在使用:

C = np.zeros((M, N))
for i in range(0, M):
    C[i, :] = (B - A[i])

编辑:
m, n 是大数字,因此,C 是一个更大的矩阵(m*n 条目)
我尝试了np.repeatnp.subtract.outer,但它们都使我的 RAM 崩溃了

【问题讨论】:

  • 看看我对答案所做的编辑。您可以指定 'out' 关键字以避免操作创建任何新数组。
  • 无论如何你都会得到一个数组 (M,N) 大小,如果你用 C 做其他事情,可能是两个。

标签: python numpy vectorization


【解决方案1】:

我想你在找ǹp.subtract.outer

M = 5
N = 10

A = np.arange(N)
B = np.arange(M)
np.subtract.outer(A,B)

输出:

array([[ 0, -1, -2, -3, -4],
       [ 1,  0, -1, -2, -3],
       [ 2,  1,  0, -1, -2],
       [ 3,  2,  1,  0, -1],
       [ 4,  3,  2,  1,  0],
       [ 5,  4,  3,  2,  1],
       [ 6,  5,  4,  3,  2],
       [ 7,  6,  5,  4,  3],
       [ 8,  7,  6,  5,  4],
       [ 9,  8,  7,  6,  5]])

它将对 A 和 B 中的所有对应用减法。对于 1 维,它相当于

C = empty(len(A),len(B))
for i in range(len(A)):
    for j in range(len(B)):
        C[i,j] = A[i] - B[j]

编辑

如果您有内存问题,您可以尝试在执行操作之前分配输出缓冲区并适当地设置 out 关键字:

C = np.zeros((M, N))
np.subtract.outer(B, A, out=C)

【讨论】:

    【解决方案2】:

    您可以在新轴上重复其中一个数组,然后减去另一个数组。

    例子:

    m = 10
    n = 20
    
    A = np.array(range(m))
    B = np.array(range(n))
    C = np.repeat(B[:, np.newaxis], m, axis=1) - A
    

    那么 C 将包含:

    array([[ 0, -1, -2, -3, -4, -5, -6, -7, -8, -9],
           [ 1,  0, -1, -2, -3, -4, -5, -6, -7, -8],
           [ 2,  1,  0, -1, -2, -3, -4, -5, -6, -7],
           [ 3,  2,  1,  0, -1, -2, -3, -4, -5, -6],
           [ 4,  3,  2,  1,  0, -1, -2, -3, -4, -5],
           [ 5,  4,  3,  2,  1,  0, -1, -2, -3, -4],
           [ 6,  5,  4,  3,  2,  1,  0, -1, -2, -3],
           [ 7,  6,  5,  4,  3,  2,  1,  0, -1, -2],
           [ 8,  7,  6,  5,  4,  3,  2,  1,  0, -1],
           [ 9,  8,  7,  6,  5,  4,  3,  2,  1,  0],
           [10,  9,  8,  7,  6,  5,  4,  3,  2,  1],
           [11, 10,  9,  8,  7,  6,  5,  4,  3,  2],
           [12, 11, 10,  9,  8,  7,  6,  5,  4,  3],
           [13, 12, 11, 10,  9,  8,  7,  6,  5,  4],
           [14, 13, 12, 11, 10,  9,  8,  7,  6,  5],
           [15, 14, 13, 12, 11, 10,  9,  8,  7,  6],
           [16, 15, 14, 13, 12, 11, 10,  9,  8,  7],
           [17, 16, 15, 14, 13, 12, 11, 10,  9,  8],
           [18, 17, 16, 15, 14, 13, 12, 11, 10,  9],
           [19, 18, 17, 16, 15, 14, 13, 12, 11, 10]])
    

    【讨论】:

      【解决方案3】:

      这是一个简单的广播任务:

      In [31]: A =np.arange(3); B=np.arange(4)
      In [32]: C = B - A[:,None]
      In [33]: C.shape
      Out[33]: (3, 4)
      In [34]: C
      Out[34]: 
      array([[ 0,  1,  2,  3],
             [-1,  0,  1,  2],
             [-2, -1,  0,  1]])
      

      这类似于https://*.com/a/66842410/901925 答案,但没有必要使用repeat。这应该会稍微减少内存使用量,但如果M*N*8 接近您的内存限制,则使用C 的此操作或后续操作可能会达到该限制。

      【讨论】: