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

基于日期比对从另一DataFrame填充df1的NextEntry_Date字段

解决DataFrame填充下一个更大日期的问题

嘿,这个需求我之前做时间序列处理时经常碰到,用Pandas可以很优雅地解决,给你两种实用的方案:

思路说明

我们的核心需求是:对df1中的每一行日期,在df2的日期列里找到第一个比它大的最小日期,本质是时间序列的「向上最近邻查找」。


方案一:用searchsorted实现高效查找(适合大数据量)

这个方法利用NumPy的searchsorted函数,效率极高,处理十万级以上数据也毫无压力:

首先构造示例数据(和你给出的结构一致):

import pandas as pd

df1 = pd.DataFrame({
    'Date': [
        '2018-01-25', '2018-02-25', '2018-03-25',
        '2018-04-25', '2018-05-25', '2018-06-25',
        '2018-07-25', '2018-08-25', '2018-09-25',
        '2018-10-25'
    ]
}).astype({'Date': 'datetime64[ns]'})

df2 = pd.DataFrame({
    'Date': ['2018-07-20', '2019-07-20', '2020-07-20']
}).astype({'Date': 'datetime64[ns]'})

然后执行关键步骤:

  • 确保df2的日期是有序的(searchsorted要求输入序列有序)
    df2_sorted = df2.sort_values('Date').reset_index(drop=True)
    df2_dates = df2_sorted['Date'].values
    
  • 用searchsorted找到每个df1日期对应的插入位置(side='right'表示找第一个大于当前值的位置)
    indices = df2_dates.searchsorted(df1['Date'], side='right')
    
  • 根据索引匹配对应的日期,超出范围的会自动设为NaN(示例中没有这种情况)
    df1['NextEntry_Date'] = df2_sorted.loc[indices, 'Date'].values
    

执行后df1的结果完全符合你的要求:

  • 2018-01-25至2018-06-25对应的NextEntry_Date都是2018-07-20
  • 2018-07-25至2018-10-25对应的都是2019-07-20

方案二:用merge_asof实现直观匹配(适合小数据量/易读性优先)

如果你更习惯Pandas的merge操作,merge_asof的direction='forward'参数专门为这个场景设计,代码更直观:

同样先构造示例数据(和上面一致),然后执行以下步骤:

  • 对两个DataFrame按日期排序
    df1_sorted = df1.sort_values('Date').reset_index(drop=True)
    df2_sorted = df2.sort_values('Date').reset_index(drop=True)
    
  • 使用merge_asof进行向前匹配
    result = pd.merge_asof(
        df1_sorted,
        df2_sorted,
        on='Date',
        direction='forward',  # 指定找下一个更大的日期
        suffixes=('', '_next')
    )
    
  • 将匹配结果回填到原df1
    df1['NextEntry_Date'] = result['Date_next'].values
    

这个方法的逻辑更直白,不需要理解索引计算,适合快速实现需求。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 03:54:18