Python Pandas-在缺少日期的组中有效地对滚动窗口应用功能

时间:2020-03-19 09:14:11

标签: python pandas pandas-groupby rolling-computation

注意:我已经知道了这个问题的答案,我之所以发布它,只是因为我在堆栈溢出时找不到正确的答案,这花了我很多时间才能解决。话虽如此,请随时提出其他选择。

问题

我有一个熊猫数据框架,其中有三列,一列跟踪日期,一列跟踪相关的观察值(即我的分组列),第三个变量存储一些数值。对于数据框中的每个组,我想计算日期列上的滚动总和。 警告::数据框中缺少某些日期,我想将其视为值为0的观察值。我不想使用交叉联接来添加所有日期。

可复制的示例

让我们有一个这样的数据框:

df = pd.DataFrame({'id_col' : np.array([1,1,1,1,1,1,2,2,2,2,2,3,3,3]),
                  'value_col' : np.random.randint(0,5,size=14),
                  'dates' : pd.to_datetime(np.array([
                  '2018-01-01',
                  '2018-02-01',
                  '2018-03-01',
                  '2018-05-01',
                  '2018-06-01',
                  '2018-09-01',
                  '2018-01-01',
                  '2018-02-01',
                  '2018-05-01',
                  '2018-06-01',
                  '2018-07-01',
                  '2018-01-01',
                  '2018-02-01',
                  '2018-03-01'])
                  )}
                 )

数据看起来像这样:

    id_col  value_col   dates
0   1   0   2018-01-01
1   1   1   2018-02-01
2   1   4   2018-03-01
3   1   0   2018-05-01
4   1   3   2018-06-01
5   1   3   2018-09-01
6   2   4   2018-01-01
7   2   3   2018-02-01
8   2   2   2018-05-01
9   2   0   2018-06-01
10  2   2   2018-07-01
11  3   4   2018-01-01
12  3   2   2018-02-01
13  3   3   2018-03-01

我尝试过但不起作用的方法:

选项1:完全忽略缺少的日期

df.groupby(['id_col']).rolling(2)['value_col'].sum().reset_index()

选项2:基于熊猫rolling documentation,使用熊猫偏移参数(返回ValueError: window must be an integer)替换窗口宽度。如果将dates列用作数据框的索引,则此方法将起作用。不幸的是,我们不能在此处使用简单索引,因为id_col中的2个不同的ID可以包含相同的日期。 (我们可以创建MultiIndex,但是会出现相同的值错误)。

df.groupby(['id_col']).rolling('60d')['value_col'].sum().reset_index()

什么是有效的,但不是很简单:

选项1:交叉联接以填写所有缺失的日期(如果您有很多数据,可能会很困难)

选项2:如本answer所述,从可迭代的笛卡尔积建立多索引。实际上,这与上述选项非常相似。

1 个答案:

答案 0 :(得分:1)

使用on的{​​{1}}参数。 documentation实际上提到了它,尽管没有示例可以看到适当的用法。幸运的是,存在熊猫github和this问题,如果您进行评论,则可以使您对如何正确使用带有偏移窗口的滚动功能有所了解。

因此,解决方案将是:

rolling

请注意,使用df.groupby(['id_col']).rolling('60d', on = 'dates')['value_col'].sum().reset_index() 代替2个月而不是60d是因为2m会给您带来以下错误:2m。有关此问题的更多信息,请检查stackoverflow问题here