You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无法使用pandas.merge_asof实现多列匹配?前向最近日期合并需求

多列分组后按前向最近日期合并Pandas DataFrame

需要合并两个包含a、b列和date日期列的DataFrame,要求先按a、b列匹配分组,再为df1的每条记录找到df2中不早于当前日期的最近日期(前向匹配)。

原始数据

df1

a    b      date
100  200    2022-01-03
100  200    2022-01-04
101  200    2022-01-05
101  200    2022-01-06
101  200    2022-01-07

df2

a    b      date
100  200    2022-01-04
100  200    2022-01-06
101  200    2022-01-03
101  200    2022-01-06
101  200    2022-01-09

预期输出

a    b      date_x      date_y
100  200    2022-01-03  2022-01-04
100  200    2022-01-04  2022-01-04
101  200    2022-01-05  2022-01-06  # 不选2022-01-03,因为早于当前日期
101  200    2022-01-06  2022-01-06
101  200    2022-01-07  2022-01-09

解决方案

方法1:使用merge_asof(推荐,效率更高)

pandas.merge_asof支持通过by参数指定多列分组匹配,结合direction='forward'实现前向最近日期匹配。注意必须先对两个DataFrame按分组列和日期列排序。

完整代码:

import pandas as pd

# 构造原始数据
df1 = pd.DataFrame({
    'a': [100, 100, 101, 101, 101],
    'b': [200, 200, 200, 200, 200],
    'date': ['2022-01-03', '2022-01-04', '2022-01-05', '2022-01-06', '2022-01-07']
})
df2 = pd.DataFrame({
    'a': [100, 100, 101, 101, 101],
    'b': [200, 200, 200, 200, 200],
    'date': ['2022-01-04', '2022-01-06', '2022-01-03', '2022-01-06', '2022-01-09']
})

# 转换日期格式为datetime
df1['date'] = pd.to_datetime(df1['date'])
df2['date'] = pd.to_datetime(df2['date'])

# 按分组列(a、b)和日期列排序,merge_asof要求输入必须有序
df1_sorted = df1.sort_values(by=['a', 'b', 'date'])
df2_sorted = df2.sort_values(by=['a', 'b', 'date'])

# 执行前向合并
result = pd.merge_asof(
    df1_sorted,
    df2_sorted,
    by=['a', 'b'],  # 按a、b分组匹配
    on='date',      # 按date列执行前向匹配
    direction='forward',  # 找第一个>=当前日期的记录
    suffixes=('_x', '_y') # 区分两个df的日期列
)

# 重置索引(可选,恢复原始顺序)
result = result.sort_index()
print(result)

输出结果与预期完全一致。

方法2:分组后使用searchsorted(兼容旧版本Pandas)

如果你的Pandas版本不支持多列by参数(较旧版本),可以通过分组+searchsorted实现:

import pandas as pd

# 构造并转换数据(同方法1)
df1['date'] = pd.to_datetime(df1['date'])
df2['date'] = pd.to_datetime(df2['date'])

# 对df2按a、b分组,预存每个分组的排序后日期列表
df2_grouped = df2.groupby(['a', 'b'])['date'].apply(sorted).to_dict()

# 定义函数:为每条df1记录找到对应分组的前向最近日期
def get_closest_forward_date(row):
    date_list = df2_grouped.get((row['a'], row['b']), [])
    if not date_list:
        return pd.NaT
    # 找到第一个>=当前日期的索引位置
    idx = pd.Series(date_list).searchsorted(row['date'], side='left')
    return date_list[idx] if idx < len(date_list) else pd.NaT

# 应用函数生成date_y列
df1['date_y'] = df1.apply(get_closest_forward_date, axis=1)
df1.rename(columns={'date': 'date_x'}, inplace=True)

print(df1)

内容的提问来源于stack exchange,提问作者sakalansaka

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 13:35:20