布尔索引是用与原数组形状一致的布尔数组作掩码直接筛选元素,返回副本而非视图;普通索引(如整数或切片)可返回视图,且不依赖条件表达式。

什么是布尔索引,它和普通索引有什么区别?
布尔索引不是“先找下标再取值”,而是用一个和原数组形状一致的 bool 数组做掩码,直接选出所有 True 位置对应的元素。它不返回视图(view),默认返回副本(copy)——这点常被忽略,后续修改不会影响原数组。
常见错误是误以为 arr[condition] 是“原地筛选”,结果改了筛选结果却没改原数组;或者把条件写成 arr > 5 and arr ,触发 <code>ValueError: The truth value of an array with more than one element is ambiguous。
- 用
&、|、~代替and、or、not - 条件表达式必须整体包裹在括号里,比如
(arr > 5) & (arr - 多维数组中,布尔索引会自动展平匹配,除非你显式指定轴(见下一条)
如何对二维数组按行或按列筛选?
二维数组的布尔索引默认按第一个轴(行)广播,所以 arr[condition] 中 condition 长度必须等于行数。若想按列筛选,得让条件数组 shape 匹配列数,并用 : 显式保留另一维。
例如:筛选第 0 列大于 3 的所有行 → arr[arr[:, 0] > 3];筛选所有列都满足条件的列 → arr[:, (arr[0] > 2) & (arr[1] > 2)](注意这里用了第 0、1 行作参考)。
快速生成专业的 Python 脚本和应用代码。一键创建完整项目结构,支持CLI、API、爬虫、Bot、Django等多种项目类型,包含完整的项目结构、配置文件、依赖管理、测试、README和文档。
- 按行筛选:
arr[condition_1d],其中condition_1d长度 =arr.shape[0] - 按列筛选:
arr[:, condition_1d],其中condition_1d长度 =arr.shape[1] - 混合筛选(如选满足条件的某几列):
arr[np.ix_(row_mask, col_mask)],比链式索引更安全
np.where 和布尔索引什么关系?
np.where 不是布尔索引的替代品,而是它的“增强版”:当只传一个参数(如 np.where(arr > 5)),它返回满足条件的索引元组,可用于高级定位;当传三个参数(np.where(condition, x, y)),它做的是逐元素三元选择,返回新数组。
容易混淆的是:有人用 arr[np.where(arr > 5)],这其实多绕了一步——等价于直接写 arr[arr > 5],且前者还可能因返回元组导致维度意外变化(比如二维数组返回 (array([0,1]), array([2,3])))。
- 要取值 → 直接用布尔索引:
arr[arr > 5] - 要取索引 → 用
np.where(arr > 5),注意它返回的是元组,解包用rows, cols = np.where(...) - 要做条件赋值 →
arr[arr > 5] = 0或np.where(arr > 5, 0, arr)(后者不修改原数组)
性能和内存要注意什么?
布尔索引会创建新的布尔数组和结果数组,对大数组(比如千万级)容易爆内存。如果只是想统计或遍历,别急着筛出全部数据。
比如要算满足条件的均值,用 np.mean(arr[arr > 100]) 会先生成所有满足条件的副本;而 np.mean(arr, where=arr > 100)(NumPy 1.17+)或 np.nanmean(np.where(arr > 100, arr, np.nan)) 更省内存。
- 避免重复计算条件:把
mask = arr > 5提前算好,复用在arr[mask]和np.sum(mask)上 - 原地修改优先用布尔索引赋值:
arr[arr 比 <code>arr = np.where(arr 更快且不额外分配 - 超大数组慎用
np.where返回索引——索引数组本身也可能很大
NaN 的数据时,arr > 5 会产生 False 而不是 NaN,这点也常被当成 bug 追半天。Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!










