Создание масштабируемой функции задержки окна в python - PullRequest
0 голосов
/ 27 февраля 2020

Я хочу создать функции запаздывания для фрейма данных, который принимает запаздывания, столбцы, сгруппированные по группам и функции для применения в качестве аргумента и выдает соответствующую статистику. Например, если переданы следующие аргументы - 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) для каждого метода. Второй метод (повторная выборка) работает, но с точки зрения эффективности он требует огромных затрат. Есть ли лучший способ масштабировать его? Изображение, показывающее разницу в производительности:

enter image description here

...