我有多维数组的脚本而不是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)
所以我们有一个矩阵arr
,有3行4列。
我脚本中最简单的情况是向数组中的值添加。例如。我正在为单个或多个行:
执行此操作> 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)
这与行的工作方式不一样吗?我在这里做错了什么?
答案 0 :(得分:6)
要将1D数组添加到多个列,您需要将broadcast值添加到2D数组。由于广播默认在左侧(形状)添加新轴,因此将行向量广播到多行:
arr[0:2] += someVector
someVector
具有形状(N,)
并自动广播以塑造(1, N)
。如果arr[0:2]
具有形状(2, N)
,那么总和将按元素执行,就好像arr[0:2]
和someVector
都是相同形状的数组(2, N)
。< / p>
但是要将列向量广播到多个列,需要提示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)
。< / p>
答案 1 :(得分:6)
非常清楚地解释@unutbu。
作为补充,换位(.T
)通常可以通过在第一维中工作来简化任务:
In [273]: arr = np.arange(12).reshape(3, 4)
In [274]: arr.T[0:2] += [1, 2, 3]
In [275]: arr
Out[275]:
array([[ 1, 2, 2, 3],
[ 6, 7, 6, 7],
[11, 12, 10, 11]])