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

如何匹配ID并筛选两DataFrame中180天内的日期,生成最接近组合

解决方法:匹配同ID且日期差180天内的最接近日期组合

我来帮你搞定这个需求,用Pandas的核心操作就能轻松实现,步骤清晰还容易复用,下面是完整的实现流程和代码:

步骤1:准备示例数据并转换日期类型

首先我们先把示例里的两个DataFrame定义出来,并且一定要把日期列转换成datetime类型——这是计算日期差的基础:

import pandas as pd

# 示例DataFrame A
df_a = pd.DataFrame({
    'ID': [42, 42, 167, 167, 105, 105],
    'Date_A': ['2012-07-21', '2013-04-12', '2009-04-27', '2010-04-19', '2010-12-16', '2012-01-05']
})

# 示例DataFrame B
df_b = pd.DataFrame({
    'ID': [12, 35, 42, 42, 167, 105, 105, 105, 105, 105],
    'Date_B': ['2016-09-08', '2008-02-02', '2012-01-09', '2013-03-13', '2010-08-02', '2010-11-26', '2011-08-12', '2011-11-11', '2013-03-15', '2013-09-13']
})

# 将日期列转换为datetime类型,否则无法计算日期差
df_a['Date_A'] = pd.to_datetime(df_a['Date_A'])
df_b['Date_B'] = pd.to_datetime(df_b['Date_B'])

步骤2:合并DataFrame并计算日期差

我们按ID把两个DataFrame合并,这样所有同ID的日期组合都会被配对,然后计算每对日期的差值绝对值:

# 按ID合并,得到同ID的所有日期组合
merged = pd.merge(df_a, df_b, on='ID', how='left')

# 计算日期差的绝对值(单位:天)
merged['date_diff'] = abs(merged['Date_A'] - merged['Date_B']).dt.days

步骤3:筛选符合条件的行并选取最接近的日期

先筛选出日期差≤180天的行,然后对每个ID+Date_A组合,挑出日期差最小的那一行(也就是最接近的日期):

# 筛选日期差在180天以内的行
filtered = merged[merged['date_diff'] <= 180]

# 按ID和Date_A分组,找到每组中日期差最小的行
result = filtered.loc[filtered.groupby(['ID', 'Date_A'])['date_diff'].idxmin()]

# 整理结果,保留需要的列并重置索引
result = result[['ID', 'Date_A', 'Date_B']].reset_index(drop=True)

最终结果

运行完上面的代码,你会得到这样的结果:

ID    Date_A    Date_B
0   42 2013-04-12 2013-03-13
1  167 2010-04-19 2010-08-02
2  105 2010-12-16 2010-11-26
3  105 2012-01-05 2011-11-11

额外优化:保留所有A的行(无匹配时标记为NaN)

如果想保留DataFrame A里的所有行,哪怕没有符合条件的B行,可以调整代码,把无匹配的Date_B标记为NaT(时间类型的空值):

# 计算所有组合的日期差,不符合条件的设为无穷大
merged['date_diff'] = abs(merged['Date_A'] - merged['Date_B']).dt.days
merged['date_diff'] = merged['date_diff'].where(merged['date_diff'] <= 180, float('inf'))

# 找到每个A行的最小日期差对应的B行
result_with_all_a = merged.loc[merged.groupby(['ID', 'Date_A'])['date_diff'].idxmin()]

# 把无匹配的Date_B设为NaN
result_with_all_a['Date_B'] = result_with_all_a['Date_B'].where(result_with_all_a['date_diff'] != float('inf'), pd.NaT)

# 整理结果
result_with_all_a = result_with_all_a[['ID', 'Date_A', 'Date_B']].reset_index(drop=True)

这时候结果会包含A中所有行,比如ID=42的2012-07-21对应的Date_B就会显示为NaT,代表没有符合条件的匹配项。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 09:54:31