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

dan*_*451 4 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)
Run Code Online (Sandbox Code Playgroud)

所以我们有一个arr3行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]])
Run Code Online (Sandbox Code Playgroud)

这很好用.但是,有时我需要操纵一个或多个.一列一栏有效:

> 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
Run Code Online (Sandbox Code Playgroud)

但我正在努力思考为什么这对多个列不起作用:

> 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)
Run Code Online (Sandbox Code Playgroud)

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

unu*_*tbu 6

要将1D数组添加到多个列,您需要将值广播到2D数组.由于广播默认在左侧(形状)添加新轴,因此自动将行向量广播到多行:

arr[0:2] += someVector
Run Code Online (Sandbox Code Playgroud)

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]])
Run Code Online (Sandbox Code Playgroud)

someVector(例如np.array([1, 2, 3]))具有形状(N,)someVector[:, None]形状,(N, 1)所以现在广播发生在右边.如果arr[:, 0:2]有形状(N, 2),则总和进行逐元素好像两者arr[:, 0:2]someVector[:, None]是相同形状的阵列,(N, 2).


B. *_* M. 6

@unutbu非常明确的解释.

作为补充,transposition(.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]])
Run Code Online (Sandbox Code Playgroud)