说明

pd.merge() 实现数据库风格的合并(join),根据一个或多个公共键(key)将两个 DataFrame 对齐合并,支持多种连接方式。

语法

pd.merge(
    left,                  # 左侧 DataFrame
    right,                 # 右侧 DataFrame
    how='inner',           # 连接方式
    on=None,               # 公共列(键)名
    left_on=None,          # 左侧键列
    right_on=None,         # 右侧键列
    left_index=False,      # 是否使用左侧索引作为键
    right_index=False,     # 是否使用右侧索引作为键
    sort=False,            # 是否按键排序
    suffixes=('_x', '_y'), # 列名冲突时的后缀
    copy=None,             # 是否复制数据
    indicator=False,       # 是否添加 _merge 列标记来源
    validate=None,         # 关系校验:'one_to_one' 等
)

参数说明

参数说明可选值
how连接方式'left'、'right'、'outer'、'inner'、'cross'
on左右两侧同名列作为键列名或列名列表
left_on / right_on左右两侧不同列名作为键列名或列名列表
left_index / right_index使用索引用作键True / False
suffixes重叠列名的后缀默认 ('_x', '_y')
indicator添加 _merge 列标记每行来源True、False、字符串
validate验证合并关系是否符合预期见下方表格

how 连接方式

说明

how 决定结果集包含哪些行,与 SQL 的 JOIN 语义一致。

how行为类比 SQL
'inner'仅保留两表键匹配的行INNER JOIN
'left'保留左表所有行,右表无匹配时填充 NaNLEFT JOIN
'right'保留右表所有行,左表无匹配时填充 NaNRIGHT JOIN
'outer'保留两表所有行,无匹配处填充 NaNFULL OUTER JOIN
'cross'两表所有行笛卡尔积CROSS JOIN

示例

import pandas as pd
 
left = pd.DataFrame({
    'key': ['a', 'b', 'c'],
    'value_l': [1, 2, 3],
})
 
right = pd.DataFrame({
    'key': ['b', 'c', 'd'],
    'value_r': [20, 30, 40],
})
 
# inner
print(pd.merge(left, right, on='key'))
#   key  value_l  value_r
# 0   b        2       20
# 1   c        3       30
 
# left
print(pd.merge(left, right, on='key', how='left'))
#   key  value_l  value_r
# 0   a        1      NaN
# 1   b        2     20.0
# 2   c        3     30.0
 
# outer
print(pd.merge(left, right, on='key', how='outer'))
#   key  value_l  value_r
# 0   a      1.0      NaN
# 1   b      2.0     20.0
# 2   c      3.0     30.0
# 3   d      NaN     40.0
 
# cross
print(pd.merge(left, right, how='cross').head())
#   key_x  value_l key_y  value_r
# 0     a        1     b       20
# 1     a        1     c       30
# 2     a        1     d       40
# ...

多键合并

left = pd.DataFrame({
    'k1': ['a', 'a', 'b'],
    'k2': ['x', 'y', 'x'],
    'v1': [1, 2, 3],
})
right = pd.DataFrame({
    'k1': ['a', 'a', 'b'],
    'k2': ['x', 'y', 'y'],
    'v2': [10, 20, 30],
})
 
print(pd.merge(left, right, on=['k1', 'k2']))
#   k1 k2  v1    v2
# 0  a  x   1  10.0
# 1  a  y   2  20.0

left_on / right_on:不同键名

left = pd.DataFrame({'lkey': ['a', 'b'], 'v': [1, 2]})
right = pd.DataFrame({'rkey': ['a', 'b'], 'w': [10, 20]})
 
print(pd.merge(left, right, left_on='lkey', right_on='rkey'))
#   lkey  v rkey   w
# 0    a  1    a  10
# 1    b  2    b  20

索引合并

left = pd.DataFrame({'v': [1, 2]}, index=['a', 'b'])
right = pd.DataFrame({'w': [10, 20]}, index=['a', 'c'])
 
# 左索引对右列
print(pd.merge(left, right, left_index=True, right_on='w'))
 
# 双索引合并
print(pd.merge(left, right, left_index=True, right_index=True, how='outer'))

suffixes:处理重叠列

left = pd.DataFrame({'key': ['a'], 'value': [1]})
right = pd.DataFrame({'key': ['a'], 'value': [100]})
 
print(pd.merge(left, right, on='key'))
#   key  value_x  value_y
# 0   a        1      100
 
print(pd.merge(left, right, on='key', suffixes=('_L', '_R')))
#   key  value_L  value_R
# 0   a        1      100

indicator:来源标记

left = pd.DataFrame({'key': ['a', 'b'], 'v': [1, 2]})
right = pd.DataFrame({'key': ['b', 'c'], 'w': [20, 30]})
 
result = pd.merge(left, right, on='key', how='outer', indicator=True)
print(result)
#   key    v     w      _merge
# 0   a  1.0   NaN   left_only
# 1   b  2.0  20.0        both
# 2   c  NaN  30.0  right_only
 
# 自定义 indicator 列名
result2 = pd.merge(left, right, on='key', how='outer', indicator='source')

validate:关系校验

说明

检查合并是否满足指定的基数关系,不满足时抛出异常。

值含义
'one_to_one' 或 '1:1'键在两侧均唯一
'one_to_many' 或 '1:m'键在左侧唯一,右侧可重复
'many_to_one' 或 'm:1'键在右侧唯一,左侧可重复
'many_to_many' 或 'm:m'两侧均可重复(默认)
try:
    pd.merge(left, right, on='key', validate='one_to_one')
except MergeError as e:
    print(e)

与 concat 的区别

merge vs concat

  • concat():沿轴向堆叠,不关心键匹配。
  • merge():按键对齐,实现类似 SQL 的连接。

需要按行拼接同结构数据用 concat,需要按列关联数据用 merge。

🔗 相关链接