如何简化基于merge_asof的DataFrame时间向前匹配合并操作?
问题描述
我有两个DataFrame,定义如下:
import datetime import pandas as pd time_start = datetime.datetime.strptime('2024-02-01 10:00:00', "%Y-%m-%d %H:%M:%S") interval_l = [1, 7, 14, 17, 21, 22, 31] df_l = pd.DataFrame(index = [time_start + datetime.timedelta(seconds=i) for i in interval_l]) df_r = pd.DataFrame(range(4), index = [time_start + datetime.timedelta(seconds=10*i) for i in range(4)], columns=['val']) df_l.index.name = 'datetime' df_r.index.name = 'datetime'
其中df_r是每10秒一条数据,包含val列。我需要将df_r按最近的向前时间合并到df_l中,未匹配到的时间对应值保留NaN。
目前我通过两次调用merge_asof实现了需求,代码如下:
df_l['time'] = df_l.index df_r = pd.merge_asof( df_r, df_l[['time']], left_index=True, right_index=True, direction='forward', ) df_l = pd.merge_asof( df_l, df_r[['time', 'val']], left_index=True, right_index=True, direction='backward', by='time' ) df_l.drop(columns=['time'], inplace=True)
请问是否有更简洁的实现方式?比如直接用一次merge_asof完成?
简洁实现方案
完全可以通过单次merge_asof调用实现需求,核心是利用direction='forward'的特性,无需构造中间列:
df_l = (df_l.reset_index() .merge_asof(df_r.reset_index(), on='datetime', direction='forward') .set_index('datetime'))
原理说明
merge_asof的direction='forward'会为左表(df_l)的每一行,找到右表(df_r)中大于等于当前行时间的最早匹配项,正好符合“最近的向前时间”的需求;- 先通过
reset_index()将索引转为列,方便指定on='datetime'进行时间匹配; - 最后用
set_index恢复原索引,直接得到目标结果。
验证结果和原有代码输出完全一致:
| datetime | val |
|---|---|
| 2024-02-01 10:00:01 | 0.0 |
| 2024-02-01 10:00:07 | 0.0 |
| 2024-02-01 10:00:14 | 1.0 |
| 2024-02-01 10:00:17 | 1.0 |
| 2024-02-01 10:00:21 | 2.0 |
| 2024-02-01 10:00:22 | 2.0 |
| 2024-02-01 10:00:31 | 3.0 |
内容的提问来源于stack exchange,提问作者user6703592
相关产品推荐
相关产品推荐

