2017-01-20 87 views
2

考虑人员活动如下假设会计记录在一家出版公司:分析:分总结记录

Name   Activity  Begin-date  End-date 
--------------------------------------------------------- 
Hasan   Proofreading 2015-01-27  2015-02-09 
Susan   Writing   2015-02-01  2015-02-15 
Peter   Editing   2015-01-01  2015-02-21 
Paul   Editing   2015-01-24  2015-01-30 
Stefan  Proofreading 2015-01-08  2015-01-08 
... 

这些代表,每个人在做,包括开始日期和结束日期(含日期)的活动。假设这家公司的高管想知道每个月在不同的活动上花了多少工作日。所需的报告可能是这样的:

Month  Activity   Man-hours 
---------------------------------------- 
2015-01  Proofreading  720 
2015-01  Editing   1283 
2015-01  Writing   473 
2015-02  Proofreading  1101 
2015-02  Editing   893 
2015-02  Writing   573 
... 

假设蟒蛇熊猫分析框架,我们可以做到这一点依靠(主要是)对大熊猫的API,而不是做一个较低的水平,‘逐位’编程?这个查询的问题是,每个记录的“开始”和“结束”时间可能跨越数月(不只是一个月),所以这些记录需要被“拆分”或“爆炸”成多个记录每个期限为一个月),然后我们可以使用通常的“groupby & sum”聚合来做最后的减少。

从未接受过SQL或数据库方面的正式培训,我不知道数据分析中是否有这样的概念,所以我不知道正确的名称。在Spark中,我认为这可以完成,因为RDD flatMap可以从单个元素中返回多个元素。

感谢, Wirawan

回答

0

首先,创建一个密集的长数据帧以每天每间开始日期和结束日期。为此,熊猫有pd.date_range从两个日期生成DatetimeIndex。假设人们在周末工作,让我们使用一个工作日的频率,但你可以使用任何有用的频率为你的情况。

从这个范围我们做一些与stack重新格式化和一些索引重置。它导致:

df =(df.set_index(['name', 'activity']) 
     .apply(lambda r : pd.Series(pd.date_range(r['begindate'],r['enddate'], freq='B')), 
       axis=1) 
     .stack() 
     .rename('date') 
     .reset_index(level=-1, drop=True) 
     .reset_index()) 
Out[73]: 
     name  activity  date 
0 Hasan Proofreading 2015-01-27 
1 Hasan Proofreading 2015-01-28 
2 Hasan Proofreading 2015-01-29 
3 Hasan Proofreading 2015-01-30 
4 Hasan Proofreading 2015-02-02 
..  ...   ...  ... 
10 Susan  Writing 2015-02-02 
11 Susan  Writing 2015-02-03 
..  ...   ...  ... 

现在你可以做你的月度聚合。将日期转换为每月期间并对其进行分组:

df.groupby(['activity',df.date.dt.to_period('M')]).size() 
Out[97]: 
activity  date 
Editing  2015-01 27 
       2015-02 15 
Proofreading 2015-01  5 
       2015-02  6 
Writing  2015-02 10