将数据帧中的行与匹配的日期和总和值合并

Combine rows in dataframe with matching dates and sum values

提问人:mzietal 提问时间:11/15/2023 最后编辑:mzietal 更新时间:11/15/2023 访问量:56

问:

我有一个包含年假信息的数据帧。此 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 天,那么这些行将被合并?

python pandas datetime group-by

评论


答:

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
谢谢,这正是我想要的!