Pandas cumsum () группирует выходные данные, отличные от sum () группирует выходные данные

#python #pandas #pandas-groupby

#python #pandas #pandas-groupby

Вопрос:

Я получаю неожиданное поведение при использовании cumsum() в сочетании с groupby.

Предполагая следующие данные (ежечасно, разные знаки, растягивающиеся на несколько лет):

 import pandas as pd
import numpy as np
start = pd.Timestamp('20191201', tz='Europe/Rome')
end = pd.Timestamp('20200331', tz='Europe/Rome')
index = pd.date_range(start,end,freq='H')
data = np.empty((len(index),))
data[::2] = 3
data[1::2] = -1
df = pd.DataFrame(data, index)
df
  

Вот как это будет выглядеть для целей тестирования:

 2019-12-01 00:00:00 01:00   3.00
2019-12-01 01:00:00 01:00   -1.00
2019-12-01 02:00:00 01:00   3.00
2019-12-01 03:00:00 01:00   -1.00
2019-12-01 04:00:00 01:00   3.00
... ...
2020-03-30 20:00:00 02:00   -1.00
2020-03-30 21:00:00 02:00   3.00
2020-03-30 22:00:00 02:00   -1.00
2020-03-30 23:00:00 02:00   3.00
2020-03-31 00:00:00 02:00   -1.00
  

Теперь обратите внимание на странную разницу между sum() и cumsum() в сочетании с group by month:

sum() —> 3 элемента, т.Е. по одному в месяц

 df.groupby(pd.Grouper(freq = 'M')).sum()
2019-12-31 00:00:00 01:00   744.00
2020-01-31 00:00:00 01:00   744.00
2020-02-29 00:00:00 01:00   696.00
2020-03-31 00:00:00 02:00   720.00
  

cumsum() —> 1489 элементов, т.Е. по одному в час

 df.groupby(pd.Grouper(freq = 'M')).cumsum()
2019-12-01 00:00:00 01:00   3.00
2019-12-01 01:00:00 01:00   2.00
2019-12-01 02:00:00 01:00   5.00
2019-12-01 03:00:00 01:00   4.00
2019-12-01 04:00:00 01:00   7.00
... ...
2020-03-30 20:00:00 02:00   716.00
2020-03-30 21:00:00 02:00   719.00
2020-03-30 22:00:00 02:00   718.00
2020-03-30 23:00:00 02:00   721.00
2020-03-31 00:00:00 02:00   720.00
  

Я вижу, что есть причина, по которой вам нужен последний вывод, но разве это не противоречиво?

Рассмотрим случай, когда пользователь хотел бы иметь накопленную ежемесячную сумму, сбрасываемую между годами. Какой код следует использовать?

Ответ №1:

Один из возможных способов сделать это:

 df.groupby(pd.Grouper(freq = 'Y')).cumsum().groupby(pd.Grouper(freq = 'M')).last()
  

Существуют ли другие / лучшие способы?