如何用Python-Pandas基于UserID检测重叠项目报名?
问题描述
现有三个独立CSV文件:
- Exit文件:包含退出日期、UserID、ProjectID
- Entry文件:包含报名日期、UserID、ProjectID
- Project文件:包含有效ProjectID及ProjectType(有效值为0、1、2)
需求:找出在有效项目中存在重叠报名的用户——即同一用户出现两次报名日期早于一次退出日期的情况。
原思路:先用isin()筛选有效项目ID的数据集,再为每个UserID创建包含日期和事件类型的数组,排序后检查是否符合“奇数项为报名、偶数项为退出”的规则,不符合则判定为存在重叠。但不想用iterrows()迭代,希望用向量操作实现。
原代码片段:
exit = pd.read_csv('exit.csv') enroll = pd.read_csv('enroll.csv') project = pd.read_csv('project.csv') df = pd.DataFrame(project) ProjectTypes = [0, 1, 2] project_valid = df[(df['ProjectType'].isin(ProjectTypes))] df = pd.DataFrame(enroll) enrollvalid = (df['ProjectID'].isin(project_valid['ProjectID'])) print("Enroll valids \n") df = df[enrollvalid] # 输出有效用户ID print(df['userID'])
解决方案
1. 数据预处理:过滤有效项目数据
首先统一筛选出有效项目对应的报名和退出记录:
import pandas as pd # 读取数据 exit_df = pd.read_csv('exit.csv') enroll_df = pd.read_csv('enroll.csv') project_df = pd.read_csv('project.csv') # 筛选有效项目(ProjectType为0、1、2) valid_project_ids = project_df[project_df['ProjectType'].isin([0,1,2])]['ProjectID'].unique() # 过滤报名和退出数据,只保留有效项目的记录 enroll_valid = enroll_df[enroll_df['ProjectID'].isin(valid_project_ids)].copy() exit_valid = exit_df[exit_df['ProjectID'].isin(valid_project_ids)].copy()
2. 构造统一事件序列(替代iterrows的核心操作)
把报名和退出数据合并,标记事件类型,然后按用户和日期排序:
# 为报名数据添加事件类型标记(1代表报名) enroll_valid['event_type'] = 1 enroll_valid = enroll_valid.rename(columns={'报名日期': 'date'})[['UserID', 'date', 'event_type']] # 为退出数据添加事件类型标记(-1代表退出) exit_valid['event_type'] = -1 exit_valid = exit_valid.rename(columns={'退出日期': 'date'})[['UserID', 'date', 'event_type']] # 合并两个事件数据集 events = pd.concat([enroll_valid, exit_valid], ignore_index=True) # 按UserID分组,对每个用户的事件按日期排序 events['date'] = pd.to_datetime(events['date']) # 确保日期是datetime类型 events_sorted = events.sort_values(by=['UserID', 'date'])
3. 检测重叠报名(向量式操作,无需迭代)
通过计算累计事件值来检测重叠:累计值>1时,说明当前存在未退出的报名(重叠)。
# 按用户计算累计事件值 events_sorted['active_enrolls'] = events_sorted.groupby('UserID')['event_type'].cumsum() # 找出存在重叠的用户:只要该用户有任意一条记录的active_enrolls>1,就判定为重叠 overlap_users = events_sorted[events_sorted['active_enrolls'] > 1]['UserID'].unique() print("存在重叠报名的用户ID:", overlap_users)
更优检测逻辑说明
这种方法比“检查奇偶项”更准确:
- 无需依赖“报名-退出严格交替”的假设,能处理多次报名/退出的复杂场景
- 完全用Pandas的分组和向量运算实现,效率远高于
iterrows()迭代 - 直接通过累计值判断当前活跃报名数,逻辑清晰且覆盖所有重叠情况
内容的提问来源于stack exchange,提问作者Eric Parson
相关产品推荐
相关产品推荐

