请有人解释这三个索引操作之间的区别:
y = np.arange(35).reshape(5,7)
# Operation 1
y[np.array([0,2,4]),1:3]
# Operation 2
y[np.array([0,2,4]), np.array([[1,2]])]
# Operation 3
y[np.array([0,2,4]), np.array([[1],[2]])]
我得不到的是:
根据numpy参考:
如果索引数组的形状不同,则尝试进行 将它们播放到相同的形状。如果他们不能广播到 相同的形状,提出异常。
好的,这意味着我做不到:
y[np.array([0,2,4]), np.array([1,2])]
但是numpy参考文献也谈到了操作1:
实际上,切片被转换为索引数组np.array([[1,2]]) (形状(1,2))与索引数组一起广播以产生a 结果形状阵列(3,2)。
为什么我不能这样做:
y[np.array([0,2,4]), np.array([[1,2]])]
我收到错误:
IndexError:形状不匹配:索引数组无法与形状一起广播(3,)(1,2)
答案 0 :(得分:1)
In [1]: import numpy as np; y = np.arange(35).reshape(5,7)
In [2]: y[np.array([0,2,4]), 1:3]
Out[2]:
array([[ 1, 2],
[15, 16],
[29, 30]])
这里我们混合了高级索引(使用数组)和基本索引(使用切片),只有一个高级索引。根据{{3}}
[a]单个高级索引可以替换切片和结果 数组将是相同的[...]
这是正确的,如下面的代码所示:
In [3]: y[::2, 1:3]
Out[3]:
array([[ 1, 2],
[15, 16],
[29, 30]])
Out[2]
和Out[3]
之间的唯一区别是前者是y
中的数据副本(高级索引始终生成副本),而后者是共享与y
相同的内存(基本索引仅生成视图)。
因此,在操作1中,我们通过np.array([0,2,4])
选择了行,并通过1:3
选择了列。
In [4]: y[np.array([0,2,4]), np.array([[1,2]])]
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-4-bf9ee1361144> in <module>()
----> 1 y[np.array([0,2,4]), np.array([[1,2]])]
IndexError: shape mismatch: indexing arrays could not be broadcast together with shapes (3,) (1,2)
这失败了,并且理解为什么我们首先必须意识到这个例子中索引的本质与操作1根本不同。现在我们只有高级索引(并且只有一个高级索引)。这意味着索引数组必须具有相同的形状或至少与reference兼容的形状。让我们来看看形状。
In [5]: np.array([0,2,4]).shape
Out[5]: (3,)
In [6]: np.array([[1,2]]).shape
Out[6]: (1, 2)
这意味着广播机制将尝试将这两个数组合并:
np.array([0,2,4]) (1d array): 3
np.array([[1,2]]) (2d array): 1 x 2
Result (2d array): 1 x F
最后一行末尾的F
表示形状不兼容。这就是IndexError
操作2的原因。
In [7]: y[np.array([0,2,4]), np.array([[1],[2]])]
Out[7]:
array([[ 1, 15, 29],
[ 2, 16, 30]])
同样,我们只有高级索引。让我们看看这些形状现在是否兼容:
In [8]: np.array([0,2,4]).shape
Out[8]: (3,)
In [9]: np.array([[1],[2]]).shape
Out[9]: (2, 1)
这意味着广播将如下工作:
np.array([0,2,4]) (1d array): 3
np.array([[1],[2]]) (2d array): 2 x 1
Result (2d array): 2 x 3
所以现在广播工作!由于我们的索引数组被广播到2x3数组,因此这也将是结果的形状。因此,它也解释了结果的形状与操作1的形状不同。
要获得形状3x2的结果,如操作1,我们可以
In [10]: y[np.array([[0],[2],[4]]), np.array([1, 2])]
Out[10]:
array([[ 1, 2],
[15, 16],
[29, 30]])
现在广播机制的工作原理如下:
np.array([[0],[2],[4]]) (2d array): 3 x 1
np.array([1, 2]) (1d array): 2
Result (2d array): 3 x 2
给出3x2阵列。而不是np.array([1, 2])
In [11]: y[np.array([[0],[2],[4]]), np.array([[1, 2]])]
Out[11]:
array([[ 1, 2],
[15, 16],
[29, 30]])
会因为
而起作用np.array([[0],[2],[4]]) (2d array): 3 x 1
np.array([[1, 2]]) (2d array): 1 x 2
Result (2d array): 3 x 2