Pandas Rolling mean based on groupby multiple columns

Viewed 3824

I have a Long format dataframe with repeated values in two columns and data in another column. I want to find SMAs for each group. My problem is : rolling() simply ignores the fact that the data is grouped by two columns.

Here is some dummy data and code.

import numpy as np
import pandas as pd

dtix=pd.Series(pd.date_range(start='1/1/2019', periods=4) )
df=pd.DataFrame({'ix1':np.repeat([0,1],4), 'ix2':pd.concat([dtix,dtix]), 'data':np.arange(0,8) })
df

ix1 ix2 data
0   0   2019-01-01  0
1   0   2019-01-02  1
2   0   2019-01-03  2
3   0   2019-01-04  3
0   1   2019-01-01  4
1   1   2019-01-02  5
2   1   2019-01-03  6
3   1   2019-01-04  7

Now when I perform a grouped rolling mean on this data, I am getting an output like this:

df.groupby(['ix1','ix2']).agg({'data':'mean'}).rolling(2).mean()
        data
ix1 ix2 
0   2019-01-01  NaN
    2019-01-02  0.5
    2019-01-03  1.5
    2019-01-04  2.5
1   2019-01-01  3.5
    2019-01-02  4.5
    2019-01-03  5.5
    2019-01-04  6.5

Desired Output: Whereas, what I would actually like to have is this:


sma
ix1 ix2 
0   2019-01-01  NaN
    2019-01-02  0.5
    2019-01-03  1.5
    2019-01-04  2.5
1   2019-01-01  NaN
    2019-01-02  4.5
    2019-01-03  5.5
    2019-01-04  6.5

Will appreciate your help with this.

1 Answers

Use another groupby by firast level (ix1) with rolling:

df1 = (df.groupby(['ix1','ix2'])
         .agg({'data':'mean'})
         .groupby(level=0, group_keys=False)
         .rolling(2)
         .mean())
print (df1)
                data
ix1 ix2             
0   2019-01-01   NaN
    2019-01-02   0.5
    2019-01-03   1.5
    2019-01-04   2.5
1   2019-01-01   NaN
    2019-01-02   4.5
    2019-01-03   5.5
    2019-01-04   6.5

In your solution affter aggregation is returned one column DataFrame, so chained rolling working with all rows, not per groups like need:

print(df.groupby(['ix1','ix2']).agg({'data':'mean'}))
                data
ix1 ix2             
0   2019-01-01     0
    2019-01-02     1
    2019-01-03     2
    2019-01-04     3
1   2019-01-01     4
    2019-01-02     5
    2019-01-03     6
    2019-01-04     7
Related