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