当前位置:首页 > 文章列表 > 文章 > python教程 > PythonDataFrame合并:concat与merge对比解析

PythonDataFrame合并:concat与merge对比解析

2025-07-11 12:12:28 0浏览 收藏

在文章实战开发的过程中,我们经常会遇到一些这样那样的问题,然后要卡好半天,等问题解决了才发现原来一些细节知识点还是没有掌握好。今天golang学习网就整理分享《Python合并DataFrame:concat与merge对比详解》,聊聊,希望可以帮助到正在努力赚钱的你。

Python中合并多个DataFrame的核心方法有两种:一是使用pd.concat进行堆叠式合并,二是使用pd.merge进行关联式合并。pd.concat主要用于沿行或列方向堆叠数据,适用于结构相似的数据整合,关键参数包括objs(待合并对象)、axis(合并方向)、join(索引/列对齐方式)及ignore_index(是否重置索引)。pd.merge则基于共同键进行数据关联,支持内连接、左连接、右连接和外连接,核心参数有left/right(待合并的两个DataFrame)、how(连接类型)、on/left_on/right_on(连接键)及suffixes(列名冲突处理)。选择concat时应确保数据结构一致或索引对齐,而merge适用于存在逻辑关联的数据整合,需注意键列清洗与连接类型选择。两者在性能上各有侧重,concat适合垂直或水平拼接,merge适合基于键的关系型合并,实际应用中应根据数据特征和需求合理选用。

Python中如何合并多个DataFrame?concat与merge对比指南

Python中合并多个DataFrame,本质上无非两种核心操作:一种是像堆积木一样,把数据框一个接一个地堆叠起来,这通常是 pd.concat 的职责;另一种则是像给不同表做“联姻”,根据某些共同的“媒人”(键)把它们关联起来,这正是 pd.merge 的强项。理解它们各自的适用场景和内在逻辑,是高效处理数据的基础。

Python中如何合并多个DataFrame?concat与merge对比指南

解决方案

在Python的pandas库中,合并多个DataFrame主要依赖于pd.concat()pd.merge()这两个函数。它们解决的是不同类型的数据整合问题。

Python中如何合并多个DataFrame?concat与merge对比指南

pd.concat() 这个函数主要用于沿着某个轴(行或列)堆叠或连接DataFrame。你可以把它想象成把几个表格直接首尾相连,或者并排摆放。

  • 核心功能: 堆叠(append)或并排连接(concatenate)。
  • 主要参数:
    • objs: 一个DataFrame对象的序列或字典,这是要合并的数据框列表。
    • axis: 决定合并方向。axis=0(默认)表示按行堆叠,即增加行;axis=1表示按列并排,即增加列。
    • join: 当按列合并时,如何处理不完全匹配的索引。'outer'(默认)会保留所有索引,缺失值用NaN填充;'inner'只保留共同的索引。当按行合并时,如何处理列。'outer'会保留所有列,缺失值用NaN填充;'inner'只保留共同的列。
    • ignore_index: 如果设为True,合并后的DataFrame会重置索引,这在堆叠操作中非常有用,可以避免重复索引。

示例:

Python中如何合并多个DataFrame?concat与merge对比指南
import pandas as pd

df1 = pd.DataFrame({'A': ['A0', 'A1'], 'B': ['B0', 'B1']}, index=[0, 1])
df2 = pd.DataFrame({'A': ['A2', 'A3'], 'B': ['B2', 'B3']}, index=[2, 3])
df3 = pd.DataFrame({'C': ['C4', 'C5'], 'D': ['D4', 'D5']}, index=[4, 5])

# 按行堆叠 (默认 axis=0)
result_rows = pd.concat([df1, df2])
# print(result_rows)

# 按列并排 (axis=1)
# 注意:这里会根据索引进行对齐,如果索引不同,会填充NaN
result_cols = pd.concat([df1, df3], axis=1)
# print(result_cols)

# 按行堆叠并重置索引
result_reset_index = pd.concat([df1, df2], ignore_index=True)
# print(result_reset_index)

pd.merge() 这个函数用于通过一个或多个键(列)将两个DataFrame连接起来,类似于SQL中的JOIN操作。它基于列的值进行匹配,而不是简单地堆叠。

  • 核心功能: 根据共同列(或索引)进行数据关联。
  • 主要参数:
    • left, right: 要合并的两个DataFrame。
    • how: 指定合并类型。
      • 'inner'(默认):只保留左右DataFrame中键都存在的行。
      • 'left':保留左DataFrame的所有行,右DataFrame中匹配的行,不匹配的用NaN填充。
      • 'right':保留右DataFrame的所有行,左DataFrame中匹配的行,不匹配的用NaN填充。
      • 'outer':保留左右DataFrame中的所有行,不匹配的用NaN填充。
    • on: 用于连接的列名(如果左右DataFrame的键列名相同)。
    • left_on, right_on: 如果左右DataFrame的键列名不同,分别指定。
    • suffixes: 当左右DataFrame有相同列名(非键列)时,用于区分这些列的后缀。

示例:

df_employees = pd.DataFrame({
    'employee_id': [1, 2, 3, 4],
    'name': ['Alice', 'Bob', 'Charlie', 'David'],
    'department_id': [101, 102, 101, 103]
})

df_departments = pd.DataFrame({
    'department_id': [101, 102, 104],
    'department_name': ['HR', 'IT', 'Finance']
})

# 内连接:只保留员工和部门ID都匹配的记录
merged_inner = pd.merge(df_employees, df_departments, on='department_id', how='inner')
# print(merged_inner)

# 左连接:保留所有员工信息,匹配部门信息
merged_left = pd.merge(df_employees, df_departments, on='department_id', how='left')
# print(merged_left)

concat 适用场景与常见误区

我个人觉得,pd.concat 最能体现其价值的地方,就是当你手里有一堆结构相同或者非常相似的数据碎片时。比如,你从数据库里分批导出了按月份划分的销售数据,或者从不同渠道抓取了格式一致的用户行为日志,这时候,把它们堆叠起来形成一个完整的、更大的数据集,concat 简直是神来之笔。它尤其适合处理时间序列数据,或者当你需要把多个文件(例如CSV)的内容合并成一个DataFrame时。

然而,concat 也不是没有坑。最常见的误区,我觉得就是索引的处理。如果你只是简单地 pd.concat([df1, df2]),而这两个DataFrame又恰好有相同的索引值(比如都是从0开始),那么合并后的结果就会出现重复索引。这在后续的数据处理中,比如使用 loc 进行选择时,可能会导致意想不到的结果。所以,我几乎成了 ignore_index=True 的忠实拥趸,尤其是在做行堆叠时,它能帮你自动生成一个干净、连续的新索引。

# 常见误区:索引重复
df_a = pd.DataFrame({'value': [10, 20]}, index=[0, 1])
df_b = pd.DataFrame({'value': [30, 40]}, index=[0, 1]) # 同样有0, 1索引

# 结果索引会重复
bad_concat = pd.concat([df_a, df_b])
# print(bad_concat)
# print(bad_concat.loc[0]) # 这会返回两行!

# 解决方案:重置索引
good_concat = pd.concat([df_a, df_b], ignore_index=True)
# print(good_concat)
# print(good_concat.loc[0]) # 只返回一行

另一个小陷阱是列的不匹配。当你 axis=0 进行行堆叠时,如果各个DataFrame的列名不完全一致,concat 默认会采取 join='outer' 策略,也就是保留所有列,不匹配的地方用 NaN 填充。这通常是期望的行为,但如果你只想要那些所有DataFrame都共有的列,那就得明确指定 join='inner'。我有时候会忘记这一点,结果发现合并出来的数据框多了很多 NaN 列,回头检查才发现是列名没对齐。

df_sales = pd.DataFrame({'product': ['A', 'B'], 'price': [100, 200]})
df_returns = pd.DataFrame({'product': ['A', 'C'], 'quantity': [1, 2]})

# 默认 outer join,会保留所有列
outer_concat = pd.concat([df_sales, df_returns], axis=0)
# print(outer_concat)

# inner join,只保留共同列(product)
inner_concat = pd.concat([df_sales, df_returns], axis=0, join='inner')
# print(inner_concat)

merge 的连接类型与复杂性处理

说到合并,其实除了最直接的拼接,我们更多时候面对的是数据间的“联姻”,这也就是 merge 的用武之地了。pd.merge 最强大的地方在于它能够模拟SQL的各种连接操作,通过 how 参数来精确控制连接的逻辑。

how 参数的奥秘:

  • how='inner' (内连接):这是默认选项,也是最严格的。它只保留左右两个DataFrame中键都存在的行。你可以想象成,只有当两个数据源都能找到匹配的对象时,这条记录才会被纳入结果。
  • how='left' (左连接):以左边的DataFrame为基准。它会保留左DataFrame的所有行,并尝试在右DataFrame中找到匹配的行。如果找到了,就合并;如果没找到,右DataFrame对应的列就用 NaN 填充。这在你想保留所有“主”数据(比如所有客户信息),然后附加“次要”数据(比如他们的订单历史)时非常有用。
  • how='right' (右连接):与左连接相反,以右边的DataFrame为基准。保留右DataFrame的所有行,并尝试在左DataFrame中找到匹配的行。
  • how='outer' (外连接):这是最“包容”的连接方式。它会保留左右两个DataFrame中的所有行。如果某个键只存在于一个DataFrame中,另一个DataFrame对应的列就会用 NaN 填充。这在你想看到所有可能的组合,即使数据不完全匹配时,会很有帮助。
# 示例数据
df_users = pd.DataFrame({
    'user_id': [1, 2, 3, 4],
    'username': ['alpha', 'beta', 'gamma', 'delta']
})

df_orders = pd.DataFrame({
    'order_id': [101, 102, 103, 104],
    'user_id': [1, 2, 5, 1], # user_id 5 不在 df_users 中
    'amount': [100, 150, 200, 120]
})

# 内连接:只显示有订单的用户
inner_join = pd.merge(df_users, df_orders, on='user_id', how='inner')
# print("\nInner Join:\n", inner_join)

# 左连接:显示所有用户,以及他们的订单(如果没有则为NaN)
left_join = pd.merge(df_users, df_orders, on='user_id', how='left')
# print("\nLeft Join:\n", left_join)

# 右连接:显示所有订单,以及对应的用户信息(如果用户不存在则为NaN)
right_join = pd.merge(df_users, df_orders, on='user_id', how='right')
# print("\nRight Join:\n", right_join)

# 外连接:显示所有用户和所有订单,无论是否匹配
outer_join = pd.merge(df_users, df_orders, on='user_id', how='outer')
# print("\nOuter Join:\n", outer_join)

处理多键合并或非等值连接: 当需要根据多个列进行合并时,merge 同样游刃有余。你只需要把 onleft_onright_on 参数的值从单个字符串变成一个字符串列表即可。比如,如果你需要根据 (department_id, employee_name) 来匹配数据,那就 on=['department_id', 'employee_name']

df_emp_details = pd.DataFrame({
    'emp_id': [1, 2, 3],
    'first_name': ['John', 'Jane', 'Peter'],
    'last_name': ['Doe', 'Smith', 'Jones']
})

df_emp_salaries = pd.DataFrame({
    'employee_id': [1, 2, 3],
    'first': ['John', 'Jane', 'Peter'],
    'last': ['Doe', 'Smith', 'Jones'],
    'salary': [50000, 60000, 70000]
})

# 多键合并
multi_key_merge = pd.merge(df_emp_details, df_emp_salaries,
                           left_on=['emp_id', 'first_name', 'last_name'],
                           right_on=['employee_id', 'first', 'last'],
                           how='inner')
# print("\nMulti-key Merge:\n", multi_key_merge)

至于非等值连接(比如 A.value > B.value),pd.merge 本身并不直接支持,它主要用于等值连接。如果真有这样的需求,我通常会考虑几种变通方法:要么是先进行一个宽泛的合并,然后用布尔索引进行筛选;要么是利用 pd.merge_asof(针对时间序列的近似匹配);再复杂一点,可能就要回到循环或者自定义函数,但那已经超出了 merge 的核心范畴了。

性能考量与最佳实践:何时选择 concatmerge

在处理大数据量时,concatmerge 的性能表现确实值得掰扯一下。这就像是开车,你知道目的地,但得选对路和交通工具。

性能表现:

  • concat: 对于简单的行堆叠,concat 通常非常高效,因为它主要是内存块的拼接。尤其是当所有DataFrame的列结构完全一致时,它的开销相对较小。然而,如果需要进行大量的列级别合并(axis=1),并且索引不完全对齐,那么 concat 可能需要在内部进行大量的重索引和数据填充,这会消耗更多的时间和内存。
  • merge: merge 的性能通常取决于你选择的连接类型 (how) 以及用于连接的键列。在内部,pandas会尝试优化,比如使用哈希表或排序合并算法。如果键列已经被索引(通过 df.set_index()),或者键列的数据类型是高效的(比如整数或分类类型),merge 的性能会更好。但如果键列是字符串且非常长,或者数据量巨大且键列没有优化,merge 可能会变得相当慢,因为它需要进行大量的字符串比较和哈希计算。

选择哪一个?这其实是个“哲学问题”,答案完全取决于你的数据关系和目标。

我的经验是:

  • 选择 concat 的时机:

    • 数据结构一致,需要垂直扩展: 你有多个DataFrame,它们拥有相同的列名和数据类型,你只是想把它们堆叠起来,形成一个更长的DataFrame。比如,每日销售数据文件,你需要把它们合并成月度或年度报告。
    • 需要水平扩展,且索引能够对齐: 你有多个DataFrame,它们有相同的行索引,你只是想把它们并排放置,增加列。比如,一个DataFrame有用户基本信息,另一个有用户的联系方式,它们的索引都是 user_id
    • 数据来源分散,但内容同质: 比如爬取了多个网页,每个网页的数据结构都一样,需要汇总。
  • 选择 merge 的时机:

    • 数据存在关联关系,需要水平整合: 你的数据分布在不同的DataFrame中,但它们之间存在逻辑上的关联(比如通过 customer_idproduct_id)。你需要根据这些关联键来组合信息。这就像数据库中的表连接。
    • 需要根据特定条件筛选或补充数据: 你想根据某个DataFrame的完整性来决定合并结果(如 left joinright join),或者你想找出所有匹配和不匹配的项(如 outer join)。
    • 数据来源异构,但逻辑相关: 比如一个DataFrame是订单明细,另一个是产品信息,你需要把产品名称、价格等信息加到订单明细中。

最佳实践建议:

  1. 数据清洗先行: 在进行任何合并操作之前,务必确保你的键列(或其他需要对齐的列)是干净的。检查数据类型是否一致,是否存在前导/尾随空格,大小写是否统一。一个小小的差异都可能导致 merge 失败或 concat 产生 NaN
  2. 明确 how 参数: 对于 merge,一定要想清楚你需要哪种连接类型。是只保留匹配项 (inner),还是保留左边所有 (left),或者所有 (outer)?这直接决定了结果数据集的完整性和大小。
  3. 索引的考量:
    • 对于 concat(axis=0),如果原始索引不重要,总是考虑 ignore_index=True 来避免索引重复。
    • 对于 merge,如果你想基于索引进行合并,可以使用 left_index=Trueright_index=True。如果键列是索引,并且数据量很大,pandas在某些情况下会利用索引的有序性来加速合并。
  4. 内存管理: 当处理非常大的DataFrame时,合并操作可能会消耗大量内存。如果遇到内存不足的问题,可以考虑:
    • 逐块处理数据(例如,使用 pd.read_csv(chunksize=...))。
    • 优化DataFrame的数据类型(例如,使用 category 类型代替 object 类型来存储重复的字符串)。
    • 仅选择必要的列进行合并,减少不必要的内存开销。

总的来说,concatmerge 都是pandas数据处理的基石,它们解决的问题截然不同。选择合适的工具,理解其背后的逻辑和潜在的“坑”,能让你在数据处理的道路上走得更稳更快。

终于介绍完啦!小伙伴们,这篇关于《PythonDataFrame合并:concat与merge对比解析》的介绍应该让你收获多多了吧!欢迎大家收藏或分享给更多需要学习的朋友吧~golang学习网公众号也会发布文章相关知识,快来关注吧!

软件业前5月利润增14.2%软件业前5月利润增14.2%
上一篇
软件业前5月利润增14.2%
Python视频流处理:OpenCV帧操作详解
下一篇
Python视频流处理:OpenCV帧操作详解
查看更多
最新文章
查看更多
课程推荐
  • 前端进阶之JavaScript设计模式
    前端进阶之JavaScript设计模式
    设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
    542次学习
  • GO语言核心编程课程
    GO语言核心编程课程
    本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
    509次学习
  • 简单聊聊mysql8与网络通信
    简单聊聊mysql8与网络通信
    如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
    497次学习
  • JavaScript正则表达式基础与实战
    JavaScript正则表达式基础与实战
    在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
    487次学习
  • 从零制作响应式网站—Grid布局
    从零制作响应式网站—Grid布局
    本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
    484次学习
查看更多
AI推荐
  • AI边界平台:智能对话、写作、画图,一站式解决方案
    边界AI平台
    探索AI边界平台,领先的智能AI对话、写作与画图生成工具。高效便捷,满足多样化需求。立即体验!
    392次使用
  • 讯飞AI大学堂免费AI认证证书:大模型工程师认证,提升您的职场竞争力
    免费AI认证证书
    科大讯飞AI大学堂推出免费大模型工程师认证,助力您掌握AI技能,提升职场竞争力。体系化学习,实战项目,权威认证,助您成为企业级大模型应用人才。
    405次使用
  • 茅茅虫AIGC检测:精准识别AI生成内容,保障学术诚信
    茅茅虫AIGC检测
    茅茅虫AIGC检测,湖南茅茅虫科技有限公司倾力打造,运用NLP技术精准识别AI生成文本,提供论文、专著等学术文本的AIGC检测服务。支持多种格式,生成可视化报告,保障您的学术诚信和内容质量。
    542次使用
  • 赛林匹克平台:科技赛事聚合,赋能AI、算力、量子计算创新
    赛林匹克平台(Challympics)
    探索赛林匹克平台Challympics,一个聚焦人工智能、算力算法、量子计算等前沿技术的赛事聚合平台。连接产学研用,助力科技创新与产业升级。
    641次使用
  • SEO  笔格AIPPT:AI智能PPT制作,免费生成,高效演示
    笔格AIPPT
    SEO 笔格AIPPT是135编辑器推出的AI智能PPT制作平台,依托DeepSeek大模型,实现智能大纲生成、一键PPT生成、AI文字优化、图像生成等功能。免费试用,提升PPT制作效率,适用于商务演示、教育培训等多种场景。
    548次使用
微信登录更方便
  • 密码登录
  • 注册账号
登录即同意 用户协议隐私政策
返回登录
  • 重置密码