跳转至

Np 数组索引

语法

array[d1(, d2, d3...)]
  • d1 :第 1 维的索引
  • 可以省略截止到某一维后的索引,如对 2 维数组 a[2] 表示第 1 行

具体到 2 维数组中:(以下均以 2 维数组 a 为例)

array[row, col]
  • row:行的索引。
  • col:列的索引。
  • 行坐标(第 1 维)不可空白:如需省略,用无限制切片 : 表示 任何行,如索引列时 a[:, 2](返回一维数组)或 a[:, 1:2] / a[:, [1]] (返回 1 列的二维数组)。

坐标索引(基本)

某个索引(row / col) 可以是单个 数字 n,表示 第 n 行(列)。如 a[1]a[1, 2]

1
2
3
4
5
6
7
8
a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
# 行1
print(a[1])
# [5 6 7 8]

# 元素(1, 2)
print(a[1, 2])
# 7

切片索引

某个索引可以是一个 切片 start:stop,表示从 第 start 行(列)到第 stop 行(列),注意切片不包括第 stop 列、切片有方向。如 a[1:3]a[:, 1]a[:, 1:3]

a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
# 行1-2
print(a[1:3])
# [[ 5  6  7  8]
# [ 9 10 11 12]]

# 列1
print(a[:, 1])
# [ 2  6 10]

# 列1-2
print(a[:, 1:3])  
# [[ 2  3]
# [ 6  7]
# [10 11]]

列表索引

某个索引也可以是一个 列表 [n1, n2, ...],表示 第 n1、n2、... 行(列),注意不要和数学的闭区间混淆。如 a[[1,2]]a[:, [1,3]]

a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
# 行1和行2
print(a[[1, 2]])
#[[ 5  6  7  8]
# [ 9 10 11 12]]

# 列1和列3
print(a[:, [1, 3]])
#[[ 2  4]
# [ 6  8]
# [10 12]]

示例

a = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
print(a, end='\n\n')
print(a[1])
print(a[1:2])
print(a[[1]], end='\n\n')

print(a[:, 1])  
print(a[:, 1:2])  
print(a[:, [1]], end='\n\n')  

a[:, [0, 1]] = a[:, [1, 0]]  
print("交换后:\n", a)

a[:1, :1] = 0  # 批量赋值也可以
print(a)
输出:
[[ 1  2  3  4]
[ 5  6  7  8]
[ 9 10 11 12]]

[5 6 7 8]
[[5 6 7 8]]
[[5 6 7 8]]

[ 2  6 10]
[[ 2]
[ 6]
[10]]
[[ 2]
[ 6]
[10]]

交换后:
[[ 2  1  3  4]
[ 6  5  7  8]
[10  9 11 12]]

[[ 0  0  3  4]
[ 0  0  7  8]
[10  9 11 12]]

多变量赋值

在错误的多变量赋值中(a[0], a[1] = a[1], a[0]),Numpy 数组实际先执行 a[0] = a[1],再 a[1] = a[0] (而普通 Python 列表是先整体计算右侧表达式,生成一个元组,然后依次赋值给左侧变量),这导致最终两行内容相同,变成了复制而不是互换。

正确地交换 NumPy 要用列表索引:a[[0, 1]] = a[[1, 0]];交换 则用切片和列表索引:a[:, [0, 1]] = a[:, [1, 0]]

条件索引

不同于前三种,条件索引单独占用一个中括号,其中的条件式实际上生成了一个布尔数组再逐个元素筛选。如 a[a>5]a[1:3][a[1:3] > 5]]

a = np.array([[1, 2, 3], [4, 5, 6], [1, 8, 9]])

# 筛选出所有大于5的元素,返回一维数组
print(a[a > 5])
# [6 8 9]

# 上面等同于:
cond = a > 5  # 创建一个布尔数组作为筛选的条件
# [[False,False,False],[False,False,True],[True,True,True]]
print(a[cond])  # 使用布尔数组进行索引

# 筛选出有(5, 8]中元素的列
print(a[((a > 5) & (a <= 8)).any(axis=1)])
# [[4 5 6]
#  [1 8 9]]

多条件的连接

注意:多条件的连接要用位运算符 & | ~(因为实际上是对多个布尔数组逐元素运算),而不能用 and or not

扩展

这里的 a[a > 5] 不等价于 [int(n) for n in a.flatten() if n > 5] ,前者 [6 8 9] 类型为 numpy.ndarray (n维数组),后者 [6, 8, 9]list

print输出就可以看到区别:np数组元素以空格间隔,而普通列表以逗号间隔。

对维数的说明

  • 索引/函数参数 中, 参数的数量 表示维数:

    • a[[2, 3]] 是对1维数组,而 a[:, [2, 3]] 是对2维数组
    • reshape(4) 表示长为4的1维数组,而 reshape(1, 4) 表示1行4列的2维数组;
  • 而在 字面量表示 中, 中括号的层数 (嵌套列表深度)表示维数:

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

    如上面用 [[[num, ...], ...], ...] 表示的2×2×3三维数组。