【问题标题】:Unexpected behaviour numpy array indexing [duplicate]意外行为numpy数组索引[重复]
【发布时间】:2019-10-11 10:41:57
【问题描述】:

当以某种意想不到的方式执行特定切片时,numpy 数组的形状正在发生变化

我尝试了几种对同一个数组进行切片的方法,但细微的差异会导致数组形状的不同结果

import numpy as np
z = np.zeros((1,9,10,2))

# This makes sense
print(z[...,[1,0]].shape)
# (1, 9, 10, 2)
print(z[0,...].shape)
# (9, 10, 2)
print(z[0:1,...,[1,0]].shape)
# (1, 9, 10, 2)
print(z[0][...,[1,0]].shape)
# (9, 10, 2)

# This doesn't, I would expect (9, 10, 2) in both cases
print(z[0,:,:,[1,0]].shape)
# (2, 9, 10)
print(z[0,...,[1,0]].shape)
# (2, 9, 10)

在最后两个示例中,我不明白为什么最后一个轴移动到第一个位置。

我正在使用 Python 3.6.4numpy 1.15.1

【问题讨论】:

  • 这是一个混合基本索引和高级索引的情况(请参阅索引文档页面)。当切片(或省略号)位于其他索引的中间时,它会移动到结果的末尾。也有重复的 SO。您已经找到了解决方法。

标签: python numpy numpy-ndarray


【解决方案1】:

您可能会发现最后两种情况的结果出乎意料的原因是因为数组的索引遵循advanced indexing 的规则,即使您也使用切片进行索引。

有关此行为背后的详细说明,您可以查看combining advanced and basic indexing。在最后这些情况下,您会得到意想不到的结果形状。在文档中,您会看到我们可能会获得意外结果的上述场景之一是:

  • 高级索引由切片、省略号或新轴分隔。例如x[arr1, :, arr2]

在您的情况下,尽管您仅使用整数沿第一个轴进行索引,但它是广播的,并且两个数组都被迭代为一个。 在这种情况下,高级索引操作产生的维度首先出现在结果数组中,然后是切片维度。

这里的关键是要理解,正如文档中提到的,这就像连接每个高级索引元素的索引结果

所以本质上它的作用与以下相同:

z = np.random.random((1,9,10,2))
a = np.concatenate([z[0,:,:,[1]], z[0,:,:,[0]]], axis=0)

与上一次索引操作相同:

b = z[0,:,:,[1,0]]
np.allclose(a,b)
# True

这种行为背后的原因是什么?

要记住的一般规则是:

数组索引引入的结果轴位于最前面,除非它们是连续的。

因此,由于此处的索引数组不是连续的,因此使用它们的结果轴将位于前面,而切片维度位于后面。

虽然使用一维数组进行索引可能看起来很奇怪,但请注意,也可以使用任意维数的数组进行索引。假设我们使用 3d 数组在第一个轴和最后一个轴上索引相同的示例数组,都使用形状 (3,4,2)。所以我们知道最终的数组在某个地方也会有形状 (3,4,2),因为两个索引数组都广播到相同的形状。现在的问题是,索引数组之间的完整切片应该放在哪里?

鉴于它应该放在中间不再那么清楚,在这些情况下有一个约定,即切片尺寸放在最后。 所以在这种情况下,我们的任务是重新排列数组的维度以匹配我们的预期输出。在上面的示例中,我们可以做的是交换最后两个轴,并使用swapaxes 来按预期排列尺寸。

【讨论】: