Python多同列名Pandas DataFrame左合并避免后缀并覆盖前值
问题原因
pandas的merge操作遇到左右表存在非连接键的同名列时,会自动添加_x、_y后缀区分两个来源的列,不会默认执行覆盖操作,因此你原来的写法无法得到预期结果。
解决方案
方法1:自定义合并函数适配reduce逻辑
适合需要明确控制每一步合并覆盖规则的场景,直接修改你原有的reduce逻辑即可:
from functools import reduce import pandas as pd # 你的DataFrame定义部分 df1 = pd.DataFrame({"Fruits":['apple','banana','mango','strawberry'], "Price":[100,50,60,70], "Count":[1,2,3,4], "shop_id":['A','A','A','A']}) df2 = pd.DataFrame({"Fruits":['apple','banana','mango','chicku'], "Price":[10,509,609,1], "Count":[8,9,10,11], "shop_id":['B','B','B','B']}) df3 = pd.DataFrame({"Fruits":['apple','banana','chicku'], "Price":[1000,5090,10], "Count":[5,6,7], "shop_id":['C','C','C']}) df4 = pd.DataFrame({"Fruits":['apple','strawberry','mango','chicku'], "Price":[50,51,52,53], "Count":[11,12,13,14], "shop_id":['D','D','D','D']}) # 自定义覆盖合并函数 def merge_cover(left, right): # 左连接,给同名列加区分后缀 merged = pd.merge(left, right, on='Fruits', how='left', suffixes=('_old', '_new')) # 后序表的值优先,空值用前序表的值填充 for col in ['Price', 'Count', 'shop_id']: merged[col] = merged[f'{col}_new'].fillna(merged[f'{col}_old']) # 仅返回需要的列 return merged[['Fruits', 'Price', 'Count', 'shop_id']] data_frames = [df1, df2, df3, df4] df_merged = reduce(merge_cover, data_frames)
执行后df_merged就是你要的仅保留一组列、后序表覆盖前序表的结果。
方法2:concat+去重 更简洁高效
如果你的需求只是按顺序保留每个Fruit最后一次出现的记录,可以用更简洁的写法,性能也更高:
# 合并所有DataFrame all_df = pd.concat([df1, df2, df3, df4]) # 按Fruits去重,保留最后出现的记录(即优先级最高的后序表记录) last_record_df = all_df.drop_duplicates(subset='Fruits', keep='last') # 和df1的Fruits列左连接,保证只保留df1中存在的Fruits result = df1[['Fruits']].merge(last_record_df, on='Fruits', how='left')
两种方法得到的结果完全一致,最终输出如下:
| Fruits | Price | Count | shop_id |
|---|---|---|---|
| apple | 50 | 11 | D |
| banana | 5090 | 6 | C |
| mango | 52 | 13 | D |
| strawberry | 51 | 12 | D |
内容的提问来源于stack exchange,提问作者Shirin
相关产品推荐
相关产品推荐

