Numpy数组中的索引混淆问题

15

我对NumPy数组的多维索引逻辑感到非常困惑。以下是示例:

import numpy as np
A = np.arange(18).reshape(3,2,3)
[[[ 0,  1,  2],
  [ 3,  4,  5]],

 [[ 6,  7,  8],
  [ 9, 10, 11]],

 [[12, 13, 14],
  [15, 16, 17]]])

这给了我一个形状为(3,2,3)的数组,假设称它们为(x,y,z)。现在我想要一个数组B,其中包含与x = 0,2 y =0,1和z = 1,2相对应的A中的元素。就像这样:

array([[[ 1,  2],
        [4,  5]],

       [[13, 14],
        [16, 17]]])

一开始我天真地认为

B=A[[0,2],[0,1],[1,2]]

会完成工作。但它会给出

array([  2, 104]) 

并且不起作用。

A[[0,2],:,:][:,:,[1,2]]

这行代码可以完成任务。但我仍然想知道我的第一次尝试有什么问题。以及我想要做到这件事的最佳方式是什么?


我的个人看法是:你们两种方式都会触发Numpy的高级索引。在高级索引上下文中,A[[0,2],[0,1],[1,2]]被解释为“在每个维度上选择每个索引号码(一种有点贪婪的方法)”。 - JP Zhang
3个回答

17
在NumPy中有两种索引方式,基本索引和高级索引。基本索引使用切片元组进行索引,不会复制数组,而是创建一个具有调整过的strides的视图。相比之下,高级索引还使用索引列表或数组,并复制数组。
B = A[[0, 2], [0, 1], [1, 2]]

使用高级索引。在高级索引中,所有索引列表首先会被广播到相同的形状,然后该形状用于输出数组。在这种情况下,它们已经具有相同的形状,因此广播不会产生任何效果。输出数组也将具有这两个条目的形状。输出数组的第一个条目是通过使用三个列表的所有第一个索引获得的,第二个条目是通过使用所有第二个索引获得的:

B = numpy.array([A[0, 0, 1], A[2, 1, 2]])

你的第二种方法

B = A[[0,2],:,:][:,:,[1,2]]

这种方法可以实现,但效率较低。它使用了两次高级索引,因此数据将被复制两次。

要使用高级索引获得实际想要的结果,您可以使用

A[np.ix_([0,2],[0,1],[1,2])]

正如nikow指出的那样。这将仅复制一次数据。

在您的示例中,您可以完全不复制数据,只使用基本索引:

B = A[::2, :, 1:2]

谢谢Sven,但是有没有更好的方法从一个数组中提取非连续(或者不规则间隔)的索引,而不是使用高级索引。(我的例子太简单了,因为我提取的所有索引都是连续的间隔)。 - jonalm
如果您的索引不是均匀间隔的,那么您当然必须使用高级索引。在这种情况下采用的方法是 ix_ 语法,正如 nikow 已经指出的那样。我只想补充一些细节,比如说,对于大型数组来说,您自己的方法效率低下。 - Sven Marnach
非常好的回答,感谢指出我的错误。我应该考虑到高级索引的效率影响。 - nikow

7
我建议阅读以下高级教程,其中解释了各种索引方法:NumPy MedKit 一旦你理解了强大的数组索引方式(以及它们如何组合),它就会变得更加清晰。如果你的第一次尝试是有效的,那么这将与其他索引技术发生冲突(从而减少了在其他用例中的选项)。
在你的示例中,你可以利用第三个索引覆盖的连续范围:
 A[[0,2],:,1:]

你可以使用以下方式:
A[np.ix_([0,2],[0,1],[1,2])]

当后面的索引不连续时,np.ix_非常方便。它只需构造三个索引数组。

正如Sven在他的回答中指出的那样,在这种特定情况下有一种更有效的方法(使用视图而不是复制版本)。

编辑:正如Sven所指出的那样,我的答案包含一些错误,我已将其删除。我仍然认为他的答案更好,但不幸的是我现在无法删除我的答案。


一些说明:
  1. 前两个代码片段不等价--它们产生不同形状的数组。第一行不像第二行那样被解释。
  2. jonalm的解决方案不可取,因为它复制了数组两次。我会在另一个答案中更详细地解释这些问题。
- Sven Marnach

0
A[(0,2),:,1:]

如果你想要

array([[[ 1,  2],
        [ 4,  5]],

       [[13, 14],
        [16, 17]]])

A[你想要的索引,你想要的行数,你想要的列数]


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接