基于Pandas按ID分组计算部门变更累计次数的技术问题
问题描述
现有一份记录客服工单审计轨迹的Pandas DataFrame,每条数据记录工单在不同部门的流转时段。需要按ID分组,生成每次部门变更(包括返回已去过的部门)的累计计数。
输入数据
| ID | Department | Start Date | End Date |
|---|---|---|---|
| A | Sales | 01/01/2022 | 02/01/2022 |
| A | Sales | 02/01/2022 | 03/01/2022 |
| A | Operations | 03/01/2022 | 04/01/2022 |
| A | Sales | 04/01/2022 | 05/01/2022 |
| B | Finance | 01/01/2022 | 02/01/2022 |
| B | Risk | 02/01/2022 | 03/01/2022 |
期望输出
新增Count of Department Change列,记录累计变更次数(同一ID下,每发生一次部门切换,计数累加,初始行计数为0)。
当前尝试代码
用户已实现变更标记,但无法生成分组累计计数:
import numpy as np df['Dept_Change_Count'] = np.where((df['Department'] != df['Department'].shift(1)) & (df['ID'] == df['ID'].shift(1)), '1', '0')
解决方案
要实现分组累计计数,核心是在同一ID分组内判断部门变更,再对变更标记做组内累加。步骤如下:
- 先按
ID和Start Date排序,确保工单流转顺序正确:
df = df.sort_values(['ID', 'Start Date']).reset_index(drop=True)
- 生成组内的部门变更标记(布尔值):
df['is_change'] = df.groupby('ID')['Department'].apply(lambda x: x != x.shift())
通过groupby('ID')限定只在同一工单ID内比较前后行的部门,避免跨ID误判。
- 对变更标记做组内累计求和,得到累计变更次数:
df['Count of Department Change'] = df.groupby('ID')['is_change'].cumsum().astype(int)
完整代码
import pandas as pd import numpy as np # 构造示例数据 data = { 'ID': ['A', 'A', 'A', 'A', 'B', 'B'], 'Department': ['Sales', 'Sales', 'Operations', 'Sales', 'Finance', 'Risk'], 'Start Date': ['01/01/2022', '02/01/2022', '03/01/2022', '04/01/2022', '01/01/2022', '02/01/2022'], 'End Date': ['02/01/2022', '03/01/2022', '04/01/2022', '05/01/2022', '02/01/2022', '03/01/2022'] } df = pd.DataFrame(data) # 排序确保流转顺序正确 df = df.sort_values(['ID', 'Start Date']).reset_index(drop=True) # 生成组内变更标记 df['is_change'] = df.groupby('ID')['Department'].apply(lambda x: x != x.shift()) # 组内累计求和得到变更计数 df['Count of Department Change'] = df.groupby('ID')['is_change'].cumsum().astype(int) # 可选:删除中间辅助列 df = df.drop('is_change', axis=1) print(df)
最终输出
| ID | Department | Start Date | End Date | Count of Department Change |
|---|---|---|---|---|
| A | Sales | 01/01/2022 | 02/01/2022 | 0 |
| A | Sales | 02/01/2022 | 03/01/2022 | 0 |
| A | Operations | 03/01/2022 | 04/01/2022 | 1 |
| A | Sales | 04/01/2022 | 05/01/2022 | 2 |
| B | Finance | 01/01/2022 | 02/01/2022 | 0 |
| B | Risk | 02/01/2022 | 03/01/2022 | 1 |
内容的提问来源于stack exchange,提问作者Scott Renfree-Tuck
相关产品推荐
相关产品推荐

