目录一、基础回顾NumPy的索引与切片1.1 基本索引1.2 基础切片二、整数数组索引花式索引2.1 一维花式索引2.2 二维花式索引2.3 花式索引与切片的组合2.4 使用np.ix_()构造笛卡尔积索引三、布尔索引3.1 基本布尔索引3.2 多条件组合3.3 二维布尔索引3.4 修改符合条件的元素四、高级切片技巧4.1 省略号...的使用4.2 newaxisNone增加维度4.3 负步长实现翻转五、视图 vs 副本5.1 验证示例5.2 安全赋值技巧六、实战案例6.1 数据清洗替换异常值6.2 图像处理提取红色通道6.3 机器学习分层采样七、性能对比向量化 vs 循环八、常见陷阱与注意事项8.1 花式索引返回副本修改不影响原数组8.2 组合索引时切片返回视图花式索引返回副本8.3 布尔索引的长度必须匹配8.4 混合整数索引和切片时结果的维度顺序九、总结在数据科学和机器学习领域NumPy是最基础也是最核心的库之一。很多初学者只会用最基本的索引和切片遇到稍微复杂的数据提取需求就不得不写循环导致代码又慢又丑。今天我就带你彻底搞懂NumPy的高级索引与切片技巧让你的代码水平瞬间提升一个档次让我们一起进入今天的正文一、基础回顾NumPy的索引与切片在深入高级技巧之前我们先回顾一下NumPy的基本索引和切片操作。1.1 基本索引NumPy数组的基本索引与Python列表类似python import numpy as np arr np.array([1, 2, 3, 4, 5]) print(arr[0]) # 1 print(arr[-1]) # 5 # 二维数组 arr2d np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) print(arr2d[0, 1]) # 2 print(arr2d[1][2]) # 6不推荐效率低 print(arr2d[1, 2]) # 6推荐写法1.2 基础切片切片语法 start:stop:step 同样适用python arr np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]) print(arr[2:7]) # [2 3 4 5 6] print(arr[:5]) # [0 1 2 3 4] print(arr[5:]) # [5 6 7 8 9] print(arr[::2]) # [0 2 4 6 8] # 二维切片 arr2d np.arange(12).reshape(3, 4) # [[ 0 1 2 3] # [ 4 5 6 7] # [ 8 9 10 11]] print(arr2d[:2, 1:3]) # [[1 2] # [5 6]]注意基础切片返回的是原始数据的视图修改视图会影响原数组。二、整数数组索引花式索引整数数组索引允许你使用另一个数组来指定要选取的元素位置。这是NumPy最强大的特性之一。2.1 一维花式索引python arr np.array([10, 20, 30, 40, 50, 60]) indices [0, 2, 4] print(arr[indices]) # [10 30 50] # 支持负数索引 print(arr[[-1, -2]]) # [60 50] # 可以重复选取 print(arr[[0, 0, 1, 1, 2]]) # [10 10 20 20 30]2.2 二维花式索引对于二维数组可以分别传入行索引和列索引python arr2d np.arange(12).reshape(3, 4) # [[ 0 1 2 3] # [ 4 5 6 7] # [ 8 9 10 11]] # 选取 (0,1)、(1,2)、(2,3) 位置的元素 rows [0, 1, 2] cols [1, 2, 3] print(arr2d[rows, cols]) # [1 6 11] # 选取整个行或列可以用切片 print(arr2d[[0, 2], :]) # 第0行和第2行的所有列 # [[ 0 1 2 3] # [ 8 9 10 11]]2.3 花式索引与切片的组合python arr2d np.arange(12).reshape(3, 4) # 选取第0行和第2行的第1列到第3列 result arr2d[[0, 2], 1:4] print(result) # [[ 1 2 3] # [ 9 10 11]]2.4 使用np.ix_()构造笛卡尔积索引当你想要选取一个矩形区域但行和列都不是连续的时候np.ix_() 就派上用场了python arr2d np.arange(12).reshape(3, 4) rows [0, 2] cols [1, 3] # 想要选取 (0,1)、(0,3)、(2,1)、(2,3) 四个点 result arr2d[np.ix_(rows, cols)] print(result) # [[ 1 3] # [ 9 11]]如果没有np.ix_()直接写arr2d[rows, cols]只会得到[1, 11]对应(0,1)和(2,3)并不是笛卡尔积。三、布尔索引布尔索引是数据分析中最常用的技巧之一用于根据条件筛选数据。3.1 基本布尔索引python arr np.array([1, 2, 3, 4, 5]) mask arr 3 print(mask) # [False False False True True] print(arr[mask]) # [4 5] # 更简洁的写法 print(arr[arr 3]) # [4 5]3.2 多条件组合使用 与、|或、~非来组合多个条件注意不能用 and / or / notpython arr np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10]) # 大于3且小于8 print(arr[(arr 3) (arr 8)]) # [4 5 6 7] # 小于等于2 或 大于等于9 print(arr[(arr 2) | (arr 9)]) # [1 2 9 10] # 取反不大于5即小于等于5 print(arr[~(arr 5)]) # [1 2 3 4 5]常见错误忘记括号会导致运算符优先级问题。arr 3 arr 8 会报错因为 优先级高于 。3.3 二维布尔索引python arr2d np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]) # 选取所有大于5的元素 print(arr2d[arr2d 5]) # [6 7 8 9] 返回一维数组 # 按行条件筛选选出所有包含偶数元素的行 rows_with_even np.any(arr2d % 2 0, axis1) print(arr2d[rows_with_even]) # [[1 2 3] # [4 5 6] # [7 8 9]] # 实际上所有行都有偶数所以全选3.4 修改符合条件的元素布尔索引也可以用于赋值python arr np.array([1, 2, 3, 4, 5]) arr[arr 3] 0 print(arr) # [1 2 3 0 0] # 二维示例 arr2d np.arange(9).reshape(3, 3) arr2d[arr2d % 2 0] -1 print(arr2d) # [[-1 1 -1] # [ 3 -1 5] # [ 6 7 8]] # 注意这里6和8也被改成了-1等等6%208%20所以正确四、高级切片技巧4.1 省略号...的使用省略号用于表示“所有剩余的维度”在多维数组时特别有用python # 三维数组 arr3d np.arange(24).reshape(2, 3, 4) # shape: (2, 3, 4) # 选取第一个维度索引0其余维度全部保留 print(arr3d[0, ...]) # 等价于 arr3d[0, :, :] print(arr3d[..., 0]) # 选取所有维度的第0列shape: (2, 3) print(arr3d[0, ..., 1]) # shape: (3,)4.2 newaxisNone增加维度使用 np.newaxis 或 None 可以在指定位置增加一个长度为1的维度python arr np.array([1, 2, 3]) print(arr.shape) # (3,) # 变成列向量 col_vec arr[:, np.newaxis] print(col_vec.shape) # (3, 1) # [[1] # [2] # [3]] # 变成行向量 row_vec arr[np.newaxis, :] print(row_vec.shape) # (1, 3) # [[1 2 3]] # 也可以同时加多个 arr2 arr[:, None, None] print(arr2.shape) # (3, 1, 1)这在广播计算中非常有用。4.3 负步长实现翻转python arr np.array([1, 2, 3, 4, 5]) print(arr[::-1]) # [5 4 3 2 1] # 二维数组的行翻转和列翻转 arr2d np.arange(9).reshape(3, 3) print(arr2d[::-1]) # 上下翻转 print(arr2d[:, ::-1]) # 左右翻转 print(arr2d[::-1, ::-1]) # 旋转180度五、视图 vs 副本理解视图和副本的区别至关重要它直接影响内存使用和bug的产生。操作类型返回结果修改是否影响原数组基础切片 arr[1:5]视图是整数数组索引 arr[[1,2,3]]副本否布尔索引 arr[arr3]副本否arr.view()视图是arr.copy()副本否5.1 验证示例python arr np.arange(5) view arr[1:4] copy arr[[1, 2, 3]] view[0] 100 copy[0] 999 print(arr) # [0 100 2 3 4] 视图修改影响了原数组 print(copy) # [999 2 3] 副本修改不影响原数组5.2 安全赋值技巧如果你想安全地修改原数组可以使用 arr[:] new_values 或直接索引赋值python arr np.arange(5) # 正确修改原数组 arr[arr 2] 0 # 布尔索引返回副本这里要小心注意虽然布尔索引返回副本但当你用布尔索引作为左值进行赋值时NumPy会正确地修改原数组的元素。这是NumPy的特殊语法糖python arr np.arange(5) arr[arr 2] 0 # 这个操作修改了原数组 print(arr) # [0 1 2 0 0]但是如果你先获取布尔索引的结果再赋值则不会影响原数组python arr np.arange(5) mask arr 2 subset arr[mask] subset[0] 99 # 修改的是副本arr不变六、实战案例6.1 数据清洗替换异常值python # 生成带有异常值的数据 data np.random.randn(1000) # 加入一些异常值 data[::50] 100 # 将大于3倍标准差的值替换为中位数 std np.std(data) median np.median(data) data[np.abs(data - median) 3 * std] median6.2 图像处理提取红色通道python # 假设有一张RGB图像shape (H, W, 3) image np.random.randint(0, 256, (1080, 1920, 3), dtypenp.uint8) # 提取红色通道索引0 red_channel image[..., 0] # 将红色通道的值加倍限制在0-255 red_channel np.clip(red_channel * 2, 0, 255) image[..., 0] red_channel6.3 机器学习分层采样python # 假设有特征X和标签y需要按标签进行分层采样 X np.random.randn(1000, 20) y np.random.choice([0, 1, 2], size1000, p[0.7, 0.2, 0.1]) # 从每个类别中抽取10个样本 sampled_indices [] for label in np.unique(y): label_indices np.where(y label)[0] sampled np.random.choice(label_indices, size10, replaceFalse) sampled_indices.extend(sampled) X_sampled X[sampled_indices] y_sampled y[sampled_indices]七、性能对比向量化 vs 循环布尔索引和花式索引的底层是用C实现的速度远快于Python循环。python import time # 创建大数据 arr np.random.randn(10_000_000) # 方法1Python循环 start time.time() result_loop [] for x in arr: if x 0: result_loop.append(x) print(fLoop time: {time.time() - start:.4f}s) # 方法2布尔索引 start time.time() result_bool arr[arr 0] print(fBool indexing time: {time.time() - start:.4f}s)布尔索引快了近100倍! ! 八、常见陷阱与注意事项8.1 花式索引返回副本修改不影响原数组python arr np.arange(10) subset arr[[1, 3, 5]] subset[0] 999 print(arr) # 原数组不变[0,1,2,3,4,5,6,7,8,9]8.2 组合索引时切片返回视图花式索引返回副本python arr np.arange(12).reshape(3, 4) # 先切片后花式索引 sub arr[:2, [1, 2]] # 第一行切片得到视图再花式索引得到副本 sub[0, 0] 999 print(arr) # 原数组不受影响8.3 布尔索引的长度必须匹配python arr np.arange(5) mask [True, False, True] # 长度3arr长度5 try: print(arr[mask]) except IndexError: print(报错布尔索引长度必须与数组长度一致)8.4 混合整数索引和切片时结果的维度顺序python arr3d np.arange(24).reshape(2, 3, 4) # 整数索引会降维 print(arr3d[1, :, :].shape) # (3, 4) 维度减少 print(arr3d[1, :, [1,2]].shape) # (3, 2) 注意维度顺序九、总结索引类型语法示例返回常用场景基础索引arr[2, 3]标量取单个元素切片arr[1:5, :]视图取连续区域整数数组arr[[0,2,4]]副本取离散位置布尔索引arr[arr0]副本条件筛选np.ix_arr[np.ix_(r,c)]副本矩形区域...arr[..., 0]视图/副本多维简化如果觉得本文对你有帮助欢迎点赞、收藏、关注哦