NumPy RuntimeWarning异常排查:无负值/NaN数据仍触发对数无效值警告
NumPy RuntimeWarning异常排查:无负值/NaN数据仍触发对数无效值警告
嗨,这个问题我之前也碰到过!核心原因其实是np.select的执行逻辑和你想的不一样——它会先把所有choices里的表达式全部计算完,再根据conditions来挑选结果,而不是只计算符合当前条件的分支。
问题根源拆解
你看你的数据里,ebit有16.8、11.5这类大于1的正值,当np.select执行时,它会不管条件先计算np.log(1 - df['ebit']),这时候1 - 16.8 = -15.8,对数函数输入负数就会触发RuntimeWarning,哪怕最后这个分支的结果根本不会被用到(因为你的数据里没有负的ebit)!
解决方案
推荐用np.piecewise替代np.select,它是专门为分段函数设计的工具,只会在对应的条件区间内执行对应的表达式,不会去计算不符合条件的分支,完美规避无效值警告。
修改后的完整函数代码:
import numpy as np import pandas as pd def calculate_ln_values(df): # 处理ebit的分段计算 df['lnebit'] = np.piecewise(df['ebit'], [df['ebit'] >= 0.0, df['ebit'] < 0.0], [lambda x: np.log(1 + x), lambda x: -np.log(1 - x)]) # 处理sale的分段计算 df['lnsale'] = np.piecewise(df['sale'], [df['sale'] >= 0.0, df['sale'] < 0.0], [lambda x: np.log(1 + x), lambda x: -np.log(1 - x)]) return df
另一种可选方案:用loc+掩码逐段计算
如果你更习惯pandas的操作风格,也可以先初始化列值为NaN,再用掩码定位有效区域计算:
def calculate_ln_values(df): # 处理ebit df['lnebit'] = np.nan mask_pos_ebit = df['ebit'] >= 0.0 mask_neg_ebit = df['ebit'] < 0.0 df.loc[mask_pos_ebit, 'lnebit'] = np.log(1 + df.loc[mask_pos_ebit, 'ebit']) df.loc[mask_neg_ebit, 'lnebit'] = -np.log(1 - df.loc[mask_neg_ebit, 'ebit']) # 处理sale df['lnsale'] = np.nan mask_pos_sale = df['sale'] >= 0.0 mask_neg_sale = df['sale'] < 0.0 df.loc[mask_pos_sale, 'lnsale'] = np.log(1 + df.loc[mask_pos_sale, 'sale']) df.loc[mask_neg_sale, 'lnsale'] = -np.log(1 - df.loc[mask_neg_sale, 'sale']) return df
验证效果
用你提供的测试数据运行修改后的函数,就不会再出现RuntimeWarning了,而且计算结果和你原本的逻辑完全一致。
备注:内容来源于stack exchange,提问作者PTQuoc
相关产品推荐
相关产品推荐

