使用Python Pandas处理顺序日志:格式转换、时间差计算及pivot报错解决
解决方案
报错原因
原代码使用pivot报错,是因为同一个user_id + token + action_id分组下存在多条重复记录,pivot要求索引+列的组合必须唯一,所以需要对重复动作做聚合处理,顺序日志场景下通常取每个分组下最早的动作时间即可。
调整后代码实现
预期输出1代码
import pandas as pd # 带重复动作的测试数据 df = pd.DataFrame({ 'user_id': [7, 12, 45, 7, 12, 12, 7, 12, 7, 12, 91, 12, 12, 91, 91, 91, 91, 45], 'token': [223, 191, 667, 223, 191, 339, 223, 339, 564, 778, 551, 778, 778, 551, 551, 551, 551, 122], 'action_id': [1, 1, 2, 3, 2, 1, 2, 2, 1, 1, 1, 4, 5, 5, 3, 5, 2, 1], 'action_timestamp': [f'timestamp{x}' for x in range(1,19)] }) # 实际场景请先将时间戳转为datetime类型,方便后续计算时间差 # df['action_timestamp'] = pd.to_datetime(df['action_timestamp']) # 用pivot_table替代pivot,指定aggfunc自动处理重复记录,这里取min即保留最早的动作时间 output1 = df[df['action_id'].isin([1,2])].pivot_table( index=['user_id', 'token'], columns='action_id', values='action_timestamp', aggfunc='min' ).add_prefix('timestamp_action_id_').reset_index().rename_axis(None, axis=1) # 筛除不同时存在action_id=1和action_id=2的记录 output1 = output1.dropna().reset_index(drop=True) print(output1)
预期输出2代码
# 计算每个有效token的动作时间差,以下为测试数据的字符串时间转数值差逻辑,实际场景替换为datetime相减即可 # output1['delta'] = output1['timestamp_action_id_2'] - output1['timestamp_action_id_1'] output1['delta'] = output1['timestamp_action_id_2'].str.replace('timestamp','').astype(int) - output1['timestamp_action_id_1'].str.replace('timestamp','').astype(int) # 按user_id分组计算平均时间差 output2 = output1.groupby('user_id', as_index=False)['delta'].mean().rename( columns={'delta':'action_id_1_to_action_id_2_time_delta_average'} ) print(output2)
逻辑说明
如果业务需求不是取最早的动作,而是取最晚的动作,将aggfunc='min'修改为aggfunc='max'即可;如果需要取action_id=1之后出现的第一个action_id=2,可以先对每个user_id+token分组下的日志按时间升序排序,再去重保留每个action_id的第一条记录,后续处理逻辑和上述代码一致。
内容的提问来源于stack exchange,提问作者Aerodyne
相关产品推荐
相关产品推荐

