如何在pandas中高效查找用户参考日期前后最近的事件及对应数值
解决方案
实现思路
- 先将
reference_date、event_date两个字段转换为pandas datetime类型,确保日期比较、排序逻辑正常 - 按
user_id对数据分组,每个分组内拆分出早于参考日期和晚于参考日期的两部分数据 - 早于参考日期的数据按
event_date降序排序,取第一条即为参考日期前最近的事件 - 晚于参考日期的数据按
event_date升序排序,取第一条即为参考日期后最近的事件 - 最后将两部分结果和用户ID、参考日期字段拼接,得到目标格式
如果需要保留原数据中对应事件的索引,可在结果中额外拼接两条事件的原始索引字段。
代码示例
import pandas as pd # 1. 预处理:转换日期列格式 df['reference_date'] = pd.to_datetime(df['reference_date']) df['event_date'] = pd.to_datetime(df['event_date']) # 2. 定义分组处理函数 def get_nearest_events(group): # 取当前用户唯一参考日期 ref_date = group['reference_date'].iloc[0] # 筛选参考日期之前的事件,降序取第一条 before_events = group[group['event_date'] < ref_date].sort_values('event_date', ascending=False).head(1) # 筛选参考日期之后的事件,升序取第一条 after_events = group[group['event_date'] > ref_date].sort_values('event_date', ascending=True).head(1) # 拼接返回结果 return pd.Series({ 'reference_date': ref_date, 'event_1': before_events['event_date'].iloc[0] if not before_events.empty else pd.NaT, 'value_1': before_events['event_value'].iloc[0] if not before_events.empty else None, # 如需保留前事件的原始索引,可取消下行注释 # 'event_1_index': before_events.index[0] if not before_events.empty else None, 'event_2': after_events['event_date'].iloc[0] if not after_events.empty else pd.NaT, 'value_2': after_events['event_value'].iloc[0] if not after_events.empty else None # 如需保留后事件的原始索引,可取消下行注释 # 'event_2_index': after_events.index[0] if not after_events.empty else None, }) # 3. 分组执行逻辑得到结果 result = df.groupby('user_id', group_keys=False).apply(get_nearest_events).reset_index()
补充说明
如果某个用户不存在参考日期前/后的事件,对应字段会返回NaT/空值,可根据业务需求自行调整空值的默认填充规则。
内容的提问来源于stack exchange,提问作者davtot12
相关产品推荐
相关产品推荐

