Python中合并DataFrame并替换列值:大数据量下值错误问题求助
问题与解决方案
场景说明
有两个DataFrame:
- df1:包含
Expenses、Calendar、Actual三列,共10000条记录 - df2:结构与df1完全一致,共150条记录
需求:保留df1全部数据,基于Expenses+Calendar的组合键关联df2,用df2的Actual值替换df1对应行的Actual值。当前代码在小数据量时正常,但处理10000条df1数据时替换值出现错误。
数据示例
df1原始数据:
Expenses Calendar Actual 0 xyz 2020-01-01 10 1 xyz 2020-02-01 99 2 txn vol(new) 2020-01-01 5 3 txn vol(new) 2020-02-01 20 4 txn vol(tenu) 2020-01-01 30 5 txn vol(tenu) 2020-02-01 40
df2原始数据:
Expenses Calendar Actual 0 txn vol(new) 2020-01-01 23 1 txn vol(new) 2020-02-01 32 2 txn vol(tenu) 2020-01-01 60
期望输出
Expenses Calendar Actual 0 xyz 2020-01-01 10 1 xyz 2020-02-01 99 2 txn vol(new) 2020-01-01 23 3 txn vol(new) 2020-02-01 32 4 txn vol(tenu) 2020-01-01 60 5 txn vol(tenu) 2020-02-01 40
当前代码问题分析
当前代码:
cols_to_replace = ['Actual'] df1.loc[df1.set_index(['Calendar','Expenses']).index.isin(df2.set_index(['Calendar','Expenses']).index), cols_to_replace] = df2.loc[df2.set_index(['Calendar','Expenses']).index.isin(df1.set_index(['Calendar','Expenses']).index),cols_to_replace].values
错误原因:df1中匹配到的行顺序是df1自身的排列顺序,而df2中筛选出的匹配行是df2自身的排列顺序,两者没有对应关系。直接赋值df2.loc[...].values会把df2的匹配值按顺序硬塞给df1的匹配行,大数据量时极易出现键值不匹配的情况,导致替换错误。
正确解决方案
推荐以下三种可靠方法,均能保证键值精准匹配,且适用于大数据量:
方法1:使用update(最优,效率最高)
利用组合索引精准匹配,update只会替换df1中存在于df2的行,不改变df1的行数和顺序:
# 将df2设置为组合索引,仅保留需要替换的Actual列 df2_update = df2.set_index(['Expenses', 'Calendar'])['Actual'] # 给df1设置相同的组合索引,执行更新 df1.set_index(['Expenses', 'Calendar'], inplace=True) df1.update(df2_update) # 恢复原索引 df1.reset_index(inplace=True)
方法2:使用combine_first
优先取df2的值,无匹配时保留df1的值,同样基于组合索引匹配:
# 两个DataFrame都设置为组合索引 df1_idx = df1.set_index(['Expenses', 'Calendar']) df2_idx = df2.set_index(['Expenses', 'Calendar']) # 合并后恢复原索引 result = df2_idx.combine_first(df1_idx).reset_index()
方法3:使用左连接+填充(直观易懂)
通过merge左连接保留df1全量数据,再用df2的值填充匹配行:
# 左连接df1和df2,区分原Actual和新Actual merged = df1.merge( df2, on=['Expenses', 'Calendar'], how='left', suffixes=('_orig', '_new') ) # 用新值替换原值,无新值则保留原值 merged['Actual'] = merged['Actual_new'].fillna(merged['Actual_orig']) # 保留目标列 result = merged[['Expenses', 'Calendar', 'Actual']]
内容的提问来源于stack exchange,提问作者SK15
相关产品推荐
相关产品推荐

