提问人:mzietal 提问时间:11/15/2023 最后编辑:mzietal 更新时间:11/15/2023 访问量:56
将数据帧中的行与匹配的日期和总和值合并
Combine rows in dataframe with matching dates and sum values
问:
我有一个包含年假信息的数据帧。此 df 包含人员 ID、休假开始日期、休假结束日期和该期间的工作日数。在某些情况下,人们会单独保存多个单日假期,我希望将它们保存为一行。另外,我想将人们休息到周五的行合并,然后从下周一开始休息几天。
输入示例:
编号 | 开始日期 | 结束日期 | 工作日 |
---|---|---|---|
1 | 2023-10-09 | 2023-10-09 | 1 |
1 | 2023-10-10 | 2023-10-10 | 1 |
1 | 2023-10-11 | 2023-10-11 | 1 |
1 | 2023-10-19 | 2023-10-22 | 4 |
2 | 2023-10-19 | 2023-10-20 | 2 |
2 | 2023-10-23 | 2023-10-25 | 3 |
3 | 2023-10-23 | 2023-10-27 | 5 |
4 | 2023-10-23 | 2023-11-03 | 10 |
预期输出:
编号 | 开始日期 | 结束日期 | 工作日 |
---|---|---|---|
1 | 2023-10-09 | 2023-10-11 | 3 |
1 | 2023-10-19 | 2023-10-22 | 4 |
2 | 2023-10-19 | 2023-10-25 | 5 |
3 | 2023-10-23 | 2023-10-27 | 5 |
4 | 2023-10-23 | 2023-11-03 | 10 |
我试图通过添加一些额外的列来做到这一点,例如 EndDate 和下一个 StartDate 之间的时间,然后通过 np.where 创建 EndDate 和工作日的新值,但当有人连续三天或更多天时,它不起作用。此外,我在删除已经合并的行时遇到了一些问题。
你有什么想法吗?
此外,我是否可以设置一个阈值,例如 3 天或 5 天,在该阈值下将合并记录?例如,如果结束日期和开始日期之间的时间少于 5 天,那么这些行将被合并?
答:
0赞
Iñigo Moreno
11/15/2023
#1
您应该使用 pandas.groupby:
grouped_df = pd.DataFrame()
grouped_df['StartDate'] = df.groupby('ID')['StartDate'].min()
grouped_df['EndDate'] = df.groupby('ID')['EndDate'].max()
grouped_df['WorkingDays'] = df.groupby('ID')['WorkingDays'].sum()
评论
0赞
mzietal
11/15/2023
感谢您的回答,也许我在我的帖子中不是 100% 清楚,但单个员工可以有多天不应该合并的连续休假,例如 ID = 1 的员工。对于这个人,我们应该有两行,而在您的解决方案中,我们只有一行。
0赞
mozway
11/15/2023
#2
您需要设置一个二级石斑鱼来识别连续日期,同时考虑到具有 BusinessDay
偏移量的工作日:
# day offset
N = 1
# ensure datetime type
df[['StartDate', 'EndDate']] = df[['StartDate', 'EndDate']].apply(pd.to_datetime)
# group the days by consecutive dates
# the rows must be sorted by StartDate + EndDate
group = (df['EndDate']
.add(pd.offsets.BusinessDay(n=N))
.groupby(df['ID'])
.transform(lambda g: g.shift().lt(df['StartDate']).cumsum())
)
out = (df.groupby(['ID', group], as_index=False)
.agg({'StartDate': 'min',
'EndDate': 'max',
'WorkingDays': 'sum'})
)
输出:
ID StartDate EndDate WorkingDays
0 1 2023-10-09 2023-10-11 3
1 1 2023-10-19 2023-10-22 4
2 2 2023-10-19 2023-10-25 5
3 3 2023-10-23 2023-10-27 5
4 4 2023-10-23 2023-11-03 10
输出:N = 6
ID StartDate EndDate WorkingDays
0 1 2023-10-09 2023-10-22 7 # 2023-10-11 and 2023-10-19
1 2 2023-10-19 2023-10-25 5 # are within 6 business days
2 3 2023-10-23 2023-10-27 5
3 4 2023-10-23 2023-11-03 10
评论
1赞
mzietal
11/16/2023
谢谢,这正是我想要的!
评论