首页 > 解决方案 > 使用多个元组进行 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

标签: pythonnumpyarray-broadcastingnumpy-slicing

解决方案


如果您想实现以编程方式对数组进行切片的能力,答案是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]]]

推荐阅读