首页 > 解决方案 > 每半年重新采样一次,累积总和

问题描述

我有一个包含每月数据的数据框,例如:

Date          Value
2016-12-01    0
2017-01-01    10
2017-02-01    20
2017-03-01    15
2017-04-01    25
2017-05-01    35
2017-06-01    1
2017-07-01    2
2018-08-01    3
2018-09-01    4
2018-10-01    5
2018-11-01    6

我想取每个月的半年累计总和,但年末是 5 月而不是 12 月。因此,一年内将有两个 6 个月期间的累计金额。所以输出应该是:

Date          Value
2016-12-01    0
2017-01-01    10
2017-02-01    30
2017-03-01    45
2017-04-01    70
2017-05-01    105

2017-06-01    1
2017-07-01    3
2018-08-01    6
2018-09-01    10
2018-10-01    15
2018-11-01    21

我试过这个:

import_monthly.groupby(by=[pd.Grouper(freq='2Q-MAY'), pd.Grouper(freq='A-MAY')]).cumsum()

但它将我的累计日期固定在 2 月 17 日和 8 月 17 日,而不是 5 月 17 日和 11 月 17 日。它也仍然在 5 月结束这一年,因此即使对于这两个 6 个月期间,它也没有正确的 2 个累积总和。我究竟做错了什么?

标签: pythonpandaspandas-groupby

解决方案


这个问题让我意识到 pandas 季度锚定偏移量变化无常,我仍然不太了解它们是如何工作的。基于这个 SO question and answer,我能够获得预期输出的唯一方法是添加一个虚拟值作为索引为 5 月 1 日或 11 月 1 日的第一行。根据@chrisb 在另一个答案中的说法,这有与在 offset 中的事实有关,在应用乘数之前计算/应用2Q-NOV锚点。NOV2

从您的 DataFrame 开始:

# Insert a sentinel value into the first row to influence
# the behaviour of the anchored-offset groupby.
# Inserting at 2015-11-01 would work too
df.loc[pd.to_datetime('2015-05-01'), 'Value'] = 0
df.sort_index(inplace=True)

df.groupby(pd.Grouper(freq='2Q-NOV')).cumsum()

            Value
Date             
2015-05-01    0.0
2016-12-01    0.0
2017-01-01   10.0
2017-02-01   30.0
2017-03-01   45.0
2017-04-01   70.0
2017-05-01  105.0
2017-06-01    1.0
2017-07-01    3.0
2018-08-01    3.0
2018-09-01    7.0
2018-10-01   12.0
2018-11-01   18.0

# Workaround: groupby with the sentinel value, then immediately drop it
df.groupby(pd.Grouper(freq='2Q-NOV')).cumsum().drop(pd.to_datetime('2015-05-01'))

            Value
Date             
2016-12-01    0.0
2017-01-01   10.0
2017-02-01   30.0
2017-03-01   45.0
2017-04-01   70.0
2017-05-01  105.0
2017-06-01    1.0
2017-07-01    3.0
2018-08-01    3.0
2018-09-01    7.0
2018-10-01   12.0
2018-11-01   18.0

推荐阅读