python - 使用多个元组进行 NumPy 切片
问题描述
考虑以下:
import numpy as np
arr = np.arange(3 * 4 * 5).reshape((3, 4, 5))
arr
如果我使用s切片slice
,我会得到,例如:
arr[:, 0:2, :].shape
# (3, 2, 5)
如果现在我使用 和 的混合物进行切片,arr
我得到:slice()
tuple()
arr[:, (0, 1), :].shape
# (3, 2, 5)
np.all(arr[:, (0, 1), :] == arr[:, :2, :])
# True
和:
arr[:, :, (0, 1)].shape
# (3, 4, 2)
np.all(arr[:, :, (0, 1)] == arr[:, :, :2])
# True
但是,如果我这样做:
arr[:, (0, 1), (0, 1)].shape
# (3, 2)
这基本上是串联的arr[:, 0, 0]
。arr[:, 1, 1]
我期待得到:
arr[:, (0, 1), (0, 1)].shape
# (3, 2, 2)
np.all(arr[:, (0, 1), (0, 1)] == arr[:, :2, :2])
# True
但显然不是这样。
如果我连接两个单独的切片,我将能够获得所需的结果,即:
arr[:, (0, 1), :][:, :, (0, 1)].shape
# (3, 2, 2)
np.all(arr[:, (0, 1), :][:, :, (0, 1)] == arr[:, :2, :2])
# True
是否可以获得与arr[:, (0, 1), :][:, :, (0, 1)]
但使用单个切片相同的结果?
现在,这个例子没那么有趣了,因为我可以tuple()
用 a代替slice()
,但如果这不是真的,这一切都变得更加相关,例如:
arr[:, (0, 2, 3), :][:, :, (0, 2, 3, 4)]
# [[[ 0 2 3 4]
# [10 12 13 14]
# [15 17 18 19]]
# [[20 22 23 24]
# [30 32 33 34]
# [35 37 38 39]]
# [[40 42 43 44]
# [50 52 53 54]
# [55 57 58 59]]]
这arr[:, (0, 2, 3), (0, 2, 3, 4)]
将是一种更方便的语法。
编辑
@Divakar @hpaulj 和 @MadPhysicist 评论/答案指向正确广播的 Iterable 等效于多个连接切片。
但是,情况并非如此,例如:
s = np.ix_((0, 1), (0, 1, 2, 3))
arr[s[0], slice(3), s[1]]
# [[[ 0 5 10]
# [ 1 6 11]
# [ 2 7 12]
# [ 3 8 13]]
#
# [[20 25 30]
# [21 26 31]
# [22 27 32]
# [23 28 33]]]
但:
arr[(0, 1), :, :][:, :3, :][:, :, (0, 1, 2, 3)]
# [[[ 0 1 2 3]
# [ 5 6 7 8]
# [10 11 12 13]]
#
# [[20 21 22 23]
# [25 26 27 28]
# [30 31 32 33]]]
和:
np.all(arr[:2, :3, :4] == arr[(0, 1), :, :][:, :3, :][:, :, (0, 1, 2, 3)])
# True
np.all(arr[s[0], slice(3), s[1]] == arr[(0, 1), :, :][:, :3, :][:, :, (0, 1, 2, 3)])
# False
解决方案
如果您想实现以编程方式对数组进行切片的能力,答案是slice
对象,而不是索引序列。例如,:2
变为slice(None, 2)
:
np.all(arr[:, slice(None, 2), slice(None, 2)] == arr[:, :2, :2])
切片选择轴的一部分。索引数组不会:它们选择单个元素。在这种情况下,索引的形状决定了输出的形状。
如果要跨多个维度选择任意索引,则索引数组的形状必须与所需输出的形状相同,或者向其广播:
arr[:, [[0], [2], [3]], [[0, 2, 3, 4]]]
推荐阅读
- python - 如何在给定 MultiIndex 对象的情况下更改 pandas DataFrame 层次索引的值
- python - 检查变量字符串是否与列表中的元素匹配
- scala - Scala中的Spark - 带有额外参数的函数映射
- kubernetes - 如何声明一长串端口(以千计)?(超过 262144 个字符)
- .net - .Net MVC 如何将 Web 应用程序拆分为 2 个服务器架构(Web 和应用程序服务器)?
- r - degree symbol incorrect in map axis labels
- ubuntu - 无法卸载 snap 包
- javascript - 如何使用 JQuery 和输出文本获取 JSON URL
- python - 删除满足条件的行的函数
- sql - 如何在oracle查询中识别主键表和外键表列数据类型和数据长度的差异