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

Pandas:带时间差的DataFrame合并及merge_asof函数解析

问题描述

我需要对两个包含ID和Date列的大型DataFrame做匹配,但不是完全匹配日期,而是要包含匹配日期前后4天的数据。

示例数据

df1

ID      Date
0   RHD78   2022-08-05
1   RHD78   2022-08-06
2   RHD78   2022-08-09
3   RHD78   2022-08-11
4   RHD78   2022-08-12
5   RHD78   2022-08-14
6   RHD78   2022-08-15
7   RHD78   2022-08-19
8   BDW56   2022-03-15
9   BDW56   2022-03-16
10  BDW56   2022-03-17
11  BDW56   2022-03-22
12  BDW56   2022-03-23
13  BDW56   2022-03-27
14  BDW56   2022-03-29
15  BDW56   2022-03-30

df2

ID      Date
0   RHD78   2022-08-12
1   BDW56   2022-03-23

当前尝试的问题

用df_result = pd.merge(df1, df2, how = 'inner', on='Date')只能得到日期完全匹配的2条记录,但我想要的是每个ID对应的匹配日期前后4天内的所有记录,期望结果如下:

df_desired

ID      Date
0   RHD78   8/9/2022
1   RHD78   8/11/2022
2   RHD78   8/12/2022
3   RHD78   8/14/2022
4   RHD78   8/15/2022
5   BDW56   3/22/2022
6   BDW56   3/23/2022
7   BDW56   3/27/2022

我试过merge_asof(),但感觉它只能取最接近的日期,不是指定范围。作为Python和Pandas新手,希望得到可行的解决方案,以及对merge_asof()的简单解释。


解决方案

步骤1:统一日期格式

首先必须把两个DataFrame的Date列转换成datetime类型,才能进行时间差计算:

import pandas as pd

df1['Date'] = pd.to_datetime(df1['Date'])
df2['Date'] = pd.to_datetime(df2['Date'])

步骤2:匹配ID+日期范围

以下两种方法都适合处理大型DataFrame:

方法1:合并后过滤(高效通用)

先按ID做内连接,再筛选出日期差在±4天内的记录:

# 按ID合并两个DataFrame,给日期列加后缀区分
merged = pd.merge(df1, df2, on='ID', suffixes=('_df1', '_df2'))

# 筛选日期差绝对值≤4天的记录
mask = abs(merged['Date_df1'] - merged['Date_df2']) <= pd.Timedelta(days=4)
df_result = merged.loc[mask, ['ID', 'Date_df1']].rename(columns={'Date_df1': 'Date'}).drop_duplicates()

# 可选:转成期望的月/日/年格式
df_result['Date'] = df_result['Date'].dt.strftime('%m/%d/%Y')

方法2:分组筛选(适合ID分组清晰的场景)

先把df2的目标日期按ID存为字典,再对df1按ID分组筛选:

# 构建ID到目标日期的映射表
target_dates = df2.set_index('ID')['Date'].to_dict()

# 定义分组筛选函数
def filter_date_range(group):
    target_date = target_dates[group.name]
    return group[(group['Date'] >= target_date - pd.Timedelta(days=4)) & 
                 (group['Date'] <= target_date + pd.Timedelta(days=4))]

# 应用分组筛选
df_result = df1.groupby('ID').apply(filter_date_range).reset_index(drop=True)
df_result['Date'] = df_result['Date'].dt.strftime('%m/%d/%Y')

merge_asof() 简化解释

merge_asof()是Pandas的时间近似匹配工具,核心逻辑:

  • 要求左右表都按匹配的时间列排序
  • 默认给左表每条记录,在右表找时间≤左表时间且最接近的单条记录
  • 可通过direction参数调整匹配方向(比如'forward'找≥左表时间的最接近值)
  • 虽然能用tolerance设置时间差上限,但它依然只返回单个近似匹配,而非范围内的所有记录——这就是它不适合你本次需求的原因,你需要的是范围内的全部符合记录,而非单个最接近的匹配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 18:45:38