Использование cumsum в pandas для группы()

От новичка Pandas: у меня есть данные, которые выглядят в основном так:

 data1=pd.DataFrame({'Dir':['E','E','W','W','E','W','W','E'], 'Bool':['Y','N','Y','N','Y','N','Y','N'], 'Data':[4,5,6,7,8,9,10,11]}, index=pd.DatetimeIndex(['12/30/2000','12/30/2000','12/30/2000','1/2/2001','1/3/2001','1/3/2001','12/30/2000','12/30/2000']))
data1
Out[1]: 
           Bool  Data Dir
2000-12-30    Y     4   E
2000-12-30    N     5   E
2000-12-30    Y     6   W
2001-01-02    N     7   W
2001-01-03    Y     8   E
2001-01-03    N     9   W
2000-12-30    Y    10   W
2000-12-30    N    11   E

И я хочу сгруппировать его несколькими уровнями, а затем сделать cumsum():

Например, как running_sum=data1.groupby(['Bool','Dir']).cumsum() <-( Не работает)

с выходом, который будет выглядеть примерно так:

Bool Dir Date        running_sum
N    E   2000-12-30           16
     W   2001-01-02            7
         2001-01-03           16
Y    E   2000-12-30            4
         2001-01-03           12
     W   2000-12-30           16

Мой "как" код явно даже не близок. Я предпринял ряд попыток и узнал много нового о том, как не делать этого.

Спасибо за любую помощь, которую вы можете дать.

Ответ 1

Попробуйте следующее:

data2 = data1.reset_index()
data3 = data2.set_index(["Bool", "Dir", "index"])   # index is the new column created by reset_index
running_sum = data3.groupby(level=[0,1,2]).sum().groupby(level=[0,1]).cumsum()

Причина, по которой вы не можете просто использовать cumsum на data3, связана с тем, как структурированы ваши данные. Группировка с помощью Bool и Dir и применение функции агрегации (sum, mean и т.д.) Приведет к созданию DataFrame меньшего размера, чем вы начали, поскольку любая используемая вами функция будет агрегировать значения на основе вашей группы ключи. Однако cumsum не является функцией аггрегации. Это вернет DataFrame, размер которого совпадает с тем, с которым он звонил. Поэтому, если ваш входной DataFrame не находится в формате, где вывод может быть того же размера после вызова cumsum, он выдает ошибку. Поэтому я сначала вызвал sum, который возвращает DataFrame в правильном формате ввода.

Извините, если я не объяснил это достаточно хорошо. Может быть, кто-то еще может мне помочь?

Ответ 2

Как указывает другой ответ, вы пытаетесь свернуть идентичные даты в отдельные строки, тогда как функция cumsum вернет серию той же длины, что и исходный DataFrame. Иными словами, вы действительно хотите группировать [Bool, Dir, Date], вычислять сумму в каждой группе, затем возвращать cumsum в строках, сгруппированных по [Bool, Dir]. Другой ответ - совершенно правильное решение вашего конкретного вопроса, здесь однострочный вариант:

data1.groupby(['Bool', 'Dir', 'Date']).sum().groupby(level=[0, 1]).cumsum()

Это возвращает результат точно в запрошенном формате.

Для тех, кто ищет простую cumsum в группе Pandas, вы можете использовать:

data1.groupby(['Bool', 'Dir']).apply(lambda x: x['Data'].cumsum())

Суммарная сумма рассчитывается внутри каждой группы. Вот как выглядит результат:

Bool  Dir            
N     E    2000-12-30     5
           2000-12-30    16
      W    2001-01-02     7
           2001-01-03    16
Y     E    2000-12-30     4
           2001-01-03    12
      W    2000-12-30     6
           2000-12-30    16
Name: Data, dtype: int64

Обратите внимание на повторяющиеся даты, но это делает строгую кумулятивную сумму, внутреннюю по отношению к строкам каждой группы, идентифицированной столбцами Bool и Dir.