用 np.isnan() 生成布尔掩码最直接,因 NaN≠NaN;np.where() 获取索引,一维用 np.where(mask)[0],二维解包为 rows, cols;结构化数组需指定字段,pandas 推荐 df.isna();性能上 np.where 优于 np.argwhere。

用 np.isnan() 生成布尔掩码是最直接的方式
NaN 本身不等于任何值(包括它自己),所以不能用 == np.nan 判断。必须用 np.isnan() —— 它专为浮点 NaN 设计,对非数字类型(如字符串)会报错,但对 float64、float32 数组稳定可靠。
返回的是和原数组形状一致的布尔数组,True 表示该位置是 NaN:
import numpy as np arr = np.array([1.0, np.nan, 2.5, np.nan, 3.0]) mask = np.isnan(arr) # → [False, True, False, True, False]
用 np.where() 获取具体索引坐标
np.where() 接收布尔数组后,返回满足条件的元素在各维度上的索引元组。一维数组返回一个 ndarray,二维及以上返回多个 ndarray(按轴顺序)。
常见组合写法:
立即学习“Python免费学习笔记(深入)”;
- 一维:
np.where(np.isnan(arr))[0]→array([1, 3]) - 二维:
rows, cols = np.where(np.isnan(matrix)),rows[i]和cols[i]构成第i个 NaN 的坐标 - 想转成 (row, col) 元组列表?用
list(zip(*np.where(np.isnan(matrix))))
注意:np.where() 不接受 axis 参数,不能直接按行/列聚合;需要额外用 np.any() 配合。
处理含 NaN 的结构化数组或 pandas DataFrame 时别直接套用
np.isnan() 对结构化数组(dtype 包含多个字段)会报 TypeError: ufunc 'isnan' not supported for the input types。此时必须指定字段,例如:
dt = np.dtype([('a', 'f8'), ('b', 'i4')])
sarr = np.array([(1.0, 2), (np.nan, 3)], dtype=dt)
np.isnan(sarr['a']) # ✅ 正确
np.isnan(sarr) # ❌ 报错pandas 中更推荐用 df.isna() 或 df.isnull(),它们自动适配各种 dtype,且支持 axis=0/1、how='any' 等语义,比裸 NumPy 更鲁棒。
性能差异:小数组无感,大数组慎用 np.argwhere()
np.argwhere() 看起来更“直观”(直接返回坐标数组),但它内部等价于 np.transpose(np.where(...)),多了一次转置开销。实测在千万级一维数组上,np.where(...)[0] 比 np.argwhere(...).flatten() 快约 15–20%。
另外:np.argwhere() 总是返回二维数组(哪怕输入是一维),容易在后续索引时引发 shape 不匹配错误,比如 arr[np.argwhere(...)] 会失败,而 arr[np.where(...)[0]] 可直接索引。
真正需要坐标的场景才用 np.argwhere();只要取值或做布尔索引,优先用 np.where() + 解包。


















