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

如何在Pandas中合并数据表,仅匹配最接近的计划与实际日期?

Pandas匹配每个计划日期到最近实际日期的正确实现

问题分析

你需要将df1的每个pld_date(计划日期)匹配到同ID下最近的act_date(实际日期),之前用merge_asof或merge全量填充了唯一的有效实际日期,问题出在没有按ID分组匹配,或者未正确配置merge_asof的参数。

解决方案

准备示例数据

先模拟你的数据场景:

import pandas as pd
import numpy as np

# df1:含ID、计划日期,实际日期全为NaT
df1 = pd.DataFrame({
    'ID': ['A', 'A', 'B', 'B'],
    'pld_date': pd.to_datetime(['2023-09-01', '2023-09-10', '2023-08-30', '2023-09-15']),
    'act_date': pd.NaT
})

# df2:含ID、实际日期(仅ID=A有有效日期2023-09-07),计划日期全为NaT
df2 = pd.DataFrame({
    'ID': ['A', 'B'],
    'act_date': pd.to_datetime(['2023-09-07', pd.NaT]),
    'pld_date': pd.NaT
})

方法1:使用merge_asof(推荐,性能更优)

merge_asof支持按分组(ID)匹配最近日期,但必须满足两个前提:

  1. 左右表都要按分组键+日期键排序
  2. 指定by参数为分组列(ID),并设置direction='nearest'

代码实现:

# 提取df2中有效的实际日期记录(过滤NaT)
valid_act_dates = df2.dropna(subset=['act_date'])[['ID', 'act_date']]

# 对df1和有效实际日期表按ID+日期排序
df1_sorted = df1.sort_values(['ID', 'pld_date'])
act_dates_sorted = valid_act_dates.sort_values(['ID', 'act_date'])

# 按ID分组,匹配最近的实际日期
df3 = pd.merge_asof(
    df1_sorted,
    act_dates_sorted,
    by='ID',  # 按ID分组匹配
    left_on='pld_date',
    right_on='act_date',
    direction='nearest'  # 找最近的日期,无论前后
)

# 整理目标列
df3 = df3[['ID', 'pld_date', 'act_date_y']].rename(columns={'act_date_y': 'act_date'})

运行后df3的结果:

IDpld_dateact_date
A2023-09-012023-09-07
A2023-09-102023-09-07
B2023-08-30NaT
B2023-09-15NaT

方法2:分组+自定义函数(灵活适配复杂场景)

如果需要更复杂的匹配逻辑,可通过分组后自定义函数计算最近日期:

# 提取有效实际日期并按ID分组
act_dict = valid_act_dates.groupby('ID')['act_date'].apply(list).to_dict()

def get_nearest_act(row):
    # 获取当前ID对应的所有有效实际日期
    act_list = act_dict.get(row['ID'], [])
    if not act_list:
        return pd.NaT
    # 计算每个实际日期与计划日期的时间差绝对值,取最小的那个
    diffs = [abs(row['pld_date'] - dt) for dt in act_list]
    return act_list[diffs.index(min(diffs))]

# 为df1的每一行匹配最近实际日期
df1['act_date'] = df1.apply(get_nearest_act, axis=1)
df3 = df1.copy()

错误原因解释

你之前的merge_asof或merge全量填充日期,大概率是因为:

  • 使用merge_asof时未指定by='ID',导致所有行不区分ID,直接匹配到唯一的有效实际日期
  • 使用普通merge时未做分组筛选,直接按ID全量合并后未过滤最小时间差的记录

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 13:32:37