合并含重复ID的两个DataFrame并保留DataFrame B的status字段值
解决方案:优先保留更新数据源的合并方法
这是个典型的优先取新数据源字段值的合并场景,用Pandas可以轻松实现,我给你一步步拆解:
步骤1:准备示例数据
先把你给出的示例DataFrame用代码还原出来:
import pandas as pd import numpy as np # 创建DataFrame A df_a = pd.DataFrame({ 'ID': [1, 2, 3], 'status': ['open', 'closed', 'pending'], 'date': ['01.01.2020', '01.01.2020', '01.01.2020'], 'someColumnA': ['A', 'B', 'C'] }) # 创建DataFrame B df_b = pd.DataFrame({ 'ID': [1, 2, 4], 'status': ['closed', 'closed', 'pending'], 'date': ['01.01.2020', '01.01.2020', '01.01.2020'], 'someColumnB': ['rr', 'tt', 'zz'] })
步骤2:全外连接并区分重复列
先做全外连接,用suffixes参数给来自A和B的重复列加上后缀,方便后续区分:
merged = pd.merge(df_a, df_b, on='ID', how='outer', suffixes=('_A', '_B'))
这一步之后,你会看到类似这样的中间结果:
| ID | status_A | date_A | someColumnA | status_B | date_B | someColumnB |
|---|---|---|---|---|---|---|
| 1 | open | 01.01.2020 | A | closed | 01.01.2020 | rr |
| 2 | closed | 01.01.2020 | B | closed | 01.01.2020 | tt |
| 3 | pending | 01.01.2020 | C | NaN | NaN | NaN |
| 4 | NaN | NaN | NaN | pending | 01.01.2020 | zz |
步骤3:处理冲突字段(优先取B的值)
对于status这种需要优先保留B的字段,用np.where判断:如果B的status不为空就用B的,否则用A的:
merged['status'] = np.where(merged['status_B'].notna(), merged['status_B'], merged['status_A'])
对于共享的date字段,如果你希望同样优先B(或者取任意存在的值),可以用combine_first:
merged['date'] = merged['date_B'].combine_first(merged['date_A'])
步骤4:补全独有列的缺失值
把someColumnA和someColumnB的缺失值替换成你需要的'-':
merged['someColumnA'] = merged['someColumnA'].fillna('-') merged['someColumnB'] = merged['someColumnB'].fillna('-')
步骤5:清理并调整列顺序
删除中间生成的带后缀的列,然后调整列顺序到你期望的样子:
final_df = merged[['ID', 'status', 'date', 'someColumnA', 'someColumnB']]
最终结果
运行完上面的代码,你会得到和你期望完全一致的DataFrame:
| ID | status | date | someColumnA | someColumnB |
|---|---|---|---|---|
| 1 | closed | 01.01.2020 | A | rr |
| 2 | closed | 01.01.2020 | B | tt |
| 3 | pending | 01.01.2020 | C | - |
| 4 | pending | 01.01.2020 | - | zz |
额外说明
如果以后还有其他类似的冲突字段(比如除了status还有其他需要优先取B的列),只需要重复步骤3的逻辑即可,非常灵活。
内容的提问来源于stack exchange,提问作者Cruden10
相关产品推荐
相关产品推荐

