可以说我有以下数据,并且需要下面显示的输出。
import pandas as pd
data = [
{'job_id': 1, 'employee': 'Joe', 'date': datetime.date(2019, 6, 10)},
{'job_id': 1, 'employee': 'Joe', 'date': datetime.date(2019, 6, 11)},
{'job_id': 2, 'employee': 'Joe', 'date': datetime.date(2019, 6, 12)},
{'job_id': 2, 'employee': 'Joe', 'date': datetime.date(2019, 6, 13)},
{'job_id': 1, 'employee': 'Joe', 'date': datetime.date(2019, 6, 14)},
{'job_id': 1, 'employee': 'Joe', 'date': datetime.date(2019, 6, 17)},
{'job_id': 2, 'employee': 'Jill', 'date': datetime.date(2019, 6, 10)},
{'job_id': 2, 'employee': 'Jill', 'date': datetime.date(2019, 6, 11)},
{'job_id': 1, 'employee': 'Jill', 'date': datetime.date(2019, 6, 12)},
{'job_id': 1, 'employee': 'Jill', 'date': datetime.date(2019, 6, 13)},
{'job_id': 3, 'employee': 'Jill', 'date': datetime.date(2019, 6, 14)}
]
data_df = pd.DataFrame(data)
output_data = [
{'job_id': 1, 'employee': 'Joe', 'start_date': datetime.date(2019, 6, 10), 'end_date': datetime.date(2019, 6, 11)},
{'job_id': 2, 'employee': 'Joe', 'start_date': datetime.date(2019, 6, 12), 'end_date': datetime.date(2019, 6, 13)},
{'job_id': 1, 'employee': 'Joe', 'start_date': datetime.date(2019, 6, 14), 'end_date': datetime.date(2019, 6, 17)},
{'job_id': 2, 'employee': 'Jill', 'start_date': datetime.date(2019, 6, 10), 'end_date': datetime.date(2019, 6, 11)},
{'job_id': 1, 'employee': 'Jill', 'start_date': datetime.date(2019, 6, 12), 'end_date': datetime.date(2019, 6, 13)},
{'job_id': 3, 'employee': 'Jill', 'start_date': datetime.date(2019, 6, 14), 'end_date': datetime.date(2019, 6, 14)}
]
output_df = pd.DataFrame(output_data)
本质上,我让表按employee
顺序排列,然后按升序排列。我需要汇总给定工作的员工的start/end日期。注意事项:
- 员工可以先工作,再转到另一份工作,然后再回到第一份工作(请参阅
Joe
-他先完成工作1,然后进行2,然后再回到1)。这应该显示每个转换的条目(请参见输出数据中的行)。 - 该员工可能连续几天都没有工作(例如,周末休息2天),但是如果他在Thurs和Fri上班,然后在周一返回工作岗位,那么Thurs-Monday都将获得一份工作。同样,在工作1的第二天见
Joe
。 - 员工可能只工作一天。在这种情况下,start_date和end_date应该是同一天(请参阅作业3的
Jill
)。 - 一名员工每天只能从事一份工作。
如果不是连续的时间段,那么我将转到数据透视表,按user/job分组,然后按最大日期和最小日期进行汇总。但是,当我寻找具有相同employee
和job_id
的连续行时,我不确定如何进行分组。
分析解答
IIUC,您可以通过两个groupby来这样做:
# to mask the jobs chunks separately
s = data_df.groupby('employee').job_id.apply(lambda x: x.ne(x.shift()).cumsum())
out_df = data_df.groupby(['employee', s]).agg({'job_id':'first', 'date':{'min','max'}})
给出:
job_id date
job_id max min
employee job_id
Jill 1 2 2019-06-11 2019-06-10
2 1 2019-06-13 2019-06-12
3 3 2019-06-14 2019-06-14
Joe 1 1 2019-06-11 2019-06-10
2 2 2019-06-13 2019-06-12
3 1 2019-06-17 2019-06-14
可以通过以下方式将其更改为您的表格:
out_df.columns = ['job_id', 'end_date', 'start_date']
out_df = out_df.reset_index(level=1,drop=True).reset_index()