Python 如何基于连续的行在两列中不做任何更改的情况下在Pandas中进行透视和聚合?
假设我有以下数据,并且需要下面显示的输出Python 如何基于连续的行在两列中不做任何更改的情况下在Pandas中进行透视和聚合?,python,pandas,pivot-table,aggregate,Python,Pandas,Pivot Table,Aggregate,假设我有以下数据,并且需要下面显示的输出 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': dateti
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
,然后按升序date
对表进行排序的。我需要一份给定工作的员工开始/结束日期的汇总表。需要注意的几点:
Joe
-他在工作1,然后是工作2,然后又回到工作1)。这应该为每个转换显示一个条目(参见输出数据中的行)如果不是连续的周期,我只需要创建一个透视表,按用户/作业分组,并按最大和最小日期聚合。但是,我不知道如何进行分组,当我查找具有相同
员工
和工作id
的连续行时,您可以通过两个分组进行分组:
# 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()
IIUC
我的逻辑与Quang Hoang相似,但我使用1 groupby,因为您说您的数据已按员工
和日期
排序。为连续相同的作业创建groupID\u id
,并将其保存为数组s
。我在这里不使用groupby
,因为在下一步中,在两个相邻的行中,相同的job\u id
,不同的employee
将由employee
和s
的groupby分开
s = data_df.job_id.diff().ne(0).cumsum().values
下一步,groupby
上的employee
,“job\u id”和s
。使用日期上的first
、last
调用agg
,并重置索引以放回列和
删除不需要的列。最后,将`列重命名为适当的名称
data_df.groupby(['employee', 'job_id', s], sort=False).date.agg(['first', 'last']) \
.reset_index().drop('level_2', 1) \
.rename(columns={'first': 'start_date', 'last': 'end_date'})
Out[1283]:
employee job_id start_date end_date
0 Joe 1 2019-06-10 2019-06-11
1 Joe 2 2019-06-12 2019-06-13
2 Joe 1 2019-06-14 2019-06-17
3 Jill 2 2019-06-10 2019-06-11
4 Jill 1 2019-06-12 2019-06-13
5 Jill 3 2019-06-14 2019-06-14
注意:我还测试了两个相邻行的样本数据,它们具有不同的
employee
,但具有相同的job\u id
。它仍然有效
Sample:
In [1289]: data_df
Out[1289]:
date employee job_id
0 2019-06-10 Joe 1
1 2019-06-11 Joe 1
2 2019-06-12 Joe 2
3 2019-06-13 Joe 2
4 2019-06-14 Joe 1
5 2019-06-10 Jill 1
6 2019-06-11 Jill 1
7 2019-06-12 Jill 2
8 2019-06-13 Jill 2
9 2019-06-14 Jill 3
s = data_df.job_id.diff().ne(0).cumsum().values
data_df.groupby(['employee', 'job_id', s], sort=False).date.agg(['first', 'last']) \
.reset_index().drop('level_2', 1) \
.rename(columns={'first': 'start_date', 'last': 'end_date'})
Out[1290]:
employee job_id start_date end_date
0 Joe 1 2019-06-10 2019-06-11
1 Joe 2 2019-06-12 2019-06-13
2 Joe 1 2019-06-14 2019-06-14
3 Jill 1 2019-06-10 2019-06-11
4 Jill 2 2019-06-12 2019-06-13
5 Jill 3 2019-06-14 2019-06-14
谢谢这似乎奏效了。快速提问-作业id行索引发生了什么变化?或者这仅仅是由于groupby引起的一些标签问题?这是来自
s
,其名称是job\u id
,而不是来自data\u df
。啊。。这是有道理的(不幸的是,我的ID使用了1、2、3,并且正好有3个组)。