说明

pd.merge_asof() 用于执行基于有序键(通常是时间)的近似匹配合并,类似 merge_ordered(),但不会匹配完全相等的键,而是匹配最近的键。常用于事件对齐、信号配对等场景。

语法

pd.merge_asof(
    left,                     # 左侧 DataFrame
    right,                    # 右侧 DataFrame
    on=None,                  # 公共有序键(通常为时间列)
    left_on=None,             # 左侧键列
    right_on=None,            # 右侧键列
    left_index=False,         # 使用左侧索引作为键
    right_index=False,        # 使用右侧索引作为键
    by=None,                  # 分组列(匹配前先按此列分组)
    left_by=None,             # 左侧分组列
    right_by=None,            # 右侧分组列
    suffixes=('_x', '_y'),    # 重叠列后缀
    tolerance=None,           # 最大匹配距离
    allow_exact_matches=True, # 是否允许精确匹配
    direction='backward',     # 匹配方向
)

参数说明

参数说明默认
on两侧共有的有序键(通常是时间)None
tolerance匹配的最大时间差,超过则不匹配None(无限)
allow_exact_matches是否返回完全相等的匹配True
direction匹配方向:'backward'、'forward'、'nearest''backward'
by在合并前先按此列分组,组内分别匹配None

direction 匹配方向

说明

控制左侧键与右侧键的匹配方向:

方向含义示例
'backward'匹配右侧小于等于左侧键的最近行查询某一时刻之前的最近状态
'forward'匹配右侧大于等于左侧键的最近行查询某一时刻之后的最近事件
'nearest'匹配距离最近的行(绝对距离最小)通用最近邻匹配

基础示例

import pandas as pd
 
left = pd.DataFrame({
    'time': pd.to_datetime(['2026-08-19 10:00', '2026-08-19 10:10', '2026-08-19 10:20']),
    'value_l': [1, 2, 3],
})
 
right = pd.DataFrame({
    'time': pd.to_datetime(['2026-08-19 10:05', '2026-08-19 10:15']),
    'value_r': [100, 200],
})
 
# 默认 backward:取右侧 ≤ 左侧键的最近一行
print(pd.merge_asof(left, right, on='time'))
#                 time  value_l  value_r
# 0 2026-08-19 10:00:00        1      NaN
# 1 2026-08-19 10:10:00        2    100.0
# 2 2026-08-19 10:20:00        3    200.0

direction=‘forward’

print(pd.merge_asof(left, right, on='time', direction='forward'))
#                 time  value_l  value_r
# 0 2026-08-19 10:00:00        1    100.0
# 1 2026-08-19 10:10:00        2    200.0
# 2 2026-08-19 10:20:00        3      NaN

direction=‘nearest’

print(pd.merge_asof(left, right, on='time', direction='nearest'))
#                 time  value_l  value_r
# 0 2026-08-19 10:00:00        1    100.0
# 1 2026-08-19 10:10:00        2    100.0
# 2 2026-08-19 10:20:00        3    200.0

tolerance:限制匹配距离

说明

以 on 列的单位为准,限制左右键的最大差值。超过 tolerance 则不匹配(结果中为 NaN)。

print(pd.merge_asof(left, right, on='time', tolerance=pd.Timedelta('5min')))
#                 time  value_l  value_r
# 0 2026-08-19 10:00:00        1      NaN   # 10:00 与 10:05 差 5 分钟,tolerance 包含边界 → 应匹配?实际边界行为需测试
# 1 2026-08-19 10:10:00        2    100.0
# 2 2026-08-19 10:20:00        3    200.0
 
# tolerance 使用数值(如 on 列为整数秒)
l2 = pd.DataFrame({'t': [1, 5], 'v': [10, 20]})
r2 = pd.DataFrame({'t': [3, 7], 'w': [100, 200]})
print(pd.merge_asof(l2, r2, on='t', tolerance=2))
#    t   v      w
# 0  1  10  100.0   # |1-3|=2 ≤ 2
# 1  5  20  200.0   # |5-7|=2 ≤ 2

allow_exact_matches

说明

当为 False 时,精确相等的键不匹配,只匹配严格大于/小于的最近值。

print(pd.merge_asof(left, right, on='time', allow_exact_matches=False))
#                 time  value_l  value_r
# 0 2026-08-19 10:00:00        1      NaN
# 1 2026-08-19 10:10:00        2      NaN   # 10:10 与 right 10:15 不够近?需看数据
# 2 2026-08-19 10:20:00        3    200.0

by:分组匹配

说明

先按 by 列分组,再在组内进行近似匹配,常用于“按标的物 + 按时间”的配对场景。

left = pd.DataFrame({
    'symbol': ['A', 'A', 'B', 'B'],
    'time': pd.to_datetime(['2026-08-19 10:00', '2026-08-19 10:10',
                            '2026-08-19 10:00', '2026-08-19 10:10']),
    'bid': [1, 2, 3, 4],
})
 
right = pd.DataFrame({
    'symbol': ['A', 'A', 'B', 'B'],
    'time': pd.to_datetime(['2026-08-19 10:05', '2026-08-19 10:15',
                            '2026-08-19 10:05', '2026-08-19 10:15']),
    'ask': [100, 200, 300, 400],
})
 
print(pd.merge_asof(left, right, on='time', by='symbol'))
#   symbol                time  bid    ask
# 0      A 2026-08-19 10:00:00    1    NaN
# 1      A 2026-08-19 10:10:00    2  100.0
# 2      B 2026-08-19 10:00:00    3    NaN
# 3      B 2026-08-19 10:10:00    4  300.0

🔗 相关链接