Python pandas合并连接指南

 更新时间:2026年08月05日 09:14:06   作者:菜冻鱼  
还在为pandas合并表格发愁?本文详细对比了merge、join、concat、merge_asof等方法,通过SQL对照和实例讲解四种连接方式,帮你快速掌握数据拼接技巧,解决索引对齐和时间序列匹配等常见难题

Pandas 提供了多种表合并方式:merge(类 SQL 的 JOIN)、join(按索引合并)、concat(轴向拼接)、combine(按规则合并)等。

pd.merge()— 最通用的合并 

基本用法

import pandas as pd

left = pd.DataFrame({
    'key': ['A', 'B', 'C', 'D'],
    'value_left': [1, 2, 3, 4]
})
right = pd.DataFrame({
    'key': ['B', 'C', 'D', 'E'],
    'value_right': [20, 30, 40, 50]
})

# 默认内连接(inner join)—— 取交集
result = pd.merge(left, right, on='key')
# key  value_left  value_right
#   B           2           20
#   C           3           30
#   D           4           40

how参数 — 四种连接方式

# 内连接:只保留两表都存在的 key
pd.merge(left, right, on='key', how='inner')

# 左连接:保留左表所有行
pd.merge(left, right, on='key', how='left')

# 右连接:保留右表所有行
pd.merge(left, right, on='key', how='right')

# 外连接:保留两表所有行(并集)
pd.merge(left, right, on='key', how='outer')

# 交叉连接:笛卡尔积(pandas 1.2+)
pd.merge(left, right, how='cross')
how行为SQL 等价
'inner'取交集(默认)INNER JOIN
'left'保留左表全部LEFT JOIN
'right'保留右表全部RIGHT JOIN
'outer'保留两表全部(并集)FULL OUTER JOIN
'cross'笛卡尔积CROSS JOIN

多列连接

left = pd.DataFrame({
    '部门': ['技术', '技术', '销售'],
    '城市': ['北京', '上海', '北京'],
    '员工': ['张三', '李四', '王五']
})
right = pd.DataFrame({
    '部门': ['技术', '技术', '销售'],
    '城市': ['北京', '深圳', '北京'],
    '评分': [95, 88, 76]
})

# 单列连接
pd.merge(left, right, on='部门')  # 会产生重复

# 多列连接(精确匹配)
pd.merge(left, right, on=['部门', '城市'], how='inner')

不同列名连接

left = pd.DataFrame({
    'emp_id': [1, 2, 3],
    'name': ['张三', '李四', '王五']
})
right = pd.DataFrame({
    'employee_id': [1, 2, 4],
    'salary': [8000, 9000, 10000]
})

# 使用 left_on / right_on
result = pd.merge(left, right,
                   left_on='emp_id', right_on='employee_id')

indicator— 追踪来源

result = pd.merge(left, right, on='key', how='outer', indicator=True)
# 新增 _merge 列: 'both' / 'left_only' / 'right_only'

# 自定义指示列名
result = pd.merge(left, right, on='key', how='outer',
                  indicator='来源')

# 快速查看哪些 key 只在一侧
print(result['来源'].value_counts())

suffixes— 重名列后缀

left = pd.DataFrame({'key': [1, 2], 'value': [10, 20]})
right = pd.DataFrame({'key': [1, 2], 'value': [100, 200]})

result = pd.merge(left, right, on='key',
                  suffixes=('_左', '_右'))
# key  value_左  value_右

DataFrame.join()— 按索引合并

left = pd.DataFrame(
    {'A': [1, 2, 3]},
    index=['a', 'b', 'c']
)
right = pd.DataFrame(
    {'B': [10, 20, 30]},
    index=['a', 'b', 'd']
)

# 按索引左连接
left.join(right, how='left')

# 按索引外连接
left.join(right, how='outer')

# 左表用列,右表用索引
left_with_key = pd.DataFrame({
    'key': ['a', 'b', 'c'],
    'A': [1, 2, 3]
})
left_with_key.join(right.set_index('...'), on='key')  # 注意:left 不能有重复 key

# 一次 join 多个 DataFrame
right2 = pd.DataFrame({'C': [100, 200]}, index=['a', 'c'])
left.join([right, right2], how='inner')

pd.concat()— 轴向拼接

纵向拼接(axis=0,默认)

df1 = pd.DataFrame({'A': [1, 2], 'B': [3, 4]}, index=['a', 'b'])
df2 = pd.DataFrame({'A': [5, 6], 'B': [7, 8]}, index=['c', 'd'])

# 纵向拼接
result = pd.concat([df1, df2])
# axis=0(默认)

# 保留原索引
result = pd.concat([df1, df2], ignore_index=True)  # 重建 0..N-1 索引

# 添加分组键(生成 MultiIndex)
result = pd.concat([df1, df2], keys=['第一组', '第二组'])
# 可通过 result.loc['第一组'] 取回原数据

# 添加分组键为列
result = pd.concat([df1, df2], keys=['第一组', '第二组'],
                   names=['组别', '原索引'])

横向拼接(axis=1)

df1 = pd.DataFrame({'A': [1, 2], 'B': [3, 4]})
df2 = pd.DataFrame({'C': [5, 6], 'D': [7, 8]})

result = pd.concat([df1, df2], axis=1)

join参数控制列对齐

df1 = pd.DataFrame({'A': [1, 2]}, index=['a', 'b'])
df2 = pd.DataFrame({'B': [3, 4]}, index=['b', 'c'])

pd.concat([df1, df2], axis=1, join='outer')   # 取并集(默认)
pd.concat([df1, df2], axis=1, join='inner')   # 取交集

ignore_indexvsverify_integrity

# ignore_index: 忽略原索引,重建 0..N-1
pd.concat([df1, df2], ignore_index=True)

# verify_integrity: 检查索引是否有重复
pd.concat([df1, df1], verify_integrity=True)   # 抛出 ValueError

pd.merge_asof()— 近似匹配连接

按最近(或最近且≤ / ≥)的键匹配,常用于时间序列对齐。

trades = pd.DataFrame({
    'time': pd.to_datetime(['09:30:01', '10:15:30', '14:45:00']),
    'price': [100.5, 101.2, 99.8]
})
quotes = pd.DataFrame({
    'time': pd.to_datetime(['09:30:00', '10:00:00', '14:00:00', '15:00:00']),
    'bid': [100.0, 101.0, 99.5, 100.5],
    'ask': [101.0, 102.0, 100.5, 101.5]
})

# 匹配最近的前一个报价
result = pd.merge_asof(trades, quotes, on='time')

# direction 参数
# 'backward' (默认): 取 quotes.time <= trades.time 的最后一行
# 'forward': 取 quotes.time >= trades.time 的第一行
# 'nearest': 取时间差的绝对值最小的行

result_fwd = pd.merge_asof(trades, quotes, on='time', direction='forward')

# tolerance: 限制最大时间差
result_tol = pd.merge_asof(trades, quotes, on='time',
                            tolerance=pd.Timedelta('5min'))

pd.merge_ordered()— 有序合并

类似 merge 但会对结果排序,并支持前向填充。

a = pd.DataFrame({'k': [1, 3, 5], 'a_val': [10, 30, 50]})
b = pd.DataFrame({'k': [2, 3, 4], 'b_val': [20, 30, 40]})

result = pd.merge_ordered(a, b, on='k')
# 结果按 k 排序,缺失值 NaN

# 前向填充
result = pd.merge_ordered(a, b, on='k', fill_method='ffill')

combine/combine_first— 按元素值规则合并

df1 = pd.DataFrame({'A': [1, np.nan, 3], 'B': [4, 5, np.nan]})
df2 = pd.DataFrame({'A': [10, 20, 30], 'B': [40, np.nan, 60]})

# combine_first: 用 df2 填充 df1 的缺失值
result = df1.combine_first(df2)
# df1 有值就用 df1,NaN 就用 df2

# combine: 自定义合并规则
result = df1.combine(df2, lambda s1, s2: np.where(s1 > s2, s1, s2))
# 取每个位置较大的值

result = df1.combine(df2, np.maximum)  # 等价写法

方法对比

方法合并依据主要参数适用场景
pd.merge()列值on, how, left_on, right_on通用表关联
df.join()索引on (可选), how索引对齐
pd.concat()axis, join, keys行/列拼接
pd.merge_asof()最近匹配on, direction, tolerance时间序列对齐
df.combine_first()元素级填补缺失值
df.combine()元素级func自定义合并规则

总结

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • Python + selenium + crontab实现每日定时自动打卡功能

    Python + selenium + crontab实现每日定时自动打卡功能

    这篇文章主要介绍了Python + selenium + crontab实现每日定时自动打卡功能,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-03-03
  • python中装饰器级连的使用方法示例

    python中装饰器级连的使用方法示例

    装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,下面这篇文章主要给大家介绍了关于python中装饰器级连的使用方法,需要的朋友可以参考借鉴,下面来一起学习学习吧。
    2017-09-09
  • 彻底明白Python中Super()使用小结

    彻底明白Python中Super()使用小结

    本文主要介绍了彻底明白Python中Super()使用小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2026-02-02
  • python实现跨excel的工作表sheet之间的复制方法

    python实现跨excel的工作表sheet之间的复制方法

    今天小编就为大家分享一篇python实现跨excel的工作表sheet之间的复制方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2018-05-05
  • 最小二乘法及其python实现详解

    最小二乘法及其python实现详解

    今天小编就为大家分享一篇最小二乘法及其python实现详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-02-02
  • Python yield 小结和实例

    Python yield 小结和实例

    yield的作用就是把一个函数变成一个 generator,带有 yield 的函数不再是一个普通函数,Python 解释器会将其视为一个 generator(不知道什么是generator要先去理解一下Python的generator的了)
    2014-04-04
  • 解决Python的requests中text中文乱码的问题

    解决Python的requests中text中文乱码的问题

    学习Python爬虫时遇到中文乱码问题,发现req.text返回的是unicode,无法再次decode,通过查看网站源码,发现网站使用的是gbk编码,Requests会自动解码来自服务器的内容,但有时推测错误,通过设置r.encoding为gbk,然后对text进行编码,可以正确打印出中文
    2025-01-01
  • 基于Python编写一个串口调试工具

    基于Python编写一个串口调试工具

    这篇文章主要为大家详细介绍了如何基于 Python编写一个tkinter 和 pyserial 的串口调试工具,可以方便地进行串口通信的设置等操作,感兴趣的小伙伴可以了解下
    2025-02-02
  • Python 实现 T00ls 自动签到脚本代码(邮件+钉钉通知)

    Python 实现 T00ls 自动签到脚本代码(邮件+钉钉通知)

    这篇文章主要介绍了Python 实现 T00ls 自动签到脚本(邮件+钉钉通知),本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-07-07
  • Python文件操作及内置函数flush原理解析

    Python文件操作及内置函数flush原理解析

    这篇文章主要介绍了Python文件操作及内置函数flush原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-10-10

最新评论