Как рассчитать скользящий максимум с начала календарной недели и месяца?

Скользящий максимум за 3 дня, все считает отлично:

df['Sales'].rolling('3D').max()

Скользящий максимум с начала календарной недели:

df['Sales'].rolling('W').max()

Получаю ошибку:

ValueError: <Week: weekday=6> is a non-fixed frequency

С месяцем - аналогично.

Датасет

Upd '7D' и '30D' не подходят, т.к считают не с начала календарной недели и месяца.

Вариант медленного решения:

%timeit [df.loc[edt - pd.tseries.offsets.DateOffset(months=1):edt, 'Sales'].max() for edt in df.index]

397 ms ± 16.5 ms

Ищу решение, которое позволит делать эти операции быстро, датасеты тяжелые.


Ответы (1 шт):

Автор решения: D.Vinogradov

Попробуйте так, вроде быстрее, предложенный не проверял, но этот отрабатывает примерно за 30-40 мс

df = pd.read_csv('/*/Sales.csv', sep=';').rename(columns={'Unnamed: 0': 'Date'})
df['Date'] = pd.to_datetime(df['Date'])

Сделайте столбцы с годом и неделей:

df['year'] = df['Date'].dt.isocalendar().year
df['WeekN'] = df['Date'].dt.isocalendar().week

Дальше группируем, скидываем индекс и из листов с датами делаем столбец. В конце можно скинуть индекс.

>>> df.groupby(['year', 'WeekN']).agg(Date=('Date', lambda x: x), max_of=('Sales', 'max')).reset_index(
    drop=True).explode('Date'))

        Date  max_of
0 2018-11-08  791958
0 2018-11-09  791958
1 2018-11-12  763447
1 2018-11-13  763447
1 2018-11-14  763447
1 2018-11-15  763447
1 2018-11-16  763447
2 2018-11-19  731052
2 2018-11-20  731052
2 2018-11-21  731052
2 2018-11-22  731052
2 2018-11-23  731052
3 2018-11-26  703182
3 2018-11-27  703182
→ Ссылка