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

时间:2017-03-18 15:27:50

标签: arrays numpy indexing

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

给出了什么:

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

a_3d = np.zeros((3,3,3))

2d索引数组:

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

将值放入x,y位置的3d数组中:

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

现在,我想使用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]]]

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

2 个答案:

答案 0 :(得分:4)

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

答案 1 :(得分:3)

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

阵列&面具定义:

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)

将上述3D数组理解为三个3x3数组,其中最顶层的数组具有索引0,中间一个数据库具有索引1,而下一个数组具有索引{{1} }}

布尔掩码:

2

现在,让我们使用布尔掩码In [58]: a_2d_index Out[58]: array([[False, False, True], [False, False, False], [False, True, True]], dtype=bool)

对数组a_3d进行切片
a_2d_index

好的,现在我们得到了上述结果。为什么以及如何?所以,想象一下:我们采用boolean-mask数组,只在每个切片上叠加数组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)

现在,无论掩码中的布尔值为a_3d,数组True中的对应元素都会(发光?)并对结果数组有贡献。当我们将掩码放在每个切片上时,每个切片都会发生这种情况(因为我们已使用a_3d,我们对数组:中的所有切片执行此操作。)

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

分配新值:

True

这是我们拥有的1D阵列。但是,掩模是2D阵列。因此,我们使用In [69]: a_1d_fill Out[69]: array([10, 20, 30])

将其更改为2D
np.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 复制到布尔掩码具有10值的第一个切片中的索引,然后将值True复制到布尔值的第二个切片中的索引mask具有值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) 10和&第一个,第二个和第三个切片中的20(布尔掩码的值分别为30)。

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