如何滚动窗口聚合但将唯一索引列保留在Pandas中?

时间:2019-08-01 19:03:17

标签: python pandas

我想滚动窗口聚合一个数据框,但是我的结果必须保留具有唯一索引的列是至关重要的,因为稍后我想将聚合重新加入到原始数据框中。

就像

df = pd.DataFrame(
   {"id": range(6),
    "t": [pd.Timestamp("2019-01-01")+dt.timedelta(seconds=sec) for sec in [2, 2, 1, 1, 1, 1]],
    "gr": list("ababab"),
    "val": range(6)})

agg = df.groupby("gr").rolling("2s", on="t")["val"].sum()  # <- id not present anymore

现在,我想将agg加入df上的id中,但是不幸的是,熊猫rolling使t成为了多索引级别。 (时间t实际上不是唯一的)

有什么办法可以在id中获得agg吗?

看着

>>> df.sort_values(["gr", "t"])
   id                   t gr  val
2   3 2019-01-01 00:00:01  a    2
4   1 2019-01-01 00:00:01  a    4
0   5 2019-01-01 00:00:02  a    0
3   2 2019-01-01 00:00:01  b    3
5   0 2019-01-01 00:00:01  b    5
1   4 2019-01-01 00:00:02  b    1

预期金额应为

   id                   t gr  sum_val
2   3 2019-01-01 00:00:01  a    2
4   1 2019-01-01 00:00:01  a    6
0   5 2019-01-01 00:00:02  a    6
3   2 2019-01-01 00:00:01  b    3
5   0 2019-01-01 00:00:01  b    8
1   4 2019-01-01 00:00:02  b    9

但是,一种建议的解决方案的输出是

agg = df.sort_values("t").groupby(['gr']).rolling("2s", on="t")['val'].sum().reset_index(name='sum_val')
agg['id'] = df.sort_values(['gr'])['id'].values
agg.sort_values(["gr", "t"])

输出:

  gr                   t  sum_val  id
0  a 2019-01-01 00:00:01      2.0   5
1  a 2019-01-01 00:00:01      6.0   3
2  a 2019-01-01 00:00:02      6.0   1
3  b 2019-01-01 00:00:01      3.0   4
4  b 2019-01-01 00:00:01      8.0   2
5  b 2019-01-01 00:00:02      9.0   0

gr='a'id=5应该是6?!

更新:我花了很多时间来演示这个问题。 更新:将t设置为时间列,因为在它没有做应做的事情之前。

2 个答案:

答案 0 :(得分:1)

由于t在组中不是唯一的,但是id是唯一的,并且您正在gr上分组,因此您可以执行以下操作:

agg = df.groupby(['gr']).rolling(2, on="t")['val'].sum().reset_index(name='sum_val')
agg['id'] = df.sort_values(['gr'])['id'].values

输出:

    gr  t   sum_val id
0   a   1   NaN 0
1   a   1   2.0 2
2   a   2   6.0 4
3   b   1   NaN 1
4   b   1   4.0 3
5   b   2   8.0 5

如果t是唯一的,则可以执行以下操作:

您可以与原始df合并

df.groupby(['gr']).rolling(2, on="t")['val'].sum().reset_index(name='sum_val').merge(df[['id', 't', 'gr']])

输出:

    gr  t   sum_val id
0   a   1   NaN      0
1   a   2   2.0      2
2   a   3   6.0      4
3   b   1   NaN      1
4   b   2   4.0      3
5   b   3   8.0      5

答案 1 :(得分:0)

您的意思是:

df['roll'] = (df.groupby("gr", as_index=False, group_keys=False)
                .apply(lambda x: x.rolling(2, on='t')['val'].sum())
             )

输出:

   id  t gr  val  roll
0   0  1  a    0   NaN
1   1  1  b    1   NaN
2   2  1  a    2   2.0
3   3  1  b    3   4.0
4   4  2  a    4   6.0
5   5  2  b    5   8.0