NumPy中条件筛选需用布尔索引而非if语句,如arr[arr > 5];多条件用&、|、~;np.where实现三元选择,np.select支持多分支逻辑。

用布尔索引做条件筛选,不是用if语句
NumPy里不能对数组写 if arr > 0: 这种Python原生条件判断——它会报 ValueError: The truth value of an array with more than one element is ambiguous。正确做法是让条件本身返回一个布尔数组,再用它当索引。
比如想取出所有大于5的元素:
import numpy as np arr = np.array([3, 7, 1, 9, 4]) mask = arr > 5 # 返回 [False, True, False, True, False] result = arr[mask] # 得到 [7, 9]
注意:布尔索引返回的是**新数组副本**,不是视图;修改 result 不会影响原 arr。
- 多个条件用
&(不是and)、|(不是or)、~(不是not) arr[(arr >= 2) & (arr —— 必须加括号,运算符优先级会导致错误- 空条件(如
arr[arr > 100])返回空数组,不会报错,但后续操作可能意外出错
用np.where做掩码替换,比循环快得多
np.where 是最常用、也最容易误用的掩码替换工具。它不只返回索引,还能直接构造新值。
立即学习“Python免费学习笔记(深入)”;
基础用法:np.where(condition, x, y) 表示“满足 condition 就取 x 对应位置的值,否则取 y 的”。x 和 y 可以是标量、数组,甚至另一个表达式。
arr = np.array([1, 6, 3, 8, 2]) new_arr = np.where(arr > 5, -1, arr) # [1, -1, 3, -1, 2]
常见陷阱:
- 别把
np.where当成“找下标”专用函数——它默认做的是三元选择,不是np.argwhere - 如果只想改一部分值,又想原地修改,用
arr[mask] = new_value更直观,比如arr[arr - x 和 y 类型不一致时,结果类型由 NumPy 类型提升规则决定,可能意外变成
float64,影响内存或后续计算
处理NaN和无穷值时,np.isfinite比!=更可靠
直接写 arr != np.nan 永远返回 False,因为 NaN 不等于任何值(包括自己)。同理,arr == np.inf 在某些版本也不稳定。
必须用专门的判断函数:
-
np.isfinite(arr):True 表示是普通数字(非 NaN、非 inf、非 -inf) -
np.isnan(arr):只对 NaN 返回 True -
np.isinf(arr):对 ±inf 都返回 True
实际替换 NaN 的典型写法:
arr = np.array([1.0, np.nan, 3.0, np.inf]) clean = np.where(np.isfinite(arr), arr, 0) # [1., 0., 3., 0.]
注意:np.nan 是浮点概念,整数数组里不会自然出现 NaN;若从 Pandas 导入数据,可能含 pd.NA,需先转为 float 或用 pandas.isna 处理。
高级场景:用np.select处理多分支条件
当条件超过两个,嵌套 np.where 会变得难读且低效。这时 np.select 更合适。
它接收三个参数:condlist(条件列表)、choicelist(对应值列表)、default(默认值)。
arr = np.array([1, 4, 7, 10, 12]) condlist = [arr < 3, (arr >= 3) & (arr < 8), arr >= 8] choicelist = ['low', 'mid', 'high'] result = np.select(condlist, choicelist, default='unknown')
输出:['low' 'mid' 'mid' 'high' 'high']
关键细节:
-
condlist和choicelist长度必须一致 - 条件按顺序匹配,第一个为 True 的生效,后续即使也满足也不执行(类似 if-elif-else)
-
default是必需参数,不能省略;设为np.nan或None时,注意最终数组 dtype 会自动升级
多条件逻辑复杂时,先用临时变量拆解条件表达式,比堆在一行里更易调试。


















