我真的对具有多个维度的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]]
完成这项工作。但我仍然想知道我的第一次尝试是否有错。什么是做我想做的最好的方式?
答案 0 :(得分:17)
NumPy basic和advanced中有两种类型的索引。基本索引使用切片元组进行索引,并且不复制数组,而是复制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]
答案 1 :(得分:7)
我推荐以下高级教程,它解释了各种索引方法:NumPy MedKit
一旦你理解了索引数组的强大方法(以及它们如何组合),它就会有意义。如果您的第一次尝试有效,那么这将与其他一些索引技术相冲突(减少您在其他用例中的选项)。
在您的示例中,您可以利用第三个索引涵盖连续范围:
A[[0,2],:,1:]
您也可以使用
A[np.ix_([0,2],[0,1],[1,2])]
在更一般的情况下,当后面的指数不连续时,这是很方便的。 np.ix_
只构造三个索引数组。
正如Sven在他的回答中所指出的,在这种特定情况下有一种更有效的方法(使用视图而不是复制版本)。
编辑:正如Sven所指出的,我的回答包含一些错误,我已将其删除。我仍然认为他的答案更好,但不幸的是我现在不能删除我的。
答案 2 :(得分:0)
A[(0,2),:,1:]
如果你想
array([[[ 1, 2],
[ 4, 5]],
[[13, 14],
[16, 17]]])
A [你想要的指数,你想要的行,你想要的颜色]