用List索引Numpy数组:arr[:][li]与arr[:,li]的区别



如何解释以下行为:

import numpy as np    
arr = np.zeros((3, 3))
li = [1,2]
print('output1:', arr[:, li].shape)
print('output2:', arr[:][li].shape)
>>output1: (3, 2)
>>output2: (2, 3)

我希望output2等于output1。

让我们使用一个不同的数组,这样更容易看到差异:

>>> arr = np.arange(9).reshape(3, 3)
>>> arr
array([[0, 1, 2],
[3, 4, 5],
[6, 7, 8]])

第一种情况arr[:, li]将选择第一个维度的所有元素(在这种情况下是所有行),然后用[1, 2]对数组进行索引,这意味着只省略第一列:

array([[1, 2],
[4, 5],
[7, 8]])

因此,它的形状为(3,2)。

另一种情况arr[:]将复制原始数组,因此它不会改变形状,因此它相当于arr[li],因此输出形状为(2, 3)。一般来说,你应该避免对数组进行双索引,因为那样可能会创建两次视图,效率很低。

您正在得到正确的输出。

第一行

print('output1:', arr[:, li].shape)

您正在打印arr中每个子数组的2nd3rd元素,从而获得每个包含2值的3元素。

第二行

print('output2:', arr[:][li].shape)

您首先选择整个数组,然后从整个数组中选择2nd3rd元素(每个元素本身包含3元素),从而获得每个包含3值的2元素。

如果检查这段代码,可以看到差异-

import numpy as np    
arr = np.arange(9).reshape(3, 3)
li = [1,2]
print('output1:', arr[:, li])
print('output2:', arr[:][li])

给出-

[[1 2]
[4 5]
[7 8]]

[[3 4 5]
[6 7 8]]

当你做arr[:, [1, 2]]时,你说的是你想要取数组的所有行(:指定了这一点),并从中取[1, 2]列。

另一方面,当您执行arr[:]时,您首先引用整个数组。

实际上,在第二种情况下,[1 2]指向原始数组的行轴,而在第一种情况下,它指向列。