Pandas合并两个DataFrame 保留df1数据按同值首次出现对齐
Pandas 两表按指定规则关联实现
需求说明
- 关联df1、df2两个DataFrame时需保留df1的全部数据,不能出现行丢失
- df2中与df1匹配的值(即
df2.C == df1.A),仅对齐到df1中该值首次出现的行,df1中后续重复出现的同值行不关联df2数据,对应关联列留空 - 常规
inner连接会丢失df1未匹配数据,普通左连接会将df1中所有同值行都与df2做笛卡尔积匹配,不符合预期
实现代码
import pandas as pd # 原始df1、df2定义 df1 = pd.DataFrame([ {'A':123456, 'B':'4/1/22'}, {'A':234567, 'B':'4/1/22'}, {'A':345678, 'B':'4/1/22'}, {'A':567890, 'B':'4/1/22'}, {'A':234567, 'B':'4/3/22'}, {'A':456789,'B':'4/4/22'} ]) df2 = pd.DataFrame([ {'C':159357,'D':'4/1/22'}, {'C':234567,'D':'4/1/22'}, {'C':234567,'D':'4/3/22'}, {'C':234567,'D':'4/2/22'}, {'C':234567,'D':'4/3/22'}, {'C':456789,'D':'4/1/22'}, {'C':654852,'D':'4/7/22'}, {'C':753951,'D':'4/1/22'} ]) # 标记df1中每个A值首次出现的行 df1['is_first'] = ~df1['A'].duplicated(keep='first') # 拆分为首次出现行、非首次出现行两部分 first_occur_rows = df1[df1['is_first']].drop(columns='is_first') non_first_rows = df1[~df1['is_first']].drop(columns='is_first').assign(C=None, D=None) # 仅对首次出现的行执行左连接匹配df2数据 matched_part = first_occur_rows.merge( df2, how='left', left_on='A', right_on='C' ) # 拼接匹配结果和非首次行,按原始索引排序还原df1的原有顺序 final_result = pd.concat([matched_part, non_first_rows]).sort_index().reset_index(drop=True)
实现逻辑说明
- 用
duplicated(keep='first')标记每个值的首次出现位置,避免重复值行参与匹配 - 仅对首次出现的锚点行做左连接,保证df2的匹配数据全部挂在对应值第一次出现的位置
- 非首次出现的df1行直接保留,关联列填充空值,不会丢失任何df1原有数据
- 拼接后按原始索引排序,完全保留df1原有的行顺序,匹配到的df2多行数据会连续排列在对应锚点行的位置
内容的提问来源于stack exchange,提问作者sheryll
相关产品推荐
相关产品推荐

