Pandas DataFrame处理函数中NaN赋值异常导致布尔结果错误排查
你遇到的核心问题是布尔判断逻辑与缺失值处理逻辑不一致,以及代码中存在的几处判断和赋值错误,导致boolean_df中错误的False值远超预期。以下是具体问题和修复方案:
1. 缺失值判断条件过严,遗漏部分缺失场景
当前代码只在lhs_val_list全部是NaN/None,或者rhs_val_list全部是NaN/None时,才给boolean_df赋值NaN。但实际场景中,只要表达式中任意一个变量是NaN,eval运算都会返回异常结果(比如NaN + 5 == 10会返回False,而非你期望的NaN),这就导致大量部分缺失的行被错误计算为False。
修复方法:修改判断条件,只要lhs_val_list或rhs_val_list中存在任意一个NaN/None,就赋值NaN:
# 替换原有的if条件 has_missing = (any(np.isnan(x) for x in lhs_val_list) or any(x is None for x in lhs_val_list) or any(np.isnan(x) for x in rhs_val_list) or any(x is None for x in rhs_val_list)) if has_missing: subtraction_df.loc[index, equation_column] = np.nan boolean_df.loc[index, equation_column] = np.nan continue
2. 缺失值处理逻辑矛盾:计算减法用替换后的值,布尔判断用原始值
在else分支中,你把lhs_val_list和rhs_val_list中的NaN替换为0来计算subtraction_df,但布尔判断时直接使用了原始行数据(row_vals = df.loc[index])。如果原始行中有NaN,eval表达式会基于原始NaN计算,返回错误的False(比如NaN + 3 == 3结果是False),而非基于替换后的0值计算。
修复方法:布尔判断时使用替换NaN为0后的变量值,构造一个包含替换后值的字典传入eval:
# 替换else分支中的eval部分 all_cols = lhs_list + rhs_list eval_vars = {} for col in all_cols: if col == '100': eval_vars[col] = 100 else: val = row.loc[col] # 统一处理NaN和None为0 eval_vars[col] = float(val) if not (pd.isna(val) or val is None) else 0 # 使用替换后的变量执行eval boolean_df.loc[index, equation_column] = eval(equation_column2, {}, eval_vars)
3. None判断逻辑无效
代码中先执行了lhs_val_list = [float(x) for x in lhs_val_list],如果原始值是None,float(None)会直接抛出TypeError;如果原始值已被Pandas转为NaN,all(x is None for x in lhs_val_list)永远为False,这部分判断完全无效。
修复方法:提前处理None值,改用pd.isna()统一判断缺失值(兼容NaN和None):
# 在转换为float之前先处理None lhs_val_list = [100 if col == '100' else row.loc[col] for col in lhs_list] lhs_val_list = [x if x is not None else np.nan for x in lhs_val_list] lhs_val_list = [float(x) for x in lhs_val_list] # 缺失值判断改用pd.isna() has_missing = (any(pd.isna(x) for x in lhs_val_list) or any(pd.isna(x) for x in rhs_val_list))
4. 链式赋值可能导致赋值失败
使用subtraction_df[equation_column][index]这种链式索引赋值,会触发SettingWithCopyWarning,在某些场景下(比如subtraction_df是某个DataFrame的切片)可能导致赋值不生效。
修复方法:改用.loc进行显式赋值:
# 替换所有赋值语句 subtraction_df.loc[index, equation_column] = np.nan boolean_df.loc[index, equation_column] = np.nan # 减法结果赋值 subtraction_df.loc[index, equation_column] = np.sum(lhs_val_list) - np.sum(rhs_val_list)
5. 单个列名的分割逻辑冗余
当lhs没有+时,lhs.split()会按空白分割,虽然结果正确,但不如直接用[lhs.strip()]更清晰高效:
lhs_list = [x.strip() for x in lhs.split('+')] if '+' in lhs else [lhs.strip()] rhs_list = [x.strip() for x in rhs.split('+')] if '+' in rhs else [rhs.strip()]
内容的提问来源于stack exchange,提问作者Neil Tipton

