Я хочу создать функции запаздывания для фрейма данных, который принимает запаздывания, столбцы, сгруппированные по группам и функции для применения в качестве аргумента и выдает соответствующую статистику. Например, если переданы следующие аргументы - lag = [2], funcs = [np.sum], cols = ['clicks'], то результатом должна быть сумма кликов за последние два дня (исключая сегодня) на группу в день.
import pandas as pd
import numpy as np
df =
pd.DataFrame(
{
"date": pd.date_range("2018-01-01", periods=12, freq="D"),
"group": ["first", "second"] * 6,
"clicks": range(12)
}
).sample(
frac=1
).set_index('date') # random shuffle
lags = [2]
funcs = [np.sum ,np.mean]
cols = ["clicks"]
for lag in lags:
agg_df = df.groupby('group').rolling(f'{lag}D', closed='left').agg(funcs)[cols]
Actual Output:
agg_df.reset_index()
group date clicks
sum mean
0 first 2018-01-01 NaN NaN
1 first 2018-01-03 0.0 0.0
2 first 2018-01-05 2.0 2.0
3 first 2018-01-07 4.0 4.0
4 first 2018-01-09 6.0 6.0
5 first 2018-01-11 8.0 8.0
6 second 2018-01-02 NaN NaN
7 second 2018-01-04 1.0 1.0
8 second 2018-01-06 3.0 3.0
9 second 2018-01-08 5.0 5.0
10 second 2018-01-10 7.0 7.0
11 second 2018-01-12 9.0 9.0
Expected Output:
group date clicks
sum mean
0 first 2018-01-01 NaN NaN
1 first 2018-01-03 0.0 0.0
2 first 2018-01-05 2.0 1.0
3 first 2018-01-07 4.0 2.0
4 first 2018-01-09 6.0 3.0
5 first 2018-01-11 8.0 4.0
6 second 2018-01-02 NaN NaN
7 second 2018-01-04 1.0 0.5
8 second 2018-01-06 3.0 1.5
9 second 2018-01-08 5.0 2.5
10 second 2018-01-10 7.0 3.5
11 second 2018-01-12 9.0 4.5
Кажется, что для среднего значения функция не берет пропущенные дни.
Я пришел со следующим решением, которое использует resample для заполнения пропущенные дни -
agg_df = df_test_time.groupby('group').resample('D').sum().reset_index().set_index('date').groupby('group',group_keys=False, as_index=False).rolling(f'{lag}D', closed='left').agg([np.sum, np.mean])[cols]
На рисунке показана разница между временем обработки в секундах (ось Y) для различного количества уникальных групп (ось X) для каждого метода. Второй метод (повторная выборка) работает, но с точки зрения эффективности он требует огромных затрат. Есть ли лучший способ масштабировать его? Изображение, показывающее разницу в производительности: