NumPy ndarray 中混合基本索引和高级索引获得的数组形状

问题描述 投票:0回答:1

这是代码:

import numpy as np

x = np.arange(2*32*32*8*16)
x = x.reshape(2, 32, 32, 8, 16)

print("x-shape=", x.shape)

y = x[0, 3:5, 8:10, [1, 2, 3, 4, 5], :]
z = x[0][3:5, 8:10, [1, 2, 3, 4, 5], :]

print("y-shape=", y.shape)
print("z-shape=", z.shape)

和输出:

x-shape= (2, 32, 32, 8, 16)
y-shape= (5, 2, 2, 16)
z-shape= (2, 2, 5, 16)

我希望数组 y 和 z 的形状相等,但事实并非如此。我需要的其实是z的形状。
有人可以解释或指出我的标准吗?
谢谢!

python arrays numpy indexing slice
1个回答
0
投票

请参阅有关索引的 numpy 文档

单元素索引的工作方式与其他标准 Python 序列的工作方式完全相同。它从 0 开始,并接受从数组末尾开始索引的负索引。 [...] 请注意,如果索引索引数少于维度的多维数组,则会得到一个亚维数组。

因此

x[0]
得到
x
的第一个多维子数组。
x[0]
将具有形状
(32, 32, 8, 16)
。然后,使用多维切片再次对其进行切片,切片的数量与维度相同。您将获得一个维度相同的数组,其中所有维度都已被切片:
[3:5, 8:10, [1, 2, 3, 4, 5], :]
将前 32 个投影到 2 (5 - 3),第二个 32 也投影到 2 (10 - 8),将 8 个投影到 5 (选择索引 1 - 5),并将 16 保留为 16 (
:
)。你得到
(2, 2, 5, 16)

这里可能让您感到困惑的是,高级索引规则(更糟糕的是,您正在结合高级和基本索引),因为您的其中一个切片是

[1, 2, 3, 4, 5]
。因此 numpy 不会创建视图,而是创建副本。如果您使用正确的切片
1:6
,则高级索引将不适用,并且
y.shape
将按预期为
(2, 2, 5, 16)

原因是视图(“胖指针”)和高级索引之间存在根本区别:使用高级索引时,不必使用具有恒定差异(算术级数)的连续范围。您可以使用质数、您最喜欢的数字等进行索引。因此,一个由指针和形状组成的简单视图(它告诉您当您在每个方向上移动 1 时如何移动指针以及数组的结束位置)是不够的。

numpy
实际上需要遍历索引列表并选择所需的索引,创建一个新数组。

© www.soinside.com 2019 - 2024. All rights reserved.