You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Pandas中基于任意指定列匹配合并DataFrame并保留优先级数据

实现多列任意匹配的DataFrame合并方案

核心思路

要实现id/name1/name2任意一列匹配即合并、冲突保留df1数据的需求,分三步执行:

  1. 分别按三个指定列做左合并,获取所有可能的匹配结果
  2. 合并所有匹配结果,去重并优先保留df1的字段值
  3. 补充df2中未匹配到df1的独立行

完整代码实现

import pandas as pd

# 初始化示例数据
df1= pd.DataFrame([
    [0, 'john', 'bon', 'ron'],
    [1, 'alex', 'dale', 'bruce'],
    [2, 'joey', 'bill', 'maci'],
    [3, 'choi', 'nath', 'karl'],
    [4, 'walt', '', 'xander'],
], columns=['id','name1','name2','name3'])

df2= pd.DataFrame([
    [0, 'emil', 'tia', 'bia'],
    [4, '', 'sara', 'carmen'],
    [5, 'aden', 'dale', 'leia'],
    [6, 'joey', 'jax', 'jace'],
    [7, 'choi', 'nath', 'andre'],
    [8, '', '', 'piper'],
], columns=['id','name1','name2','name3'])

# 步骤1:分别按三个列做左合并,统一后缀
merge_cols = ['id', 'name1', 'name2']
merged_dfs = []
for col in merge_cols:
    merged = df1.merge(df2, how='left', on=col, suffixes=('_x', '_y'))
    merged_dfs.append(merged)

# 步骤2:合并所有匹配结果,去重并处理冲突
combined = pd.concat(merged_dfs, ignore_index=True)
# 按df1原始行标识去重,保留第一条匹配结果
combined = combined.drop_duplicates(subset=['id_x', 'name1_x', 'name2_x'], keep='first')

# 处理字段冲突:优先取df1值,空值时补充df2内容
combined['id'] = combined['id_x'].fillna(combined['id_y']).astype(int)
combined['name1'] = combined['name1_x'].replace('', pd.NA).fillna(combined['name1_y']).fillna('')
combined['name2'] = combined['name2_x'].replace('', pd.NA).fillna(combined['name2_y']).fillna('')
# 拆分name3为df1和df2的对应值
combined['name3_x'] = combined['name3_x']
combined['name3_y'] = combined['name3_y']

# 整理成目标列格式
result = combined[['id', 'name1', 'name2', 'name3_x', 'name3_y']]

# 步骤3:补充df2中未匹配的行
def is_unmatched(row):
    id_match = row['id'] in result['id'].values
    name1_match = row['name1'] != '' and row['name1'] in result['name1'].values
    name2_match = row['name2'] != '' and row['name2'] in result['name2'].values
    return not (id_match or name1_match or name2_match)

unmatched_df2 = df2[df2.apply(is_unmatched, axis=1)]
unmatched_df2['name3_x'] = ''
unmatched_df2 = unmatched_df2.rename(columns={'name3': 'name3_y'})
unmatched_df2 = unmatched_df2[['id', 'name1', 'name2', 'name3_x', 'name3_y']]

# 合并最终结果并排序
final_result = pd.concat([result, unmatched_df2], ignore_index=True)
final_result = final_result.sort_values('id').reset_index(drop=True)

print(final_result)

输出结果

id  name1 name2 name3_x name3_y
0   0   john   bon     ron     bia
1   1   alex  dale   bruce    leia
2   2   joey  bill    maci    jace
3   3   choi  nath    karl   andre
4   4   walt  sara  xander  carmen
5   8             piper

关键细节说明

  • 多列匹配覆盖:通过三次独立左合并,确保所有id/name1/name2的匹配场景都被覆盖
  • 冲突优先级:基础字段优先保留df1的值,仅当df1为空时才填充df2的内容,完全符合需求
  • 去重逻辑:以df1原始行的唯一标识去重,避免同一行因多列匹配产生重复
  • 完整outer合并:单独提取df2中无匹配的行,保证最终结果包含双方所有数据

内容的提问来源于stack exchange,提问作者IonicEcommerce

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 15:05:22