说明
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' | 保留左表所有行,右表无匹配时填充 NaN | LEFT JOIN |
'right' | 保留右表所有行,左表无匹配时填充 NaN | RIGHT JOIN |
'outer' | 保留两表所有行,无匹配处填充 NaN | FULL 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.0left_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 100indicator:来源标记
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。
🔗 相关链接
- 14.1 concat() - 轴向拼接
- 14.3 join() - 基于索引的便捷合并
- 14.5 merge_ordered() - 有序数据的合并变体
- 14.4 merge_asof() - 时间序列近似匹配