如何在Pandas的groupby中进行滚动窗口聚合?

时间:2018-04-03 09:04:43

标签: python pandas pandas-groupby

编辑:我意识到时间窗口不是我想到的,所以下面的解决方案似乎确实有效:/

我想对变量val和时间t进行滚动窗口聚合,但每个窗口应该在分类变量cat内。

我还想保留旧列,只是在它们旁边生成一个新的聚合列。

所以我试过

import random
import numpy as np
import pandas as pd

N=100
np.random.seed(0)
random.seed(0)

df = pd.DataFrame({"t": [pd.Timestamp(1514764800+random.randint(0, 10000000), unit="s") for _ in range(N)],
                   "cat": np.random.choice(["a", "b", "c"], size=N),
                   "val": np.random.randint(1,10, size=N),
                  })

df_agg = (df.groupby("cat", group_keys=False)
            .apply(lambda d:d.assign(aggval=d.sort_values("t")
                                             .rolling("7d", on="t")
                                             ["val"].agg("sum")
                                     )
                   )
          ).sort_values(["cat", "t"])

-->
   cat                   t  val  aggval
41   a 2018-01-01 05:19:33    5     5.0
38   a 2018-01-03 17:26:20    9    14.0
2    a 2018-01-08 20:40:15    6    15.0
36   a 2018-01-13 02:14:38    9    15.0
22   a 2018-01-15 07:39:52    1    16.0
89   a 2018-01-16 13:59:03    6    16.0
85   a 2018-01-18 10:36:42    9    25.0
...

但这似乎没有让订单正确。

这样做的正确方法是什么?

1 个答案:

答案 0 :(得分:2)

可以使用此替代解决方案join用于新列:

df_agg1 = (df.join(df.sort_values("t")
                   .set_index('t')
                   .groupby("cat")
                   .rolling("7d")["val"].sum()
                   .rename('aggval'), on=['cat','t'])
                   .sort_values(["cat", "t"]))
print (df_agg1.head(10))
   cat                   t  val aggval
41   a 2018-01-01 05:19:33    5    5.0
38   a 2018-01-03 17:26:20    9   14.0
2    a 2018-01-08 20:40:15    6   15.0
36   a 2018-01-13 02:14:38    9   15.0
22   a 2018-01-15 07:39:52    1   16.0
89   a 2018-01-16 13:59:03    6   16.0
85   a 2018-01-18 10:36:42    9   25.0
26   a 2018-01-20 13:18:05    4   20.0
15   a 2018-01-28 03:15:45    2    2.0
78   a 2018-02-05 16:53:25    6    6.0

print ((df_agg == df_agg1).all())
cat       True
t         True
val       True
aggval    True
dtype: bool

如果不需要新栏目:

df_agg = (df.sort_values("t")
             .set_index('t')
             .groupby("cat")
             .rolling("7d")["val"].sum()
             .reset_index()
             )
print (df_agg.head(10))
  cat                   t   val
0   a 2018-01-01 05:19:33   5.0
1   a 2018-01-03 17:26:20  14.0
2   a 2018-01-08 20:40:15  15.0
3   a 2018-01-13 02:14:38  15.0
4   a 2018-01-15 07:39:52  16.0
5   a 2018-01-16 13:59:03  16.0
6   a 2018-01-18 10:36:42  25.0
7   a 2018-01-20 13:18:05  20.0
8   a 2018-01-28 03:15:45   2.0
9   a 2018-02-05 16:53:25   6.0