如何用Pandas筛选在buy与add事件间存在cancel事件的用户
筛选符合条件用户的简便实现方案
针对你需要筛选存在cancel事件发生在buy之后、add之前的用户需求,这里提供几种比原方法更简洁直观的实现方式:
方法一:分组遍历检查(逻辑清晰)
先对用户分组,提取每个用户的三类事件时间,直接判断是否存在满足时间关系的cancel事件:
import pandas as pd # 转换时间列为datetime类型(必须步骤) df['timestamp'] = pd.to_datetime(df['timestamp']) target_users = [] # 按用户分组处理 for user_id, group in df.groupby('user_id'): # 按时间排序事件 sorted_events = group.sort_values('timestamp') # 提取各类事件的时间列表 buy_times = sorted_events[sorted_events['event'] == 'buy']['timestamp'].tolist() cancel_times = sorted_events[sorted_events['event'] == 'cancel']['timestamp'].tolist() add_times = sorted_events[sorted_events['event'] == 'add']['timestamp'].tolist() # 检查是否有cancel落在任意buy和add之间 for cancel_t in cancel_times: has_earlier_buy = any(buy_t < cancel_t for buy_t in buy_times) has_later_add = any(add_t > cancel_t for add_t in add_times) if has_earlier_buy and has_later_add: target_users.append(user_id) break # 找到一个符合条件的就停止检查该用户 print(target_users) # 输出:[1, 3]
方法二:关联事件表筛选(代码简洁)
把buy、cancel、add三类事件单独提取后按用户关联,直接筛选满足时间顺序的组合,最后去重得到用户:
import pandas as pd df['timestamp'] = pd.to_datetime(df['timestamp']) # 提取三类事件并重命名时间列 buy_df = df[df['event'] == 'buy'][['user_id', 'timestamp']].rename(columns={'timestamp': 'buy_time'}) cancel_df = df[df['event'] == 'cancel'][['user_id', 'timestamp']].rename(columns={'timestamp': 'cancel_time'}) add_df = df[df['event'] == 'add'][['user_id', 'timestamp']].rename(columns={'timestamp': 'add_time'}) # 按用户关联三类事件,筛选时间符合条件的记录 valid_combinations = pd.merge(pd.merge(buy_df, cancel_df, on='user_id'), add_df, on='user_id') valid_combinations = valid_combinations[(valid_combinations['buy_time'] < valid_combinations['cancel_time']) & (valid_combinations['cancel_time'] < valid_combinations['add_time'])] # 去重得到目标用户 target_users = valid_combinations['user_id'].unique().tolist() print(target_users) # 输出:[1, 3]
方法三:分组标记前后事件(高效处理大数据)
利用分组transform给每个cancel事件标记是否存在更早的buy和更晚的add,再筛选符合条件的用户:
import pandas as pd df['timestamp'] = pd.to_datetime(df['timestamp']) # 按用户和时间排序 df_sorted = df.sort_values(['user_id', 'timestamp']) # 标记每个时间点之前是否出现过buy def mark_buy_before(ts_series): user_data = df_sorted[df_sorted['user_id'] == ts_series.name] buy_times = user_data[user_data['event'] == 'buy']['timestamp'] return ts_series.apply(lambda t: any(t > bt for bt in buy_times)) # 标记每个时间点之后是否出现过add def mark_add_after(ts_series): user_data = df_sorted[df_sorted['user_id'] == ts_series.name] add_times = user_data[user_data['event'] == 'add']['timestamp'] return ts_series.apply(lambda t: any(t < at for at in add_times)) df_sorted['has_buy_before'] = df_sorted.groupby('user_id')['timestamp'].transform(mark_buy_before) df_sorted['has_add_after'] = df_sorted.groupby('user_id')['timestamp'].transform(mark_add_after) # 筛选符合条件的cancel事件对应的用户,去重 target_users = df_sorted[(df_sorted['event'] == 'cancel') & df_sorted['has_buy_before'] & df_sorted['has_add_after']]['user_id'].unique().tolist() print(target_users) # 输出:[1, 3]
内容的提问来源于stack exchange,提问作者clssyyy123
相关产品推荐
相关产品推荐

