含SymPy S.NaN条目的numpy矩阵按行求和将nan视为0的方法
问题解决方法
问题核心是NumPy的NaN判断逻辑无法识别SymPy的单例NaN对象S.NaN,以下是两种可直接落地的方案:
方案1:保留NumPy矩阵格式,替换S.NaN后求和
SymPy的S.NaN是全局唯一单例对象,用x is S.NaN即可100%准确判断元素是否为SymPy NaN,不需要依赖np.isnan:
import numpy as np from sympy import S # 原始矩阵B B = np.matrix([[1, S.NaN, 30], [S.NaN, 2, S.NaN], [8, S.NaN, S.NaN], [S.NaN, 1, 16]]) # 向量化判断SymPy NaN,替换为0后按行求和 vec_is_nan = np.vectorize(lambda elem: elem is S.NaN) B_fill_zero = np.where(vec_is_nan(B), 0, B) row_sum_result = B_fill_zero.sum(axis=1)
运行后结果和预期完全一致,即使矩阵元素是SymPy符号表达式(例如x、30*x),求和逻辑也能正常工作,比如[x, S.NaN, 30*x]会正确返回31*x。
方案2:改用SymPy原生矩阵,调用内置方法处理
如果不需要强制使用NumPy矩阵,SymPy原生的Matrix类型自带替换和逐行求和方法,写法更简洁,天然适配SymPy表达式:
from sympy import Matrix, S # 构造SymPy矩阵 B_sym = Matrix([[1, S.NaN, 30], [S.NaN, 2, S.NaN], [8, S.NaN, S.NaN], [S.NaN, 1, 16]]) # 替换S.NaN为0后逐行求和 row_sum_result = B_sym.replace(S.NaN, 0).rowwise().sum()
注意事项
- 禁止用
x == S.NaN判断NaN:按照NaN的运算规则,NaN和任何值(包括自身)做等值判断都会返回False,必须用is做对象身份判断。 np.nansum失效的原因:该函数仅能识别NumPy体系的浮点型np.NaN,会将SymPy的S.NaN识别为普通Python对象,加法运算时会触发NaN传播,最终返回全NaN结果。- 如果需要把
S.NaN转为np.NaN,只需要把上述替换逻辑里的0换成np.nan即可,后续就能正常调用np.nansum计算。
内容的提问来源于stack exchange,提问作者selroh18
相关产品推荐
相关产品推荐

