如何用Python获取用户停止日期前的最后交易日期?
解决方法:匹配每个用户停止日期前的最后一笔交易日期
示例数据模拟
先按照示例格式,模拟两个输入DataFrame:
import pandas as pd # DataFrame1:用户列表及停止日期(含多停止日期的用户) df1 = pd.DataFrame({ 'user_id': ['A', 'A', 'B', 'C'], 'stop_date': pd.to_datetime(['2023-01-15', '2023-03-20', '2023-02-10', '2023-04-05']) }) # DataFrame2:用户交易历史及交易日期 df2 = pd.DataFrame({ 'user_id': ['A', 'A', 'A', 'B', 'B', 'C'], 'transaction_date': pd.to_datetime(['2023-01-10', '2023-01-20', '2023-03-18', '2023-02-05', '2023-02-12', '2023-04-01']), 'amount': [100, 200, 150, 50, 75, 300] })
方案一:用merge_asof高效匹配(推荐)
pd.merge_asof专门用于按时间序列匹配最近的前置/后置记录,适合这类按用户+时间找最近交易的场景:
- 先对两个DataFrame按
user_id和日期字段排序(merge_asof要求右表必须排序,左表排序可提升匹配效率) - 通过
direction='backward'指定匹配小于等于停止日期的最近交易日期
# 排序处理 df1_sorted = df1.sort_values(by=['user_id', 'stop_date']) df2_sorted = df2.sort_values(by=['user_id', 'transaction_date']) # 执行匹配 result = pd.merge_asof( df1_sorted, df2_sorted, by='user_id', # 按用户分组匹配 left_on='stop_date', right_on='transaction_date', direction='backward' # 取stop_date之前的最近交易 ) # 整理输出格式 result = result[['user_id', 'stop_date', 'transaction_date']].rename( columns={'transaction_date': 'last_transaction_before_stop'} ) print(result)
输出结果:
user_id stop_date last_transaction_before_stop 0 A 2023-01-15 2023-01-10 1 A 2023-03-20 2023-03-18 2 B 2023-02-10 2023-02-05 3 C 2023-04-05 2023-04-01
方案二:分组筛选法(灵活适配复杂场景)
如果需要保留交易的其他字段,或者有额外筛选逻辑,可采用交叉合并+分组取最大值的方式:
# 交叉合并同一用户的停止日期与交易记录 cross_merge = pd.merge(df1, df2, on='user_id', how='left') # 筛选交易日期早于等于停止日期的记录 filtered = cross_merge[cross_merge['transaction_date'] <= cross_merge['stop_date']] # 按用户+停止日期分组,取最晚的交易日期 grouped_result = filtered.groupby(['user_id', 'stop_date'])['transaction_date'].max().reset_index() grouped_result = grouped_result.rename(columns={'transaction_date': 'last_transaction_before_stop'}) # 补全无前置交易的停止日期记录(对应字段为NaN) final_result = df1.merge(grouped_result, on=['user_id', 'stop_date'], how='left') print(final_result)
这个方法的优势是可以灵活扩展,比如同时保留交易金额等字段,只需调整分组时的字段即可。
内容的提问来源于stack exchange,提问作者Nicole Ardizzi
相关产品推荐
相关产品推荐

