如何对ndarray进行索引#

如何对 ndarray 进行索引#

另请参阅

ndarray 的索引

本页介绍了常见示例。有关索引的深入了解,请参阅 ndarray 的索引。

访问特定/任意行和列#

使用 基本索引 功能,例如 切片和步长 以及 维度索引工具。

>>> a = np.arange(30).reshape(2, 3, 5)

>>> a

array([[[ 0, 1, 2, 3, 4],

[ 5, 6, 7, 8, 9],

[10, 11, 12, 13, 14]],

[[15, 16, 17, 18, 19],

[20, 21, 22, 23, 24],

[25, 26, 27, 28, 29]]])

>>> a[0, 2, :]

array([10, 11, 12, 13, 14])

>>> a[0, :, 3]

array([ 3, 8, 13])

请注意,索引操作的输出形状可能与原始对象不同。若要在索引后保留原始维度,可以使用 newaxis。要使用其他此类工具,请参阅 维度索引工具。

>>> a[0, :, 3].shape

(3,)

>>> a[0, :, 3, np.newaxis].shape

(3, 1)

>>> a[0, :, 3, np.newaxis, np.newaxis].shape

(3, 1, 1)

变量也可用于索引

>>> y = 0

>>> a[y, :, y+3]

array([ 3, 8, 13])

请参阅 在程序中处理可变数量的索引,了解如何在索引变量中使用 切片 (slice) 和 省略号 (Ellipsis)。

索引列#

要索引列,必须对最后一个轴进行索引。使用 维度索引工具 来获得所需的维度数量。

>>> a = np.arange(24).reshape(2, 3, 4)

>>> a

array([[[ 0, 1, 2, 3],

[ 4, 5, 6, 7],

[ 8, 9, 10, 11]],

[[12, 13, 14, 15],

[16, 17, 18, 19],

[20, 21, 22, 23]]])

>>> a[..., 3]

array([[ 3, 7, 11],

[15, 19, 23]])

要索引每一列中的特定元素,请按如下方式利用 高级索引。

>>> arr = np.arange(3*4).reshape(3, 4)

>>> arr

array([[ 0, 1, 2, 3],

[ 4, 5, 6, 7],

[ 8, 9, 10, 11]])

>>> column_indices = [[1, 3], [0, 2], [2, 2]]

>>> np.arange(arr.shape[0])

array([0, 1, 2])

>>> row_indices = np.arange(arr.shape[0])[:, np.newaxis]

>>> row_indices

array([[0],

[1],

[2]])

使用 row_indices 和 column_indices 进行高级索引。

>>> arr[row_indices, column_indices]

array([[ 1, 3],

[ 4, 6],

[10, 10]])

沿特定轴索引#

使用 take。另请参阅 take_along_axis 和 put_along_axis。

>>> a = np.arange(30).reshape(2, 3, 5)

>>> a

array([[[ 0, 1, 2, 3, 4],

[ 5, 6, 7, 8, 9],

[10, 11, 12, 13, 14]],

[[15, 16, 17, 18, 19],

[20, 21, 22, 23, 24],

[25, 26, 27, 28, 29]]])

>>> np.take(a, [2, 3], axis=2)

array([[[ 2, 3],

[ 7, 8],

[12, 13]],

[[17, 18],

[22, 23],

[27, 28]]])

>>> np.take(a, [2], axis=1)

array([[[10, 11, 12, 13, 14]],

[[25, 26, 27, 28, 29]]])

创建大型矩阵的子集#

使用 切片和步长 来访问大数组的片段。

>>> a = np.arange(100).reshape(10, 10)

>>> a

array([[ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9],

[10, 11, 12, 13, 14, 15, 16, 17, 18, 19],

[20, 21, 22, 23, 24, 25, 26, 27, 28, 29],

[30, 31, 32, 33, 34, 35, 36, 37, 38, 39],

[40, 41, 42, 43, 44, 45, 46, 47, 48, 49],

[50, 51, 52, 53, 54, 55, 56, 57, 58, 59],

[60, 61, 62, 63, 64, 65, 66, 67, 68, 69],

[70, 71, 72, 73, 74, 75, 76, 77, 78, 79],

[80, 81, 82, 83, 84, 85, 86, 87, 88, 89],

[90, 91, 92, 93, 94, 95, 96, 97, 98, 99]])

>>> a[2:5, 2:5]

array([[22, 23, 24],

[32, 33, 34],

[42, 43, 44]])

>>> a[2:5, 1:3]

array([[21, 22],

[31, 32],

[41, 42]])

>>> a[:5, :5]

array([[ 0, 1, 2, 3, 4],

[10, 11, 12, 13, 14],

[20, 21, 22, 23, 24],

[30, 31, 32, 33, 34],

[40, 41, 42, 43, 44]])

同样的操作可以通过稍微复杂一点的高级索引来完成。请记住,高级索引会创建副本。

>>> a[np.arange(5)[:, None], np.arange(5)[None, :]]

array([[ 0, 1, 2, 3, 4],

[10, 11, 12, 13, 14],

[20, 21, 22, 23, 24],

[30, 31, 32, 33, 34],

[40, 41, 42, 43, 44]])

您还可以使用 mgrid 来生成索引。

>>> indices = np.mgrid[0:6:2]

>>> indices

array([0, 2, 4])

>>> a[:, indices]

array([[ 0, 2, 4],

[10, 12, 14],

[20, 22, 24],

[30, 32, 34],

[40, 42, 44],

[50, 52, 54],

[60, 62, 64],

[70, 72, 74],

[80, 82, 84],

[90, 92, 94]])

过滤值#

非零元素#

使用 nonzero 获取一个元组,其中包含对应于每个维度的非零元素数组索引。

>>> z = np.array([[1, 2, 3, 0], [0, 0, 5, 3], [4, 6, 0, 0]])

>>> z

array([[1, 2, 3, 0],

[0, 0, 5, 3],

[4, 6, 0, 0]])

>>> np.nonzero(z)

(array([0, 0, 0, 1, 1, 2, 2]), array([0, 1, 2, 2, 3, 0, 1]))

使用 flatnonzero 获取扁平化后的 ndarray 中非零元素的索引。

>>> np.flatnonzero(z)

array([0, 1, 2, 6, 7, 8, 9])

任意条件#

使用 where 根据条件生成索引,然后使用 高级索引。

>>> a = np.arange(30).reshape(2, 3, 5)

>>> indices = np.where(a % 2 == 0)

>>> indices

(array([0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1]),

array([0, 0, 0, 1, 1, 2, 2, 2, 0, 0, 1, 1, 1, 2, 2]),

array([0, 2, 4, 1, 3, 0, 2, 4, 1, 3, 0, 2, 4, 1, 3]))

>>> a[indices]

array([ 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28])

或者,使用 布尔数组索引。

>>> a > 14

array([[[False, False, False, False, False],

[False, False, False, False, False],

[False, False, False, False, False]],

[[ True, True, True, True, True],

[ True, True, True, True, True],

[ True, True, True, True, True]]])

>>> a[a > 14]

array([15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29])

过滤后替换值#

使用带有过滤条件的赋值来替换所需的值。

>>> p = np.arange(-10, 10).reshape(2, 2, 5)

>>> p

array([[[-10, -9, -8, -7, -6],

[ -5, -4, -3, -2, -1]],

[[ 0, 1, 2, 3, 4],

[ 5, 6, 7, 8, 9]]])

>>> q = p < 0

>>> q

array([[[ True, True, True, True, True],

[ True, True, True, True, True]],

[[False, False, False, False, False],

[False, False, False, False, False]]])

>>> p[q] = 0

>>> p

array([[[0, 0, 0, 0, 0],

[0, 0, 0, 0, 0]],

[[0, 1, 2, 3, 4],

[5, 6, 7, 8, 9]]])

获取最大值/最小值的索引#

使用 argmax 和 argmin。

>>> a = np.arange(30).reshape(2, 3, 5)

>>> np.argmax(a)

29

>>> np.argmin(a)

0

使用 axis 关键字获取沿特定轴的最大值和最小值的索引。

>>> np.argmax(a, axis=0)

array([[1, 1, 1, 1, 1],

[1, 1, 1, 1, 1],

[1, 1, 1, 1, 1]])

>>> np.argmax(a, axis=1)

array([[2, 2, 2, 2, 2],

[2, 2, 2, 2, 2]])

>>> np.argmax(a, axis=2)

array([[4, 4, 4],

[4, 4, 4]])

>>> np.argmin(a, axis=1)

array([[0, 0, 0, 0, 0],

[0, 0, 0, 0, 0]])

>>> np.argmin(a, axis=2)

array([[0, 0, 0],

[0, 0, 0]])

将 keepdims 设置为 True,以在结果中保留被归约的轴,使其成为大小为 1 的维度。

>>> np.argmin(a, axis=2, keepdims=True)

array([[[0],

[0],

[0]],

[[0],

[0],

[0]]])

>>> np.argmax(a, axis=1, keepdims=True)

array([[[2, 2, 2, 2, 2]],

[[2, 2, 2, 2, 2]]])

要获取 N 维数组中每个 (N-1) 维数组的最大值或最小值索引,请使用 reshape 将数组重塑为 2D 数组,沿 axis=1 应用 argmax 或 argmin,并使用 unravel_index 恢复每个切片的值索引。

>>> x = np.arange(2*2*3).reshape(2, 2, 3) % 7 # 3D example array

>>> x

array([[[0, 1, 2],

[3, 4, 5]],

[[6, 0, 1],

[2, 3, 4]]])

>>> x_2d = np.reshape(x, (x.shape[0], -1))

>>> indices_2d = np.argmax(x_2d, axis=1)

>>> indices_2d

array([5, 0])

>>> np.unravel_index(indices_2d, x.shape[1:])

(array([1, 0]), array([2, 0]))

返回的第一个数组包含原始数组中沿轴 1 的索引,第二个数组包含沿轴 2 的索引。因此,x[0] 中的最大值即为 x[0, 1, 2]。

高效地多次索引同一个 ndarray#

必须记住,基本索引会产生 视图 (views),而高级索引会产生 副本 (copies),后者的计算效率较低。因此,应尽可能使用基本索引,而非高级索引。

进一步阅读#

Nicolas Rougier 的 100 个 NumPy 练习 很好地展示了索引如何与其他操作相结合。练习 6, 8, 10, 15, 16, 19, 20, 45, 59, 64, 65, 70, 71, 72, 76, 80, 81, 84, 87, 90, 93, 94 均特别关注了索引。

[an error occurred while processing the directive]