Python-numpy-索引与切片
📅 2026/7/29 23:09:57
👁️ 阅读次数
📝 编程学习
NumPy 索引与切片
NumPy 提供了比 Python list 强大得多的索引能力:基本索引、切片、花式索引(Fancy Indexing)、布尔索引。
🔰 基本索引与切片
一维数组
importnumpyasnp arr=np.array([10,20,30,40,50,60])# 基本索引print(arr[0])# 10print(arr[-1])# 60(倒数第一)print(arr[-2])# 50# 切片(返回视图,非副本!)print(arr[1:4])# [20 30 40]print(arr[:3])# [10 20 30](前 3 个)print(arr[3:])# [40 50 60](从第 3 个到最后)print(arr[::2])# [10 30 50](步长 2)print(arr[::-1])# [60 50 40 30 20 10](反转)# 切片赋值(会修改原数组!)arr[1:4]=99print(arr)# [10 99 99 99 50 60]二维数组
mat=np.arange(12).reshape(3,4)print(mat)# [[ 0 1 2 3]# [ 4 5 6 7]# [ 8 9 10 11]]# 单个元素print(mat[0,0])# 0print(mat[2,-1])# 11# 整行 / 整列print(mat[1])# [4 5 6 7](第 1 行)print(mat[1,:])# 同上print(mat[:,2])# [ 2 6 10](第 2 列)# 子矩阵(切片)print(mat[0:2,1:3])# [[1 2]# [5 6]]# 步长切片print(mat[::2,::2])# 每隔一行、每隔一列# [[ 0 2]# [ 8 10]]# 行 + 列混合print(mat[0,:2])# [0 1](第 0 行前 2 列)print(mat[:2,-1])# [3 7](前 2 行最后 1 列)三维及以上
tensor=np.arange(24).reshape(2,3,4)# shape: (2, 3, 4) — 2 个矩阵,每个 3×4print(tensor[0])# 第一个 3×4 矩阵print(tensor[0,1])# 第一个矩阵的第 1 行 → (4,)print(tensor[0,1,2])# 标量 → 6print(tensor[:,0,:])# 每个矩阵的第 0 行 → (2, 4)print(tensor[:,:,::2])# 每矩阵每隔一列 → (2, 3, 2)...(Ellipsis)省略号
arr=np.arange(120).reshape(2,3,4,5)# 等价写法print(arr[0,:,:,:])# 完整写法print(arr[0,...])# 用 ... 代替中间的 :print(arr[...,2])# 最后一个维度的第 2 索引 → (2, 3, 4)print(arr[0,...,:3])# 第一个块,最后维取前 3 → (3, 4, 3)🎯 花式索引(Fancy Indexing)
用整数数组来索引,返回副本(非视图)。
一维花式索引
arr=np.array([10,20,30,40,50])# 用列表指定索引print(arr[[0,2,4]])# [10 30 50]# 可以用任意整数数组indices=np.array([4,1,1,3])print(arr[indices])# [50 20 20 40]# 可以任意顺序、重复print(arr[[4,4,4,0,0]])# [50 50 50 10 10]二维花式索引
mat=np.arange(12).reshape(3,4)# 指定行索引print(mat[[0,2]])# 第 0 行和第 2 行# [[ 0 1 2 3]# [ 8 9 10 11]]# 指定行 + 列索引print(mat[[0,2,1],[0,3,1]])# 取 (0,0), (2,3), (1,1) → [0 11 5]# ix_: 取行和列的笛卡尔积(子矩阵)print(mat[np.ix_([0,2],[1,3])])# [[ 1 3]# [ 9 11]]# ix_ 等价于 mat[[0,2]][:, [1,3]]花式索引 vs 切片
mat=np.arange(12).reshape(3,4)# 切片返回视图view=mat[:2,:2]view[0,0]=99print(mat[0,0])# 99 ← 原数组被修改了!# 花式索引返回副本copy=mat[[0,1]][:,[0,1]]copy[0,0]=999print(mat[0,0])# 99 ← 原数组未修改🔍 布尔索引 ⭐
arr=np.array([15,3,8,22,1,9,13])# 条件直接筛选print(arr[arr>10])# [15 22 13]# 多条件(用 & | ~,必须加括号!)print(arr[(arr>5)&(arr<20)])# [15 8 9 13]print(arr[(arr<5)|(arr>20)])# [3 22 1]print(arr[~(arr>10)])# [3 8 1 9]# ⚠️ 常见错误:用 and/or 或不加括号# arr[arr > 5 and arr < 20] ← 报错!# arr[arr > 5 & arr < 20] ← 结果错误(& 优先级高)!# arr[(arr > 5) & (arr < 20)] ← 正确!二维布尔索引
mat=np.arange(12).reshape(3,4)# 按条件筛选行print(mat[mat[:,0]>3])# 第 0 列 >3 的行# [[ 4 5 6 7]# [ 8 9 10 11]]# 整体条件mask=mat>5print(mat[mask])# [6 7 8 9 10 11](返回一维数组)布尔掩码赋值
arr=np.array([15,3,8,22,1,9,13])arr[arr>10]=0# 所有 >10 的变 0print(arr)# [0 3 8 0 1 9 0]arr[arr<5]=-1# 所有 <5 的变 -1print(arr)# [-1 -1 8 0 -1 9 -1]📌np.where()— 条件索引三剑客
条件替换(三元运算)
arr=np.array([15,3,8,22,1,9,13])# where(条件, True时的值, False时的值)result=np.where(arr>10,1,0)print(result)# [1 0 0 1 0 0 1]result=np.where(arr>10,arr,-arr)print(result)# [ 1 -3 -8 1 -1 -9 1]条件查找(返回索引)
arr=np.array([15,3,8,22,1,9,13])# 找到满足条件的索引indices=np.where(arr>10)print(indices)# (array([0, 3, 6]),) ← 返回元组!print(indices[0])# [0 3 6](一维时)print(arr[indices])# [15 22 13]# 二维mat=np.arange(12).reshape(3,4)rows,cols=np.where(mat>5)print(rows)# [1 1 2 2 2 2] — 行索引print(cols)# [2 3 0 1 2 3] — 列索引print(mat[rows,cols])# [6 7 8 9 10 11] — 值多条件组合
# np.where 也可以处理多条件arr=np.arange(10)result=np.where((arr>3)&(arr<8),arr*10,arr)print(result)# [0 1 2 3 40 50 60 70 8 9]🎯np.argwhere()— 获取非零/True 索引
arr=np.array([0,5,0,3,0,8,0])print(np.argwhere(arr>0))# [[1]# [3]# [5]]# 和 where 的区别:argwhere 返回 (N, ndim) 数组,where 返回元组📊np.take()/np.put()— 按索引取值/设值
arr=np.array([10,20,30,40,50])# take: 按索引取值print(arr.take([0,2,4]))# [10 30 50]print(np.take(arr,[4,3,3]))# [50 40 40]# 二维按轴取mat=np.arange(12).reshape(3,4)print(np.take(mat,[0,2],axis=0))# 取第 0、2 行print(np.take(mat,[0,2],axis=1))# 取第 0、2 列# put: 按索引设值(原地修改)arr=np.array([10,20,30,40,50])np.put(arr,[0,2],[99,88])print(arr)# [99 20 88 40 50]🔄np.select()/np.clip()— 多条件/裁剪
# select: 多条件多选择arr=np.array([15,3,8,22,1,9,13])conditions=[arr<5,arr>15,True]# True = 兜底choices=[-1,1,0]result=np.select(conditions,choices)print(result)# [0 -1 0 1 -1 0 0]# clip: 限制在范围内print(np.clip(arr,5,15))# [15 5 8 15 5 9 13]print(arr.clip(5,15))# 同上(方法形式)📐 多维索引技巧
按行列号取值
mat=np.arange(12).reshape(3,4)# 提取对角线print(np.diag(mat))# [0 5 10]print(np.diag(mat,k=1))# [1 6 11](上对角线)# 提取上三角 / 下三角print(np.triu(mat))# 上三角(含对角线)print(np.tril(mat,k=-1))# 下三角(不含对角线)# 索引数组组合row_indices=np.array([0,1,2])col_indices=np.array([3,2,1])print(mat[row_indices,col_indices])# [3 6 9] — 取 (0,3),(1,2),(2,1)按轴索引(take_along_axis)
mat=np.arange(12).reshape(3,4)# 取每行最大值的索引对应的列col_idx=mat.argmax(axis=1)# [3 3 3]result=np.take_along_axis(mat,col_idx[:,None],axis=1)print(result)# [[3] [7] [11]]📝 速查表
| 需求 | 代码 |
|---|---|
| 单个元素 | arr[0, 1]/arr[-1] |
| 整行/列 | arr[1, :]/arr[:, 2] |
| 子矩阵 | arr[0:2, 1:3] |
| 步长切片 | arr[::2, ::3] |
| 反转 | arr[::-1] |
| 省略号 | arr[0, ..., :3] |
| 花式行索引 | arr[[0, 2, 4]] |
| 笛卡尔积索引 | arr[np.ix_([0,2], [1,3])] |
| 布尔筛选 | arr[arr > 10] |
| 多条件 | arr[(a>3) & (a<10)] |
| 条件替换 | np.where(arr > 0, 1, -1) |
| 条件查找 | np.where(arr > 0) |
| 列表取值 | np.take(arr, [0, 2]) |
| 多条件选择 | np.select(conds, choices) |
| 裁剪 | np.clip(arr, lo, hi) |
[[numpy-总览|← 返回总览]]
编程学习
技术分享
实战经验