切片对象是 ndarray 元组时的高级整数切片

Advanced Integer slicing when slicing object is an ndarray tuple

我明白了

x=np.array([[1, 2], [3, 4], [5, 6]] 
y = x[[0,1,2], [0,1,0]] 

输出给出 y= [1 4 5] 这只是将第一个列表作为行和秒列表和列。

但是下面是如何工作的?

x = np.array([[ 0,  1,  2],[ 3,  4,  5],[ 6,  7,  8],[ 9, 10, 11]]) 

rows = np.array([[0,0],[3,3]])
cols = np.array([[0,2],[0,2]]) 
y = x[rows,cols] 

这给出了输出:

[[ 0  2]                                                                      
 [ 9 11]] 

能否请您解释一下使用ndarrays作为切片对象时的逻辑?为什么它的行和列都有一个二维数组。当切片对象是 ndarray 而不是 python 列表时,规则有何不同?

理解这一点的最简单方法是以下观察:输出的形状由索引数组的形状决定,或者更准确地说,由将所有索引数组一起广播所产生的形状决定。

这样看:你有一个给定形状的数组 A 和另一个形状的数组 V,你想用 A 中的值填充 V。你需要指定什么?那么,对于 A 中的每个位置,您需要指定 V 中某些元素的坐标。因此,如果 V 是 ND,则需要 N 个与 A 形状相同或至少可广播的索引数组。然后通过将这些索引数组放在它们在 [] 表达式中的坐标位置来索引 V

为简单起见,我们将保持二维并假设 rows.shape = cols.shape。 (你可以通过广播打破这个规则,但现在我们不会)。我们称这个形状为 (I, J)

那么 y = x[rows, cols] 等同于:

y = np.empty((I, J))
for i in range(I):
    for j in range(J):
        y[i, j] = x[rows[i, j], cols[i, j]]

我们有以下数组 x

x = np.array([[1, 2], [3, 4], [5, 6]] 

索引 [0, 1, 2][0, 1, 0] 索引到 x 时就像

x[[0,1,2], [0,1,0]] 

给出

[1,  4,  5]

我们使用的索引基本上转化为:

[0, 1, 2] & [0, 1, 0] --> [0,0], [1,1], [2,0]

因为我们使用一维列表作为索引,所以我们得到一维数组作为结果。


有了这些知识,让我们看看下一个案例。现在,我们将数组 x 设为:

x = np.array([[ 0,  1,  2],[ 3,  4,  5],[ 6,  7,  8],[ 9, 10, 11]]) 

现在索引是二维数组。

rows = np.array([[0,0],[3,3]])
cols = np.array([[0,2],[0,2]]) 

索引到数组 x 时,如:

x[rows,cols] 

简单翻译为:

[[0,0],[3,3]]
  | |   | |      ====> [[0,0]], [[0,2]], [[3,0]], [[3,2]]
[[0,2],[0,2]]

现在,很容易观察到这 4 个 list of list 在索引到数组 x 时如何给出以下结果(即这里只是 returns 来自数组 x 的角元素 ):

[[ 0,  2]                                                                      
 [ 9, 11]]

请注意,在这种情况下,我们得到的结果是二维数组(与第一种情况下的一维数组相反),因为我们的索引 rowscolumns 本身是二维数组(即等效list of list) 而在第一种情况下,我们的索引是一维数组(或者等效地简单 list 没有任何嵌套)。

因此,如果您需要二维数组作为结果,则需要将二维数组作为索引。