Pandas:在日期时间上执行 Groupby Rolling 时不保留索引

我有一个数据框,其中一些日期相同。作为问题的说明,我创建了一个日期相同的示例 df。


df = pd.DataFrame({"column1": range(6), 

                   "column2": range(6), 

                   'group': 3*['A','B'], 

                   'date':pd.date_range("20190101", periods=6)})

df.loc[:,'date']=df.loc[0,'date']


df

# Output of DF

   column1  column2 group       date

0        0        0     A 2019-01-01

1        1        1     B 2019-01-01

2        2        2     A 2019-01-01

3        3        3     B 2019-01-01

4        4        4     A 2019-01-01

5        5        5     B 2019-01-01

对 datetime 列执行 groupby 滚动操作时出现问题:索引未保留。当日期相同时,这是一个问题,因为无法合并回原始数据框(这是我的目标)。


df.groupby('group').rolling('2D',on='date')['column1'].sum()


# Output of Groupby Rolling

group  date      

A      2019-01-01    0.0

       2019-01-01    2.0

       2019-01-01    6.0

B      2019-01-01    1.0

       2019-01-01    4.0

       2019-01-01    9.0

Name: column1, dtype: float64

我有一个可行的替代解决方案,但速度要慢得多。


df.groupby('group').apply(lambda x: x.rolling('2D',on='date')['column1'].sum())


# Output of Groupby Apply Rolling 

group   

A      0    0.0

       2    2.0

       4    6.0

B      1    1.0

       3    4.0

       5    9.0

Name: column1, dtype: float64

希望有比上述更有效的东西。


撒科打诨
浏览 133回答 2
2回答

莫回无

对于那些感兴趣的人,我创建了一个更复杂的示例 df 来测试上面提出的每个解决方案的效率。我原来的方法(这里最慢,但如果组很少则效率高):%%timeitdf = pd.DataFrame({"column1": range(600),                    "column2": range(600),                    "column3": range(600),                   "column4": range(600),                   "column5": range(600),                   "column6": range(600),                   "column7": range(600),                   "column8": range(600),                   'group': 5*['l'+str(i) for i in range(120)],                    'date':pd.date_range("20190101", periods=600)})### Set the date the samedf.loc[:,'date']=df.loc[0,'date']cols = ['column1','column2','column3','column4','column5','column6','column7','column8']newcols = ['col1','col2','col3','col4','col5','col6','col7','col8']if newcols[0] not in df.columns:    df = df.reindex(columns=df.columns.tolist()+newcols)df[newcols]=df.groupby('group').apply(lambda x: x.rolling('2D',on='date')[cols].sum()                                     ).sort_index(level=1).drop('date',axis=1).values# timeit output345 ms ± 28 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)大卫埃里克森的解决方案。如果有很多组且每个组中的观察值很少,那么它是有效的。%%timeitdf = pd.DataFrame({"column1": range(600),                    "column2": range(600),                    "column3": range(600),                   "column4": range(600),                   "column5": range(600),                   "column6": range(600),                   "column7": range(600),                   "column8": range(600),                   'group': 5*['l'+str(i) for i in range(120)],                    'date':pd.date_range("20190101", periods=600)})### Set the date the samedf.loc[:,'date']=df.loc[0,'date']cols = ['column1','column2','column3','column4','column5','column6','column7','column8']newcols = ['col1','col2','col3','col4','col5','col6','col7','col8']if newcols[0] not in df.columns:    df = df.reindex(columns=df.columns.tolist()+newcols)my_dict = {}my_dict["index"] = "max"my_dict.update(dict.fromkeys(cols, "sum"))df[newcols]=df.reset_index().groupby('group').rolling('2D',on='date').agg(my_dict).sort_values('index').drop('index',axis=1).values# timeit output110 ms ± 11.5 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)RichieV 提出的最快的解决方案:%%timeitdf = pd.DataFrame({"column1": range(600),                    "column2": range(600),                    "column3": range(600),                   "column4": range(600),                   "column5": range(600),                   "column6": range(600),                   "column7": range(600),                   "column8": range(600),                   'group': 5*['l'+str(i) for i in range(120)],                    'date':pd.date_range("20190101", periods=600)})### Set the date the samedf.loc[:,'date']=df.loc[0,'date']cols = ['column1','column2','column3','column4','column5','column6','column7','column8']newcols = ['col1','col2','col3','col4','col5','col6','col7','col8']if newcols[0] not in df.columns:    df = df.reindex(columns=df.columns.tolist()+newcols)    df=df.sort_values(['group','date'],kind='mergesort').reset_index(drop=True)df[newcols]=df.groupby('group').rolling('2D',on='date')[cols].sum().valuesdf=df.sort_values('column1',kind='mergesort').reset_index(drop=True)# timeit output40 ms ± 6.41 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

青春有我

您可以使用.reset_index()该列,然后将该index列作为其余列的结果与.groupby和 一起使用.agg。我想这会比 lambda x 快得多。df = pd.DataFrame({"column1": range(6),                "column2": range(6),                'group': 3*['A','B'],                'date':pd.date_range("20190101", periods=6)})df = df.reset_index().groupby('group').rolling('5D',on='date').agg({'index' : 'max', 'column1' : 'sum'}))df                   index    column1group   date        A       2019-01-01  0.0     0.0        2019-01-03  2.0     2.0        2019-01-05  4.0     6.0B       2019-01-02  1.0     1.0        2019-01-04  3.0     4.0        2019-01-06  5.0     9.0从那里,如果你想要没有日期的最终输出格式,你可以这样做:df = df.reset_index().groupby(['group','index'])['column1'].sum()group  indexA      0.0      0.0       2.0      2.0       4.0      6.0B      1.0      1.0       3.0      4.0       5.0      9.0
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python