二维NumPy数组求均值时如何避免除零错误并替换nan/inf为0
问题原因
你之前的两种方案失效、以及原始计算出现nan的核心原因有三个:
np.nan的特性是和任何值做相等判断都会返回False,包括它自身,所以avg == np.nan永远返回全False的掩码,根本无法选中nan值做替换。- 第一种掩码方案错误使用了布尔索引:直接用
A+B>0的二维掩码去索引数组,会把所有符合条件的元素抽平为一维数组,丢失原有的3行结构,此时再按axis=1求均值自然无法得到正确的按行结果。 - 原始计算触发异常是因为第二行最后一个位置
A+B=0、对应位置C=0,0/0运算得到nan;如果遇到分子非0、分母为0的情况还会得到inf值。
可行方案
根据你想要的处理逻辑,选对应方法即可:
方案1:先替换元素异常值再计算均值(最常用)
逻辑是:计算比值时,先把所有nan/inf的元素替换为0,再按行求均值,异常元素会作为0参与均值计算。
用np.nan_to_num可以一次性完成nan、正负inf的替换,搭配np.errstate可以临时屏蔽除0警告,避免控制台输出无用提示:
import numpy as np A = np.array([[2,2,2],[1,0,0],[1,2,1]]) B = np.array([[2,0,2],[0,1,0],[1,2,1]]) C = np.array([[2,0,1],[0,1,0],[1,1,2]]) # 临时关闭除0、非法值的警告 with np.errstate(divide='ignore', invalid='ignore'): ratio = C / (A + B) # 把所有nan、正inf、负inf都替换为0 ratio = np.nan_to_num(ratio, nan=0.0, posinf=0.0, neginf=0.0) # 按行求均值 avg = np.average(ratio, axis=1)
运行得到的avg结果为[0.25 0.33333333 0.58333333],没有异常值。
如果你不想引入nan_to_num,也可以用掩码直接在原结构上计算,避免打平数组:
denominator = A + B ratio = np.zeros_like(C, dtype=np.float64) mask = denominator > 0 # 仅在分母有效位置计算比值,其余位置保持初始值0 ratio[mask] = C[mask] / denominator[mask] avg = np.average(ratio, axis=1)
得到的结果和上面完全一致。
方案2:计算完均值后替换整行异常值
如果你的逻辑是:只要某一行计算出来的均值是nan/inf,就把这行的均值直接设为0,不需要把异常元素拆出来参与计算,可以直接对最终的均值数组做替换,注意要用numpy提供的判断函数而不是==判断:
with np.errstate(divide='ignore', invalid='ignore'): avg = np.average(C/(A+B), axis=1) # 选中所有是nan或inf的位置,替换为0 avg[np.isnan(avg) | np.isinf(avg)] = 0
这个方案得到的结果是[0.25 0. 0.58333333],第二行因为原始计算结果是nan,直接被替换为0。
内容的提问来源于stack exchange,提问作者user13925399
相关产品推荐
相关产品推荐

