如何基于 2D 索引和 1D 值向量替换 Numpy 3D 数组中沿 z 轴的值

Chr*_*ian 6 arrays indexing numpy

我似乎很难理解数组索引。

给出的内容:

我确实有一个像这样的 3d 数组:

a_3d = np.zeros((3,3,3))
Run Code Online (Sandbox Code Playgroud)

一个二维索引数组:

a_2d_index = np.array([[0,0,1], [0,0,0], [0,1,1]]).astype('bool')
Run Code Online (Sandbox Code Playgroud)

以及在 x,y 位置放置到 3d 数组中的值:

a_1d_fill = np.array([10,20,30])
Run Code Online (Sandbox Code Playgroud)

现在,我确实想使用 a_2d_index 来查找 a_3d 中的位置并将 a_1d_fill 垂直放置在这个 x,y 位置......

最终结果应如下所示:

a_3d := [[[0,0, 10],
          [0,0,  0],
          [0,10,10]],
         [[0,0, 20],
          [0,0,  0],
          [0,20,20]],
         [[0,0, 30],
          [0,0,  0],
          [0,30,30]]]
Run Code Online (Sandbox Code Playgroud)

这将用于非常大的阵列,因此内存效率和速度至关重要......(少量复制,最好就地修改)

Stu*_*erg 7

In [26]: a_3d = np.zeros((3,3,3), dtype=int)

In [27]: a_2d_index = np.array([[0,0,1], [0,0,0], [0,1,1]]).astype('bool')

In [28]: a_1d_fill = np.array([10,20,30])

In [29]: a_3d[:,a_2d_index] = a_1d_fill[:,np.newaxis]

In [30]: a_3d
Out[30]:
array([[[ 0,  0, 10],
        [ 0,  0,  0],
        [ 0, 10, 10]],

       [[ 0,  0, 20],
        [ 0,  0,  0],
        [ 0, 20, 20]],

       [[ 0,  0, 30],
        [ 0,  0,  0],
        [ 0, 30, 30]]])
Run Code Online (Sandbox Code Playgroud)


kma*_*o23 5

也许一点解释和直觉可能会帮助未来的读者更好地理解切片。我(无耻地)使用Stuart Berg 的解决方案来解释用户以获得切片的直观感受。

数组和掩码定义:

In [57]: a_3d        # array with unique numbers for better understanding.
Out[57]: 
array([[[13, 14, 15],
        [23, 24, 25],
        [33, 34, 35]],

       [[ 3,  4,  5],
        [ 6,  7,  8],
        [ 9, 10, 11]],

       [[ 0,  1,  2],
        [30, 31, 32],
        [40, 41, 42]]], dtype=uint8)
Run Code Online (Sandbox Code Playgroud)

将上面的 3D 数组理解为数组的三个切片,3x3最上面的数组有索引0,中心有索引1,底部有索引2

布尔掩码:

In [58]: a_2d_index
Out[58]: 
array([[False, False,  True],
       [False, False, False],
       [False,  True,  True]], dtype=bool)
Run Code Online (Sandbox Code Playgroud)

现在,让我们a_3d使用布尔掩码对数组进行切片a_2d_index

In [68]: a_3d[:, a_2d_index]   # : means apply the mask to all the slices(here 3)
Out[68]: 
array([[15, 34, 35],
       [ 5, 10, 11],
       [ 2, 41, 42]], dtype=uint8)
Run Code Online (Sandbox Code Playgroud)

好的,现在我们得到了上面的结果。为什么以及如何?所以,想象一下:我们采用布尔掩码数组,并将其叠加在a_3d每个切片上的数组上。

现在,只要True掩码中有布尔值,数组中的相应元素a_3d就会(发光?)并为结果数组做出贡献。当我们将掩码放在每个切片上时,每个切片都会发生这种情况(因为我们已经使用了:,所以我们对 array 中的所有切片都这样做a_3d)。

所以耶,切片完成了!现在,我们要分配新值(其中掩码具有布尔值True)。

分配新值:

In [69]: a_1d_fill
Out[69]: array([10, 20, 30])
Run Code Online (Sandbox Code Playgroud)

这是我们拥有的一维数组。但是,掩码是二维数组。因此,我们使用以下方法将其更改为 2Dnp.newaxis

In [70]: a_2d_fill = a_1d_fill[:, np.newaxis]

In [71]: a_2d_fill
Out[71]: 
array([[10],
       [20],
       [30]])


In [73]: a_3d[:, a_2d_index] = a_2d_fill
Run Code Online (Sandbox Code Playgroud)

现在,此分配将值复制10到布尔掩码具有True值的第一个切片中的20索引,然后将值复制到布尔掩码具有值的第二个切片中的索引,True最后将值复制30到布尔掩码具有值的第三个切片中的索引True.

最终结果如下:

In [74]: a_3d
Out[74]: 
array([[[13, 14, 10],
        [23, 24, 25],
        [33, 10, 10]],

       [[ 3,  4, 20],
        [ 6,  7,  8],
        [ 9, 20, 20]],

       [[ 0,  1, 30],
        [30, 31, 32],
        [40, 30, 30]]], dtype=uint8)
Run Code Online (Sandbox Code Playgroud)

呼!那真的很长。因此,简而言之,结果数组应该分别在第一、第二和第三个切片(其中 boolean mask 具有 value )中具有 values 1020、 & 。30True


PS:切片提供原始数组的视图引用。因此,当我们使用切片更改值时,这将影响原始数组。因此,这是一个就地修改。