我有带有多维数组的脚本,而不是 for 循环,我想使用矢量化实现来解决我的问题(有时包含列操作)。
让我们考虑一个带有矩阵 arr
的简单示例:
> arr = np.arange(12).reshape(3, 4)
> arr
> ([[ 0, 1, 2, 3],
[ 4, 5, 6, 7],
[ 8, 9, 10, 11]])
> arr.shape
> (3, 4)
所以我们有一个 3 行 4 列的矩阵
arr
。我的脚本中最简单的情况是 将 添加到数组中的值。例如。我正在为单个或多个 行 执行此操作:
> someVector = np.array([1, 2, 3, 4])
> arr[0] += someVector
> arr
> array([[ 1, 3, 5, 7], <--- successfully added someVector
[ 4, 5, 6, 7], to one row
[ 8, 9, 10, 11]])
> arr[0:2] += someVector
> arr
> array([[ 2, 5, 8, 11], <--- added someVector to two
[ 5, 7, 9, 11], <--- rows at once
[ 8, 9, 10, 11]])
这很好用。但是,有时我需要操作一个或多个 列 。一次一列有效:
> arr[:, 0] += [1, 2, 3]
> array([[ 3, 5, 8, 11],
[ 7, 7, 9, 11],
[11, 9, 10, 11]])
^
|___ added the values [1, 2, 3] successfully to
this column
但我正在努力思考为什么这个 不能同时用于 多列的 :
> arr[:, 0:2] += [1, 2, 3]
> ValueError
> Traceback (most recent call last)
> <ipython-input-16-5feef53e53af> in <module>()
> ----> 1 arr[:, 0:2] += [1, 2, 3]
> ValueError: operands could not be broadcast
> together with shapes (3,2) (3,) (3,2)
这不是与 行 的工作方式完全相同吗?我在这里做错了什么?
最佳答案
要将一维数组添加到多列,您需要将值 broadcast 到二维数组。由于默认情况下广播会在(形状的)左侧添加新轴,因此会自动将行向量广播到多行:
arr[0:2] += someVector
someVector
的形状为 (N,)
并被自动广播为形状 (1, N)
。如果 arr[0:2]
的形状为 (2, N)
,则按元素执行求和,就好像 arr[0:2]
和 someVector
都是相同形状 (2, N)
的数组。但是要将列向量广播到多列需要提示 NumPy 您希望广播发生在右侧的轴上。实际上,您必须使用
someVector[:, np.newaxis]
或等效的 someVector[:, None]
在右侧显式添加新轴:In [41]: arr = np.arange(12).reshape(3, 4)
In [42]: arr[:, 0:2] += np.array([1, 2, 3])[:, None]
In [43]: arr
Out[43]:
array([[ 1, 2, 2, 3],
[ 6, 7, 6, 7],
[11, 12, 10, 11]])
someVector
(例如 np.array([1, 2, 3])
)的形状为 (N,)
,someVector[:, None]
的形状为 (N, 1)
所以现在广播发生在右侧。如果 arr[:, 0:2]
的形状为 (N, 2)
,则按元素执行求和,就好像 arr[:, 0:2]
和 someVector[:, None]
都是相同形状 (N, 2)
的数组。