如何优雅获取Pandas中dfB独有的同列DataFrame记录?
提取dfB中不存在于dfA的记录的优雅方案
我来给你分享几个简洁高效、符合Pythonic风格的Pandas实现方法,完美满足你只提取dfB独有的记录的需求。先拿个示例数据来演示:
假设我们有两个结构完全一致的DataFrame:
import pandas as pd dfA = pd.DataFrame({ 'id': [1, 2, 3], 'value': [10, 20, 30] }) dfB = pd.DataFrame({ 'id': [2, 3, 4, 5], 'value': [20, 30, 40, 50] })
我们期望得到的结果是dfB中id为4、5的两行记录。
方法一:使用merge + indicator(推荐,高效清晰)
这是最直观也最适合大数据集的方法,利用Pandas的merge功能自带的标记特性:
# 以所有列为键,左连接dfB和dfA,添加来源标记列 merged_df = dfB.merge(dfA, on=list(dfA.columns), how='left', indicator=True) # 筛选出仅存在于dfB的行,然后删除标记列 result = merged_df[merged_df['_merge'] == 'left_only'].drop('_merge', axis=1)
原理说明:
how='left'确保保留dfB的所有行,匹配不到dfA的行也会保留indicator=True会自动添加_merge列,标记该行的来源:left_only(仅dfB有)、right_only(仅dfA有)、both(两边都有)- 最后筛选
left_only的行,就是我们要的dfB独有的记录
方法二:使用concat + drop_duplicates
通过拼接两个DataFrame并标记来源,再去重筛选:
# 给每个DataFrame添加来源标记,然后拼接 combined = pd.concat([dfA.assign(source='A'), dfB.assign(source='B')]) # 按数据列去重,只保留在整个集合中仅出现一次的行(即两边独有的) unique_rows = combined.drop_duplicates(subset=list(dfA.columns), keep=False) # 筛选出来源为B的行,删除标记列得到结果 result = unique_rows[unique_rows['source'] == 'B'].drop('source', axis=1)
原理说明:
assign(source='A')给dfA的每一行添加一个标记列,方便后续区分来源drop_duplicates(subset=..., keep=False)会移除所有在数据列上重复的行,只留下两边各自独有的记录- 最后筛选来源为B的行,就是dfB中不在dfA的记录
方法三:使用isin + all(axis=1)(适合小数据集)
如果你的数据集不大,这个一行流的写法也很简洁:
# 检查dfB的每一行是否完全存在于dfA中,取反后筛选 result = dfB[~dfB.isin(dfA.to_dict('list')).all(axis=1)]
原理说明:
dfA.to_dict('list')把dfA转换成列名对应值列表的字典dfB.isin(...)生成一个布尔DataFrame,每个元素表示是否在对应列的列表里all(axis=1)检查整行所有元素都匹配(即该行在dfA中存在),~取反后就是dfB中独有的行
这三种方法里,方法一是最推荐的——不仅代码可读性高,而且Pandas的merge底层做了优化,处理大数据集时效率远高于方法三。如果你的DataFrame有重复行,这三个方法也都能正确保留dfB中重复且不在dfA里的行,完全符合你的需求。
内容的提问来源于stack exchange,提问作者Idodo
相关产品推荐
相关产品推荐

