Pandas中实现Left Join并留存未匹配的右表数据
解决Pandas左连接拆分匹配数据与右表未匹配数据的问题
嘿,我明白你想要的效果了——既要拿到左右表匹配的合并结果,又要把右表里没匹配上左表的数据单独存起来对吧?其实你用pd.merge加indicator的思路是对的,可能只是筛选和后续处理的步骤没到位,我来给你捋清楚:
首先,先明确我们的目标:
merged表:仅包含左右表通过key1、key2匹配上的行saveForLater表:仅包含右表中没有在左表找到匹配键的行
步骤1:构建示例数据(还原你给出的案例)
import pandas as pd # 左表df1(对应你提到的dfStore) df1 = pd.DataFrame({ 'key1': [1, 2], 'key2': [2, 2], 'val1': [1, 1], 'val2': [1, 2], 'val3': [2, 2] }) # 右表df2(对应你提到的dfMap) df2 = pd.DataFrame({ 'key1': [1, 1, 3], 'key2': [2, 1, 2], 'val1': ['a', 'a', 'a'], 'val2': ['b', 'b', 'b'], 'val3': ['c', 'c', 'c'] })
步骤2:执行带indicator的全外连接
必须用how='outer'才能同时捕获三种匹配状态:left_only(仅左表有)、both(左右都有)、right_only(仅右表有)。同时用suffixes区分左右表的同名字段:
merged_full = pd.merge( df1, df2, how='outer', on=["key1", "key2"], indicator=True, suffixes=('_left', '_right') )
步骤3:提取匹配的merged表
筛选_merge列值为both的行,就是左右表匹配上的数据,最后删除辅助列_merge:
merged = merged_full[merged_full['_merge'] == 'both'].drop(columns=['_merge']) # 如果需要合并同名字段(比如val1_left和val1_right),可以根据需求处理,比如保留右表值 merged = merged.drop(columns=['val1_left', 'val2_left', 'val3_left']).rename( columns={'val1_right': 'val1', 'val2_right': 'val2', 'val3_right': 'val3'} )
步骤4:提取右表未匹配的saveForLater表
筛选_merge列值为right_only的行,然后只保留右表原有的字段即可:
saveForLater = merged_full[merged_full['_merge'] == 'right_only'].drop(columns=['_merge']) # 移除左表的空值列,只保留右表的字段 saveForLater = saveForLater[df2.columns]
验证结果
merged表会包含key1=1, key2=2的匹配行saveForLater表会包含key1=1, key2=1和key1=3, key2=2的行(对应你提到的未匹配数据)
你之前的方法可能是用了how='left'而不是outer,导致无法捕获right_only的行,或者在筛选后没有正确清理列名。按照上面的步骤就能精准拆分出你需要的两个表啦!
内容的提问来源于stack exchange,提问作者Swifty2Point0
相关产品推荐
相关产品推荐

