np.nan_to_num 默认将 np.nan 替换为 0.0,np.inf 替换为 dtype 对应的 finfo.max(如 float64 下约 1.798e308),-np.inf 替换为 finfo.min。

np.nan_to_num 默认如何处理 inf 和 nan
np.nan_to_num 默认把 np.nan 替换成 0.0,把 np.inf 替换成当前浮点类型的极大值(如 np.finfo(float).max),-np.inf 替换成极小值(np.finfo(float).min)。这不是“截断”或“丢弃”,而是有明确数值映射的填充。
常见误解是它只管 nan,其实 inf 类型默认也参与转换——这点容易被忽略,尤其在做数据清洗时误以为 inf 会保留原样。
- 默认行为等价于:
np.nan_to_num(x, nan=0.0, posinf=None, neginf=None),其中posinf和neginf为None时才触发极值替换 - 若显式传入
posinf=1e308,则np.inf被替换成1e308,不再用finfo.max - 若传
posinf=np.nan,那np.inf反而变成nan,后续可能被二次处理
posinf/neginf 设为 None 时的实际边界值是什么
当 posinf 或 neginf 为 None(即未指定),np.nan_to_num 会查当前 dtype 的 finfo。对 float64,np.finfo(np.float64).max ≈ 1.798e308;对 float32,则是 ≈ 3.403e38。这些值不是 magic number,而是 IEEE 754 规定的可表示最大有限值。
关键点:这个替换发生在“数值域内”,不引发 overflow(因为本身就是上限),但下游计算若再做乘法或指数运算,仍可能立刻溢出为 inf。
- 检查方式:
np.finfo(x.dtype).max,别硬记常量 - 混合 dtype 数组(如含
float32和float64)会先 upcast,再取对应finfo - 整数数组不处理
inf(本身不能存inf),但nan会报错,需先转 float
为什么有时 np.nan_to_num(x, nan=0) 后仍有 inf
最常见原因是:你传入的是整数数组,或数组里根本没 inf,但你以为有;或者你用了旧版 NumPy(posinf/neginf 参数尚未支持 None 默认行为(那时默认不处理 inf)。
另一个隐蔽原因:输入含 Python 原生 float('inf'),但数组 dtype 是 object ——此时 np.nan_to_num 不递归处理 object 元素,直接返回原数组。
- 确认 dtype:
x.dtype,非object且为浮点型才有效 - 检查 inf 是否真实存在:
np.isinf(x).any(),别靠 print 猜 - 旧版本兼容写法:
np.nan_to_num(x, nan=0.0, posinf=1e308, neginf=-1e308)
替代方案:何时不该用 np.nan_to_num
如果目标只是“去掉异常值用于绘图或统计”,用 np.nan_to_num 可能掩盖问题——把 inf 塞进一个极大但合法的数,mean、std 会被严重扭曲。这时候更稳妥的是显式掩码或截断。
例如,用 np.clip 限定范围,或用布尔索引清空:x[np.isinf(x)] = np.nan 再统一处理;又或者用 scipy.stats.mstats.trimmed_mean 避开极端值。
-
np.nan_to_num适合“快速兜底 + 进入下游数值计算流程”的场景,比如喂给 sklearn 模型前的预处理 - 不适合探索性分析——它不报 warning,也不留 trace,静默替换后你可能很久才发现结果异常
- 若需日志记录哪些位置被替换,得自己封装一层,检查
np.isnan(x) | np.isinf(x)再操作









