Python pandas - Эффективно применять функцию для скользящего окна по группе с пропущенными датами - PullRequest
0 голосов
/ 19 марта 2020

Примечание: Я уже знаю ответ на этот вопрос, я публикую его только потому, что не смог найти правильный ответ о переполнении стека, и мне потребовалось удивительное количество времени, чтобы его выяснить. При этом, не стесняйтесь предлагать другие варианты.

Вопрос

У меня есть pandas DataFrame с тремя столбцами, один отслеживает дату, один отслеживает связанные наблюдения (т. е. мой столбец группировки), а третья переменная хранит некоторые числовые значения c. Для каждой группы в моем фрейме данных я хотел бы рассчитать скользящую сумму по столбцу даты. Предостережение: в фрейме данных отсутствуют некоторые даты, я хотел бы рассматривать их как наблюдения со значением 0. Я не хочу использовать перекрестное соединение для добавления всех дат.

Воспроизводимый пример

Давайте создадим такой кадр данных:

df = pd.DataFrame({'id_col' : np.array([1,1,1,1,1,1,2,2,2,2,2,3,3,3]),
                  'value_col' : np.random.randint(0,5,size=14),
                  'dates' : pd.to_datetime(np.array([
                  '2018-01-01',
                  '2018-02-01',
                  '2018-03-01',
                  '2018-05-01',
                  '2018-06-01',
                  '2018-09-01',
                  '2018-01-01',
                  '2018-02-01',
                  '2018-05-01',
                  '2018-06-01',
                  '2018-07-01',
                  '2018-01-01',
                  '2018-02-01',
                  '2018-03-01'])
                  )}
                 )

Данные выглядят примерно так:

    id_col  value_col   dates
0   1   0   2018-01-01
1   1   1   2018-02-01
2   1   4   2018-03-01
3   1   0   2018-05-01
4   1   3   2018-06-01
5   1   3   2018-09-01
6   2   4   2018-01-01
7   2   3   2018-02-01
8   2   2   2018-05-01
9   2   0   2018-06-01
10  2   2   2018-07-01
11  3   4   2018-01-01
12  3   2   2018-02-01
13  3   3   2018-03-01

Подходы, которые я пробовал и не работают:

Опция 1: полностью игнорирует пропущенные даты

df.groupby(['id_col']).rolling(2)['value_col'].sum().reset_index()

Опция 2: На основе pandas скользящая документация , замените ширину окна, используя параметры смещения pandas (возвращает ValueError: window must be an integer). Этот подход сработал бы, если бы столбец дат использовался в качестве индекса кадра данных. К сожалению, мы не можем использовать простой индекс здесь, так как 2 разных идентификатора из id_col могут содержать одну и ту же дату. (Мы могли бы создать MultiIndex, но затем получить ту же ошибку значения).

df.groupby(['id_col']).rolling('60d')['value_col'].sum().reset_index()

Что работает, но не очень просто:

Опция 1: Крест присоединиться, чтобы заполнить все пропущенные даты (может быть сложно, если у вас много данных)

Вариант 2: Построить мультииндекс из декартового произведения итераций, как в этом ответе . На самом деле это очень похоже на приведенный выше вариант.

1 Ответ

0 голосов
/ 19 марта 2020

Используйте параметр on rolling. Документация на самом деле упоминает об этом, хотя нет примеров, чтобы увидеть соответствующее использование. К счастью, существует pandas github и эта проблема, которая, если вы go просматриваете комментарии, дает некоторое представление о том, как на самом деле правильно использовать функцию прокрутки со смещением windows.

Следовательно, решение будет таким:

df.groupby(['id_col']).rolling('60d', on = 'dates')['value_col'].sum().reset_index()

Обратите внимание на использование 60d в качестве прокси-сервера в течение 2 месяцев вместо 2m, потому что 2m выдаст вам следующую ошибку: ValueError: <2 * MonthEnds> is a non-fixed frequency. Чтобы узнать больше об этой проблеме, проверьте вопрос stackoverflow здесь .

...