Numpy:一次向量化访问多个列?
Numpy: vectorized access of several columns at once?
我有包含多维数组的脚本,我想使用矢量化实现来解决我的问题(有时包含列操作)而不是 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)
.
@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]])
我有包含多维数组的脚本,我想使用矢量化实现来解决我的问题(有时包含列操作)而不是 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)
.
@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]])