如何基于公共标识列合并两个 DataFrame 并优先保留第二张表的重复行

发布时间 - 2026-01-07 00:00:00    点击率:

本文介绍一种高效、可扩展的方法,使用 pd.concat() 配合布尔索引实现两表按指定列(支持单列或多列)合并:保留 df2 的全部行,仅补充 df1 中在 df2 中完全不存在的行(含重复),避免 combine_first 导致的重复膨胀问题。

在 Pandas 数据处理中,当需要“以 df2 为主、df1 为辅”合并两个结构相同的数据框(即:保留 df2 的所有行,同时只追加 df1 中在 df2 中完全未出现过的记录(包括重复行)),直接使用 combine_first 或 merge 往往会因索引对齐逻辑导致重复行被错误广播——正如示例中 A=123 的行从 df2 的 4 行 + df1 的 2 行,意外膨胀为 8 行。

正确解法是:显式分离“覆盖部分”与“补充部分”,再垂直拼接:

✅ 推荐方案:concat + 布尔索引(高效、清晰、支持多列)

import pandas as pd
from io import StringIO

# 示例数据
csv1_data = """A,B,C,D
123,xyz,S1,1111
123,xyz,S1,1111
234,mno,S3,2222
999,abc,S9,9999
999,abc,S9,9999"""

csv2_data = """A,B,C,D
123,abc,S1,1234
123,abc,S1,1234
123,abc,S1,1234
123,cde,S2,2345
234,nop,S3,
567,pqr,S5,5555"""

df1 = pd.read_csv(StringIO(csv1_data), dtype=str, keep_default_na=False)
df2 = pd.read_csv(StringIO(csv2_data), dtype=str, keep_default_na=False)

# ✅ 核心逻辑:取 df2 全部 + df1 中 A 值不在 df2.A 中的行(保留原始重复)
key_col = 'A'
result = pd.concat([
    df2,
    df1[~df1[key_col].isin(df2[key_col])]
], ignore_index=True)

print(result)

输出:

     A    B   C     D
0  123  abc  S1  1234
1  123  abc  S1  1234
2  123  abc  S1  1234
3  123  cde  S2  2345
4  234  nop  S3      
5  567  pqr  S5  5555
6  999  abc  S9  9999
7  999  abc  S9  9999

? 支持多列联合标识(动态适配)

当关键标识不止一列(如 ['A', 'B'] 或 ['A', 'A1', 'A2']),只需将列名列表传入,并利用 MultiIndex.isin() 进行精确匹配:

key_cols = ['A']  # 可动态替换为 ['A', 'B']、['A', 'A1', 'A2'] 等
# 构建 MultiIndex 进行成员判断
df1_mask = ~df1.set_index(key_cols).index.isin(df2.set_index(key_cols).index)
result = pd.concat([df2, df1[df1_mask]], ignore_index=True)
? 性能提示:该方法时间复杂度为 O(n + m),远优于基于索引重排的 combine_first(易触发内部广播),特别适合百万级数据场景。

⚠️ 注意事项与最佳实践

  • 不要用 set_index 后 combine_first:它会将 df1 中每个匹配索引的所有行与 df2 中对应索引的所有行做笛卡尔式填充,导致重复爆炸;
  • isin 判断基于值而非位置:确保 key 列类型一致(如都为字符串),避免因 int/str 混合导致匹配失败;
  • 空值(NaN)需预处理:isin() 对 NaN 默认返回 False,若业务允许 NaN 作为有效键,建议先用 fillna() 统一占位符(如 "");
  • 内存友好:全程不修改原 DataFrame,无需 .copy(),ignore_index=True 保证结果索引连续。

综上,pd.concat([df2, df1[~df1[key].isin(df2[key])]]) 是解决“主从式去重合并”的简洁、健壮且高性能的标准范式,兼顾可读性与工程可维护性。


# csv  # pandas  # NULL  # 字符串  # int  # copy  # 布尔  # 卡尔  # 只需  # 不存在  # 数据处理  # 而非  # 高性能  # 会将  # 往往会  # 都为 


相关栏目: 【 网站优化151355 】 【 网络推广146373 】 【 网络技术251813 】 【 AI营销90571


相关推荐: Laravel如何设置自定义的日志文件名_Laravel根据日期或用户ID生成动态日志【技巧】  怎么制作一个起泡网,水泡粪全漏粪育肥舍冬季氨气超过25ppm,可以有哪些措施降低舍内氨气水平?  如何在HTML表单中获取用户输入并结合JavaScript动态控制复利计算循环  Laravel Admin后台管理框架推荐_Laravel快速开发后台工具  如何在IIS管理器中快速创建并配置网站?  微信h5制作网站有哪些,免费微信H5页面制作工具?  C++时间戳转换成日期时间的步骤和示例代码  如何获取PHP WAP自助建站系统源码?  Win11怎么更改系统语言为中文_Windows11安装语言包并设为显示语言  如何在万网开始建站?分步指南解析  今日头条AI怎样推荐抢票工具_今日头条AI抢票工具推荐算法与筛选【技巧】  成都网站制作公司哪家好,四川省职工服务网是做什么用?  如何挑选优质建站一级代理提升网站排名?  购物网站制作费用多少,开办网上购物网站,需要办理哪些手续?  今日头条微视频如何找选题 今日头条微视频找选题技巧【指南】  智能起名网站制作软件有哪些,制作logo的软件?  如何基于PHP生成高效IDC网络公司建站源码?  Laravel如何使用Scope本地作用域_Laravel模型常用查询逻辑封装技巧【手册】  Laravel如何自定义分页视图?(Pagination示例)  制作公司内部网站有哪些,内网如何建网站?  桂林网站制作公司有哪些,桂林马拉松怎么报名?  实现点击下箭头变上箭头来回切换的两种方法【推荐】  Laravel如何实现数据导出到PDF_Laravel使用snappy生成网页快照PDF【方案】  PHP怎么接收前端传的文件路径_处理文件路径参数接收方法【汇总】  Laravel如何创建自定义Artisan命令?(代码示例)  Python面向对象测试方法_mock解析【教程】  ChatGPT怎么生成Excel公式_ChatGPT公式生成方法【指南】  Laravel如何使用缓存系统提升性能_Laravel缓存驱动和应用优化方案  高端网站建设与定制开发一站式解决方案 中企动力  1688铺货到淘宝怎么操作 1688一键铺货到自己店铺详细步骤  历史网站制作软件,华为如何找回被删除的网站?  网站图片在线制作软件,怎么在图片上做链接?  如何快速生成ASP一键建站模板并优化安全性?  LinuxShell函数封装方法_脚本复用设计思路【教程】  如何选择可靠的免备案建站服务器?  如何快速查询域名建站关键信息?  Win11摄像头无法使用怎么办_Win11相机隐私权限开启教程【详解】  教你用AI将一段旋律扩展成一首完整的曲子  JS实现鼠标移上去显示图片或微信二维码  如何在云虚拟主机上快速搭建个人网站?  如何在IIS中新建站点并配置端口与物理路径?  JS经典正则表达式笔试题汇总  猪八戒网站制作视频,开发一个猪八戒网站,大约需要多少?或者自己请程序员,需要什么程序员,多少程序员能完成?  5种Android数据存储方式汇总  装修招标网站设计制作流程,装修招标流程?  Laravel全局作用域是什么_Laravel Eloquent Global Scopes应用指南  用yum安装MySQLdb模块的步骤方法  Laravel如何升级到最新的版本_Laravel版本升级流程与兼容性处理  Python并发异常传播_错误处理解析【教程】  如何在IIS中配置站点IP、端口及主机头?