У меня есть объекты панды series.groupby, назовите их data. Если я распечатаю элементы, это будет выглядеть так:
<pandas.core.groupby.generic.SeriesGroupBy object at ***>
(1, 0 397.44
1 12.72
2 422.40
Name: value, dtype: float64)
(2, 3 398.88
4 6.48
5 413.52
Name: value, dtype: float64)
(3, 6 398.40
7 68.40
8 18.96
9 56.64
10 406.56
Name: value, dtype: float64)
(4, 11 398.64
12 14.64
13 413.76
Name: value, dtype: float64)
...
Я хочу создать эквивалентный объект, записи которого представляют собой совокупную сумму каждого подсписка в серии за вычетом первой записи этого списка. Так, например, первый элемент будет выглядеть так:
(1, 0 0 #(= 397.44 - 397.44)
1 12.72 #(= 397.44 + 12.72 - 397.44)
2 435.12 #(= 397.44 + 12.72 + 422.40 - 397.44)
Я могу легко получить совокупную сумму, используя apply:
cumulative_sums = data.apply(lambda x: x.cumsum())
но когда я пытаюсь вычесть первый элемент списка интуитивно понятным способом (lambda x: x.cumsum()-x[0]), я получаю KeyError. Как я могу достичь того, что пытаюсь сделать?






Пытаться:
cumulative_sums = data.apply(lambda x: x.cumsum() - x.iat[0])
print(cumulative_sums)
Распечатки:
a b
1 0 0.00
1 12.72
2 435.12
2 3 0.00
4 6.48
5 420.00
3 6 0.00
7 68.40
8 87.36
9 144.00
10 550.56
Name: value, dtype: float64
Лучше всего избегать apply (это цикл) и использовать cumsum / преобразование, оптимизированное для этой конкретной задачи:
cumulative_sums = data.cumsum()-data.transform('first')
Выход:
0 0.00
1 12.72
2 435.12
3 0.00
4 6.48
5 420.00
6 0.00
7 68.40
8 87.36
9 144.00
10 550.56
11 0.00
12 14.64
13 428.40
Name: value, dtype: float64
Прирост в скорости весьма заметен:
Обратите внимание: если значения в исходном наборе данных отсортированы по группам, вы даже можете избежать groupby. Предполагая, что df введено с group/value в виде столбцов:
cs = df['value'].cumsum()
cumulative_sums = cs-cs.mask(df['group'].duplicated()).ffill()
Вариант с двумя сериями:
cs = series.cumsum()
cumulative_sums = cs-cs.mask(group.duplicated()).ffill()
Что еще быстрее:
Пример ввода для альтернативы:
series = pd.Series([1, 2, 3, 10, 2, 30, 7, 1, 2, 3])
group = pd.Series([0,0,0,1,1,1,1,2,2,2])
df = pd.DataFrame({'group': group, 'value': series})
Впечатляющее ускорение! Для меня это разовая оптимизация не так важна, но это отличный ответ для тех, кто пытается сделать что-то подобное, и я буду иметь это в виду для будущих связанных задач.
Красиво спасибо.