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

Kos*_*Kos 6 python indexing numpy

受到另一个问题的启发,我试图将我的思想包含在NumPy中的高级索引中,并建立更直观的理解它的工作原理.

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

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

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

>>> y[4]
4
Run Code Online (Sandbox Code Playgroud)

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

>>> idx = [4, 3, 2, 1]
>>> y[idx]
array([4, 3, 2, 1])
Run Code Online (Sandbox Code Playgroud)

所以,如果我用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
Run Code Online (Sandbox Code Playgroud)

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

>>> idx = [[[4, 3], [2, 1]]]
>>> y[idx]
array([[4, 3],
       [2, 1]])
Run Code Online (Sandbox Code Playgroud)

是什么让numpy表现得这样?

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

>>> idx = np.array([[4, 3], [2, 1]])
>>> y[idx]
array([[4, 3],
       [2, 1]])
Run Code Online (Sandbox Code Playgroud)

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

MSe*_*ert 3

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

\n

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

\n

通过添加另一个列表,您确实告诉 NumPy 您想要沿第一个维度进行切片,因为最外面的列表被有效地解释为好像您只传递了一个“第一个维度的索引列表”:arr[[[[4, 3], [2, 1]]]]

\n

文档中:

\n
\n

例子

\n

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

\n
>>> x = np.array([[1, 2], [3, 4], [5, 6]])\n>>> x[[0, 1, 2], [0, 1, 0]]\narray([1, 4, 5])\n
Run Code Online (Sandbox Code Playgroud)\n
\n

\n
\n

警告

\n

高级索引的定义意味着它x[(1,2,3),]x[(1,2,3)]. 后者相当于x[1,2,3]触发基本选择,而前者则触发高级索引。请务必了解为什么会发生这种情况。

\n
\n

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

\n
>>> y.take([[4, 3], [2, 1]])  # 2D array\narray([[4, 3],\n       [2, 1]])\n
Run Code Online (Sandbox Code Playgroud)\n
\n

此函数 [ np.take] 与 \xe2\x80\x9cfancy\xe2\x80\x9d 索引(使用数组索引数组)执行相同的操作;但是,如果您需要沿给定轴的元素,它会更容易使用。

\n
\n

或者将索引转换为数组。这样,NumPy 将其解释array为奇特索引(特殊情况!),而不是“多维索引”:

\n
>>> y[np.asarray([[4, 3], [2, 1]])]\narray([[4, 3],\n       [2, 1]])\n
Run Code Online (Sandbox Code Playgroud)\n