Python DataFrame:为每个ID匹配最接近HandoverDate的Sent日期
问题描述
现有如下DataFrame:
data = {'SalePrice':[10,10,10,20,20,3,3,1,4,8,8],'HandoverDateA':['2022-04-30','2022-04-30','2022-04-30','2022-04-30','2022-04-30','2022-04-30','2022-04-30','2022-04-30','2022-04-30','2022-03-30','2022-03-30'],'ID': ['Tom', 'Tom','Tom','Joseph','Joseph','Ben','Ben','Eden','Tim','Adam','Adam'], 'Tranche': ['Red', 'Red', 'Red', 'Red','Red','Blue','Blue','Red','Red','Red','Red'],'Totals':[100,100,100,50,50,90,90,70,60,70,70],'Sent':['2022-01-18','2022-02-19','2022-03-14','2022-03-14','2022-04-22','2022-03-03','2022-02-07','2022-01-04','2022-01-10','2022-01-15','2022-03-12'],'Amount':[20,10,14,34,15,60,25,10,10,40,20],'Opened':['2021-12-29','2021-12-29','2021-12-29','2022-12-29','2022-12-29','2021-12-19','2021-12-19','2021-12-29','2021-12-29','2021-12-29','2021-12-29']}
需要为每个ID找到不晚于对应HandoverDateA的Sent日期中,与HandoverDateA最接近的日期。尝试过自定义函数和循环分组的方法,但循环速度过慢,需要高效的解决方案。
高效解决方案
步骤1:转换日期列为datetime类型
首先将日期列转为pandas可计算的datetime类型:
import pandas as pd df = pd.DataFrame(data) df['HandoverDateA'] = pd.to_datetime(df['HandoverDateA']) df['Sent'] = pd.to_datetime(df['Sent'])
步骤2:分组获取目标日期
提供两种高效实现方式:
方法一:精准匹配差值逻辑
按ID分组后,筛选符合Sent <= HandoverDateA的记录,计算日期差值绝对值,取差值最小的Sent日期:
def get_nearest_sent(group): handover_date = group['HandoverDateA'].iloc[0] filtered = group[group['Sent'] <= handover_date] if filtered.empty: return pd.NaT # 无符合条件日期时返回空值 filtered['date_diff'] = abs(filtered['Sent'] - handover_date) return filtered.loc[filtered['date_diff'].idxmin(), 'Sent'] result = df.groupby('ID').apply(get_nearest_sent).reset_index(name='NearestSentDate')
方法二:取最大符合条件日期(性能更优)
在Sent <= HandoverDateA的前提下,最大的Sent日期就是最接近HandoverDateA的,直接取最大值即可:
# 先筛选符合条件的行 filtered_df = df[df['Sent'] <= df['HandoverDateA']] # 分组取最大Sent日期 result = filtered_df.groupby('ID')['Sent'].max().reset_index(name='NearestSentDate') # 若需保留所有ID(含无符合条件日期的),用merge补全空值 result = df[['ID']].drop_duplicates().merge(result, on='ID', how='left').fillna(pd.NaT)
输出结果示例
最终result的结构如下:
| ID | NearestSentDate |
|---|---|
| Adam | 2022-03-12 |
| Ben | 2022-03-03 |
| Eden | 2022-01-04 |
| Joseph | 2022-04-22 |
| Tim | 2022-01-10 |
| Tom | 2022-03-14 |
内容的提问来源于stack exchange,提问作者user13948
相关产品推荐
相关产品推荐

