如何识别多非排序任务列中重复分配给用户的任务?
问题:识别重复分配的任务用户
首先构建测试用DataFrame:
import pandas as pd df = pd.DataFrame({'user': ['u1', 'u2', 'u3', 'u4', 'u5'], 'date': ['1. August 2023', '5. January 2023', '2. May 2023', '13. July 2023', '1. January 2023'], 'task1': ['A', 'D', 'G', 'B', 'J'], 'task2': ['B', 'E', 'H', 'D', 'K'], 'task3': ['C', 'F', 'A', 'I', 'L']}) print(df)
输出结果:
user date task1 task2 task3 0 u1 1. August 2023 A B C 1 u2 5. January 2023 D E F 2 u3 2. May 2023 G H A 3 u4 13. July 2023 B D I 4 u5 1. January 2023 J K L
需求:识别被分配了已属于其他用户任务的用户。
尝试的代码(返回空DataFrame,不符合预期):
new_df = df.copy() new_df["date"] = pd.to_datetime(new_df["date"], format="%d. %B %Y") new_df = new_df.sort_values("date") new_df = new_df.loc[new_df[['task1', 'task2', 'task3']].duplicated()]
预期输出:
tasks_to_reassign = {'u4': ['task2'], 'u1': ['task1', 'task2']}
原因:u4在2023年7月13日被分配的task2(D)已在2023年1月5日分配给u2;u1在2023年8月1日被分配的task1(A)和task2(B),此前已分别分配给u3(2023年5月2日)和u4(2023年7月13日)。
解决方案
你的问题在于duplicated()是检查整行任务列是否完全重复,但实际需要追踪单个任务值是否在更早日期被其他用户分配过,而非整行重复。按以下步骤实现:
步骤1:预处理数据,转换日期并排序
先将日期转为datetime类型,按日期升序排列,确保处理顺序从早到晚:
new_df = df.copy() new_df["date"] = pd.to_datetime(new_df["date"], format="%d. %B %Y") new_df = new_df.sort_values("date").reset_index(drop=True)
步骤2:将宽表转为长格式,便于追踪单任务分配历史
把多任务列拆成每行对应一个用户-日期-任务类型-任务值的记录:
melted = new_df.melt( id_vars=['user', 'date'], value_vars=['task1', 'task2', 'task3'], var_name='task_type', value_name='task_value' )
步骤3:遍历标记重复分配的任务
用字典记录每个任务的首次归属用户,遍历每行数据检查是否存在跨用户的重复分配:
task_assigned = {} tasks_to_reassign = {} for idx, row in melted.iterrows(): user = row['user'] task_val = row['task_value'] task_type = row['task_type'] # 任务已被其他用户分配过,标记为需要重分配 if task_val in task_assigned and task_assigned[task_val] != user: if user not in tasks_to_reassign: tasks_to_reassign[user] = [] tasks_to_reassign[user].append(task_type) # 任务未被分配过,记录首次归属用户 elif task_val not in task_assigned: task_assigned[task_val] = user
最终结果
运行后得到预期输出:
print(tasks_to_reassign) # 输出:{'u4': ['task2'], 'u1': ['task1', 'task2']}
补充说明
- 代码按日期顺序处理,仅标记晚于首次分配的跨用户重复任务;
- 当前逻辑允许同一用户重复分配自己的任务,若需禁止自重复,可去掉
task_assigned[task_val] != user的判断;
内容的提问来源于stack exchange,提问作者VERBOSE
相关产品推荐
相关产品推荐

