如何基于ID列合并Pandas DataFrame,补全更新数据并解决重复ID?
Pandas基于ID合并DataFrame:填充、更新与新增记录解决方案
问题描述
需要基于animal_id列合并两个DataFrame,实现以下目标:
- 用df2的数据填充df1的缺失值
- 用df2的非空值更新df1的已有数据
- 添加df2中存在但df1中没有的新ID记录
使用pd.merge(how='outer')时出现ID重复行,需解决该问题。
示例数据
import pandas as pd df1 = pd.DataFrame({ "animal_id": ["a12", "a17", "a45"], "name": ["Lucy", "Lola", "Duke"], "race": ["Akita", "Beagle", "Boxer"], "weight": ["", "13", "23"], "date": ["2020-12-01", "2019-03-08", "2017-10-21"] }) df2 = pd.DataFrame({ "animal_id": ["a12", "a20", "a45", "a71"], "race": ["Akita", "Pug", "Boxer", "Poodle"], "weight": ["23", "19", "25", "10.4"], "pedigree": ["1","1","1","0"] })
解决方案
步骤1:指定合并键执行outer merge
必须明确指定on='animal_id'作为唯一合并键,避免因默认合并多列导致的重复行。合并时给同名列添加后缀区分来源:
merged = pd.merge(df1, df2, on='animal_id', how='outer', suffixes=('_df1', '_df2'))
步骤2:合并重复列(优先保留df2数据)
对同时存在于两个DataFrame的列(如race、weight),优先取df2的值,df2为空时回退使用df1的值:
for col in ['race', 'weight']: merged[col] = merged[f'{col}_df2'].fillna(merged[f'{col}_df1']) merged.drop([f'{col}_df1', f'{col}_df2'], axis=1, inplace=True)
步骤3:处理独有列的缺失值
将仅存在于单个DataFrame的列(如name、date、pedigree)中的NaN替换为空字符串,匹配期望格式:
merged['name'] = merged['name'].fillna('') merged['date'] = merged['date'].fillna('') merged['pedigree'] = merged['pedigree'].fillna('')
步骤4:调整列顺序并重置索引
按照期望的列顺序整理结果,可选重置索引:
merged = merged[['animal_id', 'name', 'race', 'weight', 'pedigree', 'date']] merged.reset_index(drop=True, inplace=True)
最终结果
执行上述代码后,输出的DataFrame与期望完全一致:
animal_id name race weight pedigree date 0 a12 Lucy Akita 23 1 2020-12-01 1 a17 Lola Beagle 13 2019-03-08 2 a20 Pug 19 1 3 a45 Duke Boxer 25 1 2017-10-21 4 a71 Poodle 10.4 0
重复行原因说明
如果未指定on='animal_id',Pandas会默认将所有列名相同的列作为合并键(如示例中的race)。当同一ID对应的这些列值不同时,会产生笛卡尔积导致ID重复。明确指定唯一合并键即可避免该问题。
内容的提问来源于stack exchange,提问作者Silvio Duarte
相关产品推荐
相关产品推荐

