在numpy中将向量添加到矩阵行

24

在numpy中,是否有一种快速的方法可以将一个向量添加到矩阵的每一行或每一列。

最近,我一直在将该向量重复成与矩阵相同大小的矩阵,但这样会消耗大量内存。例如

    mat=np.arange(15)
    mat.shape=(5,3)

    vec=np.ones(3)
    mat+=np.tile(vec, (5,1))

我能想到的另一种方法是使用Python循环,但循环速度较慢:

    for i in xrange(len(mat)):
        mat[i,:]+=vec
有没有一种快速的方法在numpy中实现这个操作,而不需要使用C扩展程序? 希望能够像广播的更灵活版本那样虚拟平铺向量。或者能够按行或列迭代操作,这在某些ufunc方法中几乎是可以做到的。

你能再给一个例子吗?你给的那个例子只是用mat + vec得到了相同的答案,所以我不确定你想要什么。[顺便说一句,这是一个“数组”,而不是一个“矩阵”。] - DSM
通过“矩阵”,我指的是一个二维数组(在数学意义上的矩阵)。 - user1149913
我想将相同的一维数组添加到二维数组的每一行。 - user1149913
1
在numpy中,matrix与2d array是不同的。例如,在matrix对象上进行乘法运算是矩阵乘法,而在array对象上是逐元素相乘,因此将它们区分开来是一个好主意。 - DSM
2个回答

40

如果要将一维数组添加到每行中,广播已经为您处理好了:

mat += vec

然而,更普遍的做法是使用 np.newaxis 将数组强制转换为可广播形式。例如:

mat + np.ones(3)[np.newaxis,:]

虽然不需要将数组添加到每一行,但对于列相加来说这是必要的:

mat + np.ones(5)[:,np.newaxis]

编辑:正如Sebastian所提到的,对于行添加,mat + vec已经正确处理了广播。它也比使用np.newaxis更快。我已经编辑了我的原始回答,以使这一点清楚。


1
这里甚至不需要,但如果mat的形状为(3,5),那么使用np.ones(3)[:,np.newaxis]就可以解决问题了。 - seberg
@Sebastian:你说得对,我只是想展示一种通用的方法来正确获取广播,因为OP要求同时添加列和行。 - JoshAdel
好的,今天我一定是真的很蠢。有人可以解释一下为什么这不只是“mat + vec”的一个较慢版本吗? - DSM
在numpy 1.18中,当我尝试运行mat += vec时,出现了错误numpy.core._exceptions.UFuncTypeError: Cannot cast ufunc 'add' output from dtype('float64') to dtype('int64') with casting rule 'same_kind'。然而,np.newaxis技巧可行。 - Trevor
1
@Trevor,错误提示你正在尝试将两个具有不同数据类型的numpy数组相加,这导致了错误。请确保matvec都使用相同的数据类型。 - Jonathan Lam
显示剩余3条评论

0
Numpy广播将自动将兼容大小的向量(1D数组)添加到矩阵(2D数组,而不是numpy matrix)。它通过从右到左匹配基于维度的形状来完成这个过程,"拉伸"缺失或值为1的维度以匹配其他维度。这在https://numpy.org/doc/stable/user/basics.broadcasting.html中有解释:
mat:               5 x 3
vec:                   3
vec (broadcasted): 5 x 3

默认情况下,numpy 数组 是行优先(“C顺序”),其中轴0是“矩阵行”,轴1是“矩阵列”,因此广播将向轴0沿着矩阵行克隆向量作为矩阵行。


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