使用numpy中的列表和数组进行索引似乎不一致

时间:2017-09-08 12:58:54

标签: python numpy indexing

受到this other question的启发,我试图将我的思绪包裹在NumPy中advanced indexing,并对其工作方式有更直观的理解。

我发现了一个有趣的案例。这是一个数组:

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

如果我将其标记为标量,我当然会得到一个标量:

>>> y[4]
4

使用1D整数数组,我得到另一个1D数组:

>>> idx = [4, 3, 2, 1]
>>> y[idx]
array([4, 3, 2, 1])

所以,如果我用2D整数数组对它进行索引,我得到......我得到了什么?

>>> idx = [[4, 3], [2, 1]]
>>> y[idx]
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IndexError: too many indices for array

哦不!对称性被打破了。我必须用3D数组索引才能获得2D数组!

>>> idx = [[[4, 3], [2, 1]]]
>>> y[idx]
array([[4, 3],
       [2, 1]])

是什么让numpy以这种方式表现?

为了使这个更有趣,我注意到使用numpy数组(而不是列表)的索引表现我的直觉期望,2D给我2D:

>>> idx = np.array([[4, 3], [2, 1]])
>>> y[idx]
array([[4, 3],
       [2, 1]])

这与我所处的地方看起来不一致。这里的规则是什么?

1 个答案:

答案 0 :(得分:2)

原因是将列表解释为numpy数组的索引:列表被解释为元组,带有元组的索引被NumPy解释为多维索引。

就像arr[1, 2]返回元素arr[1][2]一样,arr[[[4, 3], [2, 1]]]arr[[4, 3], [2, 1]]相同,并且根据多维索引规则返回元素arr[4, 2]arr[3, 1]

通过添加一个列表,您可以告诉NumPy您希望沿第一个维度进行切片,因为最外面的列表被有效地解释为您只传入了第一个维度的一个&#34;索引列表&#34;: arr[[[[4, 3], [2, 1]]]]

来自documentation

  

实施例

     

从每一行开始,应选择一个特定元素。行索引只是[0,1,2],列索引指定要为相应行选择的元素,此处为[0,1,0]。将两者结合使用可以使用高级索引解决任务:

>>> x = np.array([[1, 2], [3, 4], [5, 6]])
>>> x[[0, 1, 2], [0, 1, 0]]
array([1, 4, 5])

and

  

警告

     

高级索引的定义意味着x[(1,2,3),]x[(1,2,3)]根本不同。后者等同于x[1,2,3],它将触发基本选择,而前者将触发高级索引。一定要明白为什么会这样。

在这种情况下,最好使用np.take

>>> y.take([[4, 3], [2, 1]])  # 2D array
array([[4, 3],
       [2, 1]])
  

这个函数[np.take]与“花式”索引(使用数组索引数组)做同样的事情;但是,如果您需要沿给定轴的元素,则可以更容易使用。

或者将索引转换为数组。就这样NumPy解释它(array是特殊的!)作为花哨的索引,而不是&#34;多维索引&#34;:

>>> y[np.asarray([[4, 3], [2, 1]])]
array([[4, 3],
       [2, 1]])