NumPy:将矩阵的每一行减去向量

70

我有一个 n x d 的矩阵和一个 n x 1 的向量。 我想编写一段代码,将矩阵中的每一行都减去这个向量。

我目前使用了一个 for 循环来遍历并将矩阵中的第 i 行减去向量。 有没有一种方法可以更简单地将整个矩阵减去向量?

谢谢!

当前代码:

for i in xrange( len( X1 ) ):
    X[i,:] = X1[i,:] - X2

这是 X1 是矩阵的第 i 行,X2 是向量。我能否使其不需要使用for循环?

3个回答

92

这在numpy中是有效的,但仅当尾部轴具有相同的维度。以下是成功从矩阵中减去向量的示例:

In [27]: print m; m.shape
[[ 0  1  2]
 [ 3  4  5]
 [ 6  7  8]
 [ 9 10 11]]
Out[27]: (4, 3)

In [28]: print v; v.shape
[0 1 2]
Out[28]: (3,)

In [29]: m  - v
Out[29]: 
array([[0, 0, 0],
       [3, 3, 3],
       [6, 6, 6],
       [9, 9, 9]])

这个方法有效是因为两者的尾轴(axis)有相同的维度(3)。

在你的情况下,导向轴(leading axis)具有相同的维度。以下是一个示例,使用与上面相同的 v,展示如何解决这个问题:

In [35]: print m; m.shape
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]
Out[35]: (3, 4)

In [36]: (m.transpose() - v).transpose()
Out[36]: 
array([[0, 1, 2, 3],
       [3, 4, 5, 6],
       [6, 7, 8, 9]])

广播轴的规则在这里详细解释。


1
m-v.transpose() 通常情况下不会有相同的效果。 - C. Yduqoli
2
@MadPhysicist 问题在于,numpy中的一维数组无法进行转置,因为它将与输出相同。您必须向其添加一个维度才能像Nagasaki45的答案或使用ndmin=2参数创建np.array时进行转置。 - xuiqzy
3
@xuiqzy,非常好的观点。我会删除评论。转置通常会复制内存。一个更好的方法可能是 m - v[:, None] - Mad Physicist

21
除了@John1024的答案外,使用numpy翻转一维向量可以按如下方式完成:
In [1]: v = np.arange(3)

In [2]: v
Out[2]: array([0, 1, 2])

In [3]: v = v[:, np.newaxis]

In [4]: v
Out[4]:
array([[0],
       [1],
       [2]])

从这里开始,使用广播(broadcasting)从每列的m中减去v非常简单:

In [5]: print(m)
[[ 0  1  2  3]
 [ 4  5  6  7]
 [ 8  9 10 11]]

In [6]: m - v
Out[6]:
array([[0, 1, 2, 3],
       [3, 4, 5, 6],
       [6, 7, 8, 9]])

3
如果你忘记了np.newaxis这个东西,FYI,m-v[:, None]也是可以用的。我认为这种选择更简单。 - Christian O'Reilly
3
@ChristianO'Reilly. np.newaxis is None。它们指的是同一个对象。在这一点上,这取决于作者认为哪个更易读。 - Mad Physicist

0
如果您只是要创建被减去的向量,也可以使用以下方式创建它:
column_vector = np.array([0,1,2], ndmin=2).T

要获取一个列向量,必须具有2个或更多维度才可能实现。
一维的numpy数组始终是行,无法进行转置!

然后你可以直接这样做

each_column_of_matrix_minus_vector = matrix - column_vector

从每列矩阵中减去列向量


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接