Для тех, кто заинтересован, я создал более сложный образец df для проверки эффективности каждого из предложенных выше решений.
Мой оригинальный подход (здесь самый медленный, но эффективный, если групп очень мало):
%%timeit
df = 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 same
df.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 output
345 ms ± 28 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
Решение Дэвида Эриксона. Это эффективно, если в каждой группе много групп с небольшим количеством наблюдений.
%%timeit
df = 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 same
df.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 output
110 ms ± 11.5 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
Решение, предложенное RichieV, которое здесь самое быстрое:
%%timeit
df = 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 same
df.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().values
df=df.sort_values('column1',kind='mergesort').reset_index(drop=True)
# timeit output
40 ms ± 6.41 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)