【问题标题】:Index confusion in numpy arraysnumpy数组中的索引混淆
【发布时间】:2011-01-27 10:41:05
【问题描述】:

我真的对具有多个维度的 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,其中 A 中的元素对应于 x = 0,2 y =0,1 和 z = 1,2。喜欢

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]] 被解释为“选择了每个维度中的每个索引号(有点贪婪的方法)。

标签: python arrays numpy


【解决方案1】:

NumPy 中有两种类型的索引basicadvanced。基本索引使用切片元组进行索引,并且不复制数组,而是复制creates a view with adjusted strides。相比之下,高级索引还使用索引列表或数组并复制数组。

你的第一次尝试

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

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

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,但有没有比使用高级索引更好的方法来从数组中提取不连续(或规则间隔)的索引。 (我的例子太简单了,因为我提取的所有索引都是连续间隔的)
  • 如果您的索引没有固定间隔,您当然必须使用高级索引。在这种情况下要走的路是ix_ 语法,正如nikow 已经指出的那样。我只是想添加更多细节,例如您自己的方法对于大型数组效率低下。
  • 很好的答案,感谢您指出我的错误。我应该考虑一下高级索引对效率的影响。
【解决方案2】:

我推荐以下高级教程,它解释了各种索引方法:NumPy MedKit

一旦您了解了索引数组的强大方法(以及它们如何组合),它就会变得有意义。如果您的第一次尝试有效,那么这将与其他一些索引技术发生冲突(减少您在其他用例中的选择)。

在您的示例中,您可以利用第三个索引覆盖一个连续范围:

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

你也可以使用

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

当后面的索引不连续时,这在更一般的情况下很方便。 np.ix_ 简单地构造了三个索引数组。

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

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

【讨论】:

  • 一些评论: 1. 你的前两个代码 sn-ps 是不等价的——它们产生不同形状的数组。第一行 not 像第二行一样被解释。 2. jonalm 的解决方案是不可取的,因为它复制了数组两次。我尝试在另一个答案中更多地解释这些问题。
【解决方案3】:
A[(0,2),:,1:]

如果你愿意

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

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

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

【讨论】:

    猜你喜欢
    • 2015-09-29
    • 2018-12-23
    • 2023-04-03
    • 2018-02-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多