考虑以下关于出版公司员工活动的假设会计记录:
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
...
假设python Pandas分析框架,我们可以(大多数情况下)依赖熊猫吗? API,而不是低级别,"逐位"编程吗?这个查询的问题是"开始"和"结束"每条记录的时间可以跨越几个月(不仅仅是一个月),因此这些记录将需要分拆"或者#34;爆炸"分成多个记录(每个记录涵盖一个月),然后我们可以使用通常的" groupby&总和"聚合做最后的减少。
从未在SQL或数据库中接受过正式培训,我不知道数据分析中是否存在这样的概念,因此我不知道正确的名称。在Spark中,我认为可以做到这一点,因为RDD flatMap
可以从单个元素中返回多个元素。
谢谢, Wirawan
答案 0 :(得分:0)
首先,在每个开始日期和结束日期之间创建一个密集的长数据帧。为此,Pandas 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