Python Pandas:基于OT存在条件重新计算DataFrame指定类别工时值
员工工时数据处理需求
我有一个记录员工不同类别工时的Pandas DataFrame,需求如下:
- 仅当某
Empl_Id下存在OT类别时,重新计算除OT、MILE和REST之外的所有类别的Value值 OT、MILE和REST类别值保持不变
示例数据
import pandas as pd data = {'Empl_Id': [1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 3, 3, 3], 'Category': ["MILE", "REST", "OT", "TRVL", "REG", "ADMIN", "REST", "REG", "MILE", "OT", "TRVL", "REST", "MAT", "REG"], 'Value': [43, 0.7, 6.33, 2.67, 52, 22, 1.17, 16.5, 73.6, 4.75, 1.33, 2.5, 5.5, 52.25]} df = pd.DataFrame(data=data)
初始数据
| Empl_Id | Category | Value |
|---|---|---|
| 1 | MILE | 43.00 |
| 1 | REST | 0.70 |
| 1 | OT | 6.33 |
| 1 | TRVL | 2.67 |
| 1 | REG | 52.00 |
| 2 | ADMIN | 22.00 |
| 2 | REST | 1.17 |
| 2 | REG | 16.50 |
| 3 | MILE | 73.60 |
| 3 | OT | 4.75 |
| 3 | TRVL | 1.33 |
| 3 | REST | 2.50 |
| 3 | MAT | 5.50 |
| 3 | REG | 52.25 |
计算逻辑
计算OT占比:仅对存在
OT的员工,计算OT工时占非OT、REST、MILE类别总工时的百分比- 员工1:
6.33/(2.67+52) ≈ 11.58% - 员工2:无
OT类别,不做任何更新 - 员工3:
4.75/(1.33+5.5+52.25) ≈ 8.04%
- 员工1:
调整目标类别值:将上述百分比从
OT、REST、MILE之外的类别Value中扣除,原类别值保持不变
实现代码
# 1. 标记存在OT的员工 has_ot = df.groupby('Empl_Id')['Category'].apply(lambda x: 'OT' in x.values).reset_index(name='has_ot') df = df.merge(has_ot, on='Empl_Id') # 2. 定义需要调整的类别 adjust_cats = ~df['Category'].isin(['OT', 'MILE', 'REST']) # 3. 计算每个员工的调整比例:OT工时 / 需调整类别总工时 def calculate_ratio(group): if not group['has_ot'].iloc[0]: group['ratio'] = 0 return group ot_hours = group.loc[group['Category'] == 'OT', 'Value'].sum() adjust_total = group.loc[adjust_cats, 'Value'].sum() group['ratio'] = ot_hours / adjust_total if adjust_total != 0 else 0 return group df = df.groupby('Empl_Id').apply(calculate_ratio).reset_index(drop=True) # 4. 调整目标类别的Value值,保留两位小数 df['Adjusted_Value'] = df.apply( lambda row: round(row['Value'] * (1 - row['ratio']), 2) if row['has_ot'] and adjust_cats.loc[row.name] else row['Value'], axis=1 ) # 5. 整理结果,去掉中间计算列 result_df = df[['Empl_Id', 'Category', 'Adjusted_Value']].rename(columns={'Adjusted_Value': 'Value'}) print(result_df)
处理后结果
| Empl_Id | Category | Value |
|---|---|---|
| 1 | MILE | 43.00 |
| 1 | REST | 0.70 |
| 1 | OT | 6.33 |
| 1 | TRVL | 2.36 |
| 1 | REG | 45.98 |
| 2 | ADMIN | 22.00 |
| 2 | REST | 1.17 |
| 2 | REG | 16.50 |
| 3 | MILE | 73.60 |
| 3 | OT | 4.75 |
| 3 | TRVL | 1.22 |
| 3 | REST | 2.50 |
| 3 | MAT | 5.06 |
| 3 | REG | 48.05 |
内容的提问来源于stack exchange,提问作者Yara1994
相关产品推荐
相关产品推荐

