使用np.select为pandas DataFrame按多条件新增列结果异常如何解决
问题根因
np.select是向量化运算,执行时会一次性基于列的初始值计算所有结果,不会逐行更新new列的中间计算值。你代码里的df['new'].shift(1)取到的全是初始赋值的0移位后的结果,根本拿不到前一行计算完成的new值,结果必然不符合预期。- 另外测试代码里给
Random列赋值的是字符串'20',后续做数值加法会触发类型错误,需要改成数值类型的20。
实现方案
该计算逻辑强依赖前一行的计算结果,属于逐行递推场景,有两种常用实现方式:
方案1:逐行迭代(逻辑直观,适合小数据集)
import pandas as pd import numpy as np # 构造测试数据集 df = pd.DataFrame(np.random.randint(0,30,size=10), columns=["Random"], index=pd.date_range("20180101", periods=10)) df = df.reset_index() df.loc[:,'Random'] = 20 # 修正为数值类型,不要用字符串'20' df['Recommandation']=['No', 'Yes', 'No', 'Yes', 'Yes', 'Yes', 'No', 'No', 'Yes', 'No'] df['diff']=[3,2,4,1,6,1,2,2,3,1] # 逐行递推计算new列 df['new'] = 0 for idx in range(len(df)): if idx < 3: # 前3行取Random列值 df.loc[idx, 'new'] = df.loc[idx, 'Random'] elif df.loc[idx, 'Recommandation'] == 'Yes': # 推荐为Yes时,取上一行new值加当前diff df.loc[idx, 'new'] = df.loc[idx-1, 'new'] + df.loc[idx, 'diff'] else: # 其余场景直接取上一行new值 df.loc[idx, 'new'] = df.loc[idx-1, 'new']
运行后new列输出为[20,20,20,21,27,28,28,28,31,31],完全匹配预期。
方案2:向量化累积计算(性能更高,适合大数据集)
逻辑本质是:前3行固定值为20,从第4行开始,仅当Recommandation为Yes时累加当前diff,其余时候累加0,直接用条件累积和即可实现,无需循环:
df['new'] = 20 # 筛选第4行及以后的行 cal_mask = df.index >= 3 # 仅当Recommandation为Yes时加diff,否则加0 add_series = (df.loc[cal_mask, 'Recommandation'] == 'Yes') * df.loc[cal_mask, 'diff'] # 累加后加初始值20 df.loc[cal_mask, 'new'] = 20 + add_series.cumsum()
该方案运行效率远高于逐行循环,计算结果和方案1完全一致。
内容的提问来源于stack exchange,提问作者ash1
相关产品推荐
相关产品推荐

