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

如何为DataFrame按ID匹配最近上下日期并添加列?

解决方案

要高效实现需求,我们可以利用pandas.merge_asof()的direction参数分别处理「最近更小日期」和「最近更大日期」,无需手动循环或复杂操作。具体步骤如下:

步骤1:转换日期格式

首先将字符串类型的日期转为datetime类型,确保能正确比较大小:

import pandas as pd

df1 = pd.DataFrame({'ID':['A', 'A', 'B', 'B'], 
    'Date':['31.08.2023', '12.09.2023', '13.09.2023', '20.08.2023']})

df2 = pd.DataFrame({'ID':['A', 'A', 'A', 'B', 'B'], 
        'Date':['30.08.2023', '14.09.2023', '10.09.2023', '28.09.2023', '19.08.2023']})

# 转换为datetime(注意dayfirst=True适配DD.MM.YYYY格式)
df1['Date'] = pd.to_datetime(df1['Date'], dayfirst=True)
df2['Date'] = pd.to_datetime(df2['Date'], dayfirst=True)

步骤2:用merge_asof分别匹配上下日期

merge_asof()要求左右表按匹配键排序,我们先对两个表按ID和Date排序,再通过direction参数区分匹配规则:

  • direction='backward':匹配同ID下小于等于当前日期的最近日期(对应DATE_DOWN)
  • direction='forward':匹配同ID下大于等于当前日期的最近日期(对应DATE_UP)
# 对两个表按ID和Date排序,满足merge_asof的要求
df1_sorted = df1.sort_values(['ID', 'Date'])
df2_sorted = df2.sort_values(['ID', 'Date'])

# 匹配DATE_DOWN:最近的更小/相等日期
df_down = pd.merge_asof(df1_sorted, df2_sorted, on='Date', by='ID', direction='backward')
df_down = df_down.rename(columns={'Date_y': 'DATE_DOWN'})

# 匹配DATE_UP:最近的更大/相等日期
df_up = pd.merge_asof(df1_sorted, df2_sorted, on='Date', by='ID', direction='forward')
df_up = df_up.rename(columns={'Date_y': 'DATE_UP'})

步骤3:合并结果并恢复原格式

将两个匹配结果合并,恢复原数据的索引顺序,并把日期转回原字符串格式:

# 合并结果,保留原df1的索引顺序
final_df = pd.merge(df_down[['ID', 'Date_x', 'DATE_DOWN']], 
                    df_up[['ID', 'Date_x', 'DATE_UP']],
                    on=['ID', 'Date_x'])
final_df = final_df.set_index(df1.index).sort_index()

# 转回DD.MM.YYYY格式的字符串
final_df = final_df.rename(columns={'Date_x': 'DATE'})
final_df['DATE'] = final_df['DATE'].dt.strftime('%d.%m.%Y')
final_df['DATE_UP'] = final_df['DATE_UP'].dt.strftime('%d.%m.%Y')
final_df['DATE_DOWN'] = final_df['DATE_DOWN'].dt.strftime('%d.%m.%Y')

print(final_df)

执行后输出结果与需求完全一致:

ID        DATE     DATE_UP   DATE_DOWN
0  A  31.08.2023  10.09.2023  30.08.2023
1  A  12.09.2023  14.09.2023  10.09.2023
2  B  13.09.2023  28.09.2023  19.08.2023
3  B  20.08.2023  28.09.2023  19.08.2023

为什么这个方法高效?

merge_asof()底层基于排序后的二分查找实现,时间复杂度为O(n log n),属于向量化操作,远快于逐行循环或apply的方式,适合处理大规模数据。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 03:12:07