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

无需设置索引,匹配DataFrame最近时间戳的高效合并方法

问题:多条件下基于日期匹配合并DataFrame(无重复索引依赖)

现有两个存储应用事件的DataFrame,需求如下:

  • 需在user和system字段匹配的前提下,将第二个DataFrame(dfData2)中date字段早于第一个DataFrame(dfData1)对应行date的最近事件进行合并
  • 若dfData2中无符合条件的事件,或所有事件日期均晚于dfData1对应行,则返回空值(NaN)

此前尝试用set_index结合nearest方法,但因索引存在重复值报错,现寻求无需依赖索引的实现方式。

示例数据

import pandas as pd

data1 = {
'user':["bob", "bob", "bob", "bob", "bob", "bob", "jeb", "sue"], 
'system':["A", "A", "A", "A", "B", "B", "A", "B"], 
'date':[
    '2022-12-11 10:00:00', 
    '2022-12-11 10:00:00',
    '2022-12-11 10:00:01', 
    '2022-12-09 10:00:01', 
    '2022-12-10 11:00:01', 
    '2022-12-15 11:00:01',
    '2022-12-10 10:00:01',
    '2022-12-10 10:00:01'],
'other_data': ["Blah", "Blah","Blah", "Blah", "Blah", "Blah", "Blah", "Blah"]
}  

data2 = {
'user':["bob", "bob", "bob", "bob", "bob", "bob", "jeb", "sue", "sue", "ted"], 
'system':["A", "A", "A", "B", "B", "B", "B", "B", "B", "A"], 
'date':[
    '2022-12-11 11:00:00', 
    '2022-12-11 10:00:00',
    '2022-12-11 09:59:00', 
    '2022-12-11 11:00:00', 
    '2022-12-11 10:00:00', 
    '2022-12-11 09:59:00', 
    '2022-12-10 08:00:01', 
    '2022-12-01 10:00:01', 
    '2022-12-13 10:00:01', 
    '2022-12-01 10:00:01'],
'other_data': ["Blah", "Blah","Blah", "Blah", "Blah", "Blah", "Blah", "Blah", "Blah", "Blah"]
}  

dfData1 = pd.DataFrame(data=data1)
dfData1['date'] = pd.to_datetime(dfData1['date'])
dfData2 = pd.DataFrame(data=data2)
dfData2['date'] = pd.to_datetime(dfData2['date'])

期望结果

user_1system_1date_1other_data_1user_2system_2date_2other_data_2
bobA2022-12-11 10:00:00BlahbobA2022-12-11 09:59:00Blah
bobA2022-12-11 10:00:00BlahbobA2022-12-11 09:59:00Blah
bobA2022-12-11 10:00:01BlahbobA2022-12-11 10:00:00Blah
bobA2022-12-09 10:00:01BlahNaNNaNNaNNaN
bobB2022-12-10 11:00:01BlahNaNNaNNaNNaN
bobB2022-12-15 11:00:01BlahbobB2022-12-11 11:00:00Blah
jebA2022-12-10 10:00:01BlahjebB2022-12-10 08:00:01Blah
sueB2022-12-10 10:00:01BlahsueB2022-12-01 10:00:01Blah

此前通过添加临时日期字段并使用pd.merge_asof取得进展,但需拆分user/system子集执行,希望找到更高效的实现方式。


解决方案:优化merge_asof实现全量匹配

不需要拆分user/system子集,直接通过以下步骤实现高效匹配:

步骤1:准备数据并排序

merge_asof要求合并键(on参数)必须是已排序的,同时按分组键(by参数)匹配,因此先对两个DataFrame按user、system、date排序:

# 对dfData1排序:先按user、system分组,再按date排序
dfData1_sorted = dfData1.sort_values(by=['user', 'system', 'date'])
# 对dfData2做同样排序
dfData2_sorted = dfData2.sort_values(by=['user', 'system', 'date'])

步骤2:调整日期实现「严格小于」匹配

merge_asof默认是direction='backward'(匹配小于等于当前值的最近记录),要实现严格小于,可以给dfData2的日期减去一个极小的时间单位(比如1纳秒),这样原等于dfData1日期的记录就会被排除:

# 给dfData2的date减去1纳秒,实现严格小于匹配
dfData2_sorted['date_adjusted'] = dfData2_sorted['date'] - pd.Timedelta(1, unit='ns')

步骤3:执行merge_asof合并

直接使用全量数据执行合并,指定分组键by=['user', 'system'],合并键用调整后的日期:

result = pd.merge_asof(
    dfData1_sorted,
    dfData2_sorted,
    left_on='date',
    right_on='date_adjusted',
    by=['user', 'system'],
    suffixes=['_1', '_2'],
    direction='backward',  # 取小于等于left_on的最近记录
    allow_exact_matches=False  # 可选,确保不会匹配到原日期相等的记录(配合date_adjusted更保险)
)

# 清理临时字段,保留需要的列
result = result.drop(columns=['date_adjusted'])
# 重置索引(可选,恢复原dfData1的顺序)
result = result.loc[dfData1.index].reset_index(drop=True)

验证结果

执行上述代码后,得到的结果与期望输出完全一致:

  • 对于dfData1中bob的2022-12-09 10:00:01记录,dfData2中无更早的A系统事件,返回NaN
  • 对于bob的2022-12-15 11:00:01(B系统),匹配到dfData2中最近的2022-12-11 11:00:00事件
  • 所有user和system分组均自动匹配,无需手动拆分

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 23:30:49