Numpy:一次对多个列进行矢量化访问?

时间:2016-03-05 14:54:02

标签: python arrays numpy vectorization slice

我有多维数组的脚本而不是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)

这与的工作方式不一样吗?我在这里做错了什么?

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]])