如何比对两个同格式DataFrame提取仅DF2存在的差异数据生成DF3
实现方案
你的需求本质是取DF2相对于DF1的差集,也就是只保留DF2里有、DF1里完全找不到的行,之前merge/concat没出对结果基本是参数没选对,按你实际的业务判断规则选下面的方法就行:
- 如果你有明确的业务唯一标识(比如数据ID、条目编码这类单字段就能唯一确定一条数据的列,假设列名是
data_id),用布尔索引筛选是效率最高的方案:
# 先把DF1里已经存在的ID存成集合,集合判断存在性的速度远快于列表 existed_ids = set(DF1['data_id']) # 筛掉DF2里已经在DF1存在的行,剩下的就是你要的新增数据 DF3 = DF2[~DF2['data_id'].isin(existed_ids)].reset_index(drop=True)
- 如果没有单独的唯一ID,需要靠多个字段联合判断是否重复(比如靠
title+crawl_time两个字段一起确定同一条数据),就把多字段拼为联合唯一键再判断:
existed_keys = set(zip(DF1['title'], DF1['crawl_time'])) DF3 = DF2[~DF2.apply(lambda row: (row['title'], row['crawl_time']) in existed_keys, axis=1)].reset_index(drop=True)
- 如果没有任何业务键,要求整行所有字段值完全一模一样才算“已经在DF1存在”,就用带
indicator参数的左连接实现,别用concat后全量去重:
merge_res = DF2.merge(DF1, how='left', indicator=True) # indicator参数会自动加_merge列,left_only就代表这行只在左表(也就是DF2)里存在 DF3 = merge_res[merge_res['_merge'] == 'left_only'].drop(columns=['_merge']).reset_index(drop=True)
之前用merge/concat拿到两表所有唯一值,是因为要么选了全外连接把DF1独有的数据也带进来了,要么concat后直接全局去重没做来源过滤,自然不符合要求。
数据量超过10万行的话优先选前两种基于唯一键判断的方案,运行速度比整行merge快很多。
内容的提问来源于stack exchange,提问作者grahamie
相关产品推荐
相关产品推荐

