也许一点解释和直觉会帮助未来读者更好地理解切片。我(无耻地)使用
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)
将上述三维数组看作是三个大小为
3x3
的数组,其中最上面的数组索引为
0
,中间的数组索引为
1
,最下面的数组索引为
2
。
布尔掩码:
In [58]: a_2d_index
Out[58]:
array([[False, False, True],
[False, False, False],
[False, True, True]], dtype=bool)
现在,让我们使用布尔掩码
a_2d_index
来切片数组
a_3d
。
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
)。
分配新值:
In [69]: a_1d_fill
Out[69]: array([10, 20, 30])
这是我们拥有的一维数组。但是,掩码是二维数组。因此,我们使用
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
的索引处,然后将值
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
(其中布尔掩码的值为True
)。
P.S.:切片提供了原始数组的视图或引用。因此,当我们使用切片更改值时,这将影响原始数组。因此,这是一种原地修改。
a_4d_array[2, :, a_2d_index] = a_1d_fill[:, np.newaxis]
在我的脚本中失败了,因为形状不匹配。 - Christiana_4d_array[2, :, idx]
是(棘手的)基本和高级索引混合的情况,https://docs.scipy.org/doc/numpy/reference/arrays.indexing.html#combining-advanced-and-basic-indexing。它的形状与您预期的相反,首先是`idx`形状,最后是切片形状的转置。 - hpaulj