如何按用户分组实现5/10/30天周期的交易滚动计数?
按用户分组的时间窗口滚动交易计数实现方案
原代码的核心问题
- 滚动窗口类型错误:
rolling(5)是按行数取最近5条记录,不是按5天时间范围统计,完全不符合需求。 - 合并方式错误:
concat([df1, transaction_counts], axis=0)是行方向拼接数据,会导致数据重复堆叠,应该用列方向拼接(axis=1),但更高效的方式是直接将计算结果作为新列赋值。 - 缺少时间排序:滚动窗口统计依赖数据按时间顺序排列,原代码未确保每个用户的交易按时间排序,会导致计算结果混乱。
正确实现步骤
1. 预处理:确保时间列类型正确并排序
首先将时间列转换为datetime类型,同时按用户ID和时间排序,保证每个用户的交易记录按时间先后排列:
import pandas as pd # 转换时间列类型 df1['authorizationProcessedAt'] = pd.to_datetime(df1['authorizationProcessedAt']) # 按用户ID和时间排序 df1 = df1.sort_values(by=['userId', 'authorizationProcessedAt'])
2. 计算多时间窗口的滚动交易数
使用rolling的window参数指定时间周期(如'5D'代表5天),通过on参数指定时间列,最后重置索引让结果与原数据对齐:
# 计算5天内滚动交易数 df1['rolling_5d_count'] = df1.groupby('userId')['transactionId'].rolling( window='5D', on='authorizationProcessedAt' ).count().reset_index(level=0, drop=True) # 计算10天内滚动交易数 df1['rolling_10d_count'] = df1.groupby('userId')['transactionId'].rolling( window='10D', on='authorizationProcessedAt' ).count().reset_index(level=0, drop=True) # 计算30天内滚动交易数 df1['rolling_30d_count'] = df1.groupby('userId')['transactionId'].rolling( window='30D', on='authorizationProcessedAt' ).count().reset_index(level=0, drop=True)
关键参数说明
window='5D':指定滚动窗口为5天,支持的时间单位包括'D'(天)、'H'(小时)、'M'(分钟)等。on='authorizationProcessedAt':指定用于计算窗口的时间列,无需将其设为索引,保持原数据结构更清晰。reset_index(level=0, drop=True):移除分组产生的userId索引层,让计算结果的索引与原数据一致,直接匹配到对应行。
测试示例
如果用以下测试数据验证:
test_data = { 'userId': ['u1', 'u1', 'u1', 'u2', 'u2'], 'authorizationProcessedAt': ['2022-11-01', '2022-11-03', '2022-11-07', '2022-11-02', '2022-11-06'], 'transactionId': ['t1', 't2', 't3', 't4', 't5'], 'amount': [100, 200, 300, 150, 250], 'merchantDescription': ['A', 'B', 'C', 'D', 'E'] } df_test = pd.DataFrame(test_data)
执行上述代码后,u1的第三条交易(2022-11-07)的rolling_5d_count会是1(仅自身,前两条交易距离超过5天),rolling_10d_count会是3(11.01、11.03、11.07都在10天内)。
内容的提问来源于stack exchange,提问作者Munessain
相关产品推荐
相关产品推荐

