Я хотел бы добавить столбец совокупной суммы в мой фрейм данных Pandas, чтобы:
name | day | no
-----|-----------|----
Jack | Monday | 10
Jack | Tuesday | 20
Jack | Tuesday | 10
Jack | Wednesday | 50
Jill | Monday | 40
Jill | Wednesday | 110
становится:
Jack | Monday | 10 | 10
Jack | Tuesday | 30 | 40
Jack | Wednesday | 50 | 90
Jill | Monday | 40 | 40
Jill | Wednesday | 110 | 150
Я пробовал различные комбо df.groupby
и df.agg(lambda x: cumsum(x))
безрезультатно.
Ответы:
Это должно сработать, нужно
groupby()
дважды:df.groupby(['name', 'day']).sum() \ .groupby(level=0).cumsum().reset_index()
Пояснение:
print(df) name day no 0 Jack Monday 10 1 Jack Tuesday 20 2 Jack Tuesday 10 3 Jack Wednesday 50 4 Jill Monday 40 5 Jill Wednesday 110 # sum per name/day print( df.groupby(['name', 'day']).sum() ) no name day Jack Monday 10 Tuesday 30 Wednesday 50 Jill Monday 40 Wednesday 110 # cumulative sum per name/day print( df.groupby(['name', 'day']).sum() \ .groupby(level=0).cumsum() ) no name day Jack Monday 10 Tuesday 40 Wednesday 90 Jill Monday 40 Wednesday 150
Dataframe в результате первой суммы индексируется
'name'
и'day'
. Вы можете увидеть это, распечатавdf.groupby(['name', 'day']).sum().index
При вычислении кумулятивной суммы вы хотите сделать это по
'name'
, соответствующей первому индексу (уровень 0).Наконец, используйте,
reset_index
чтобы имена повторялись.df.groupby(['name', 'day']).sum().groupby(level=0).cumsum().reset_index() name day no 0 Jack Monday 10 1 Jack Tuesday 40 2 Jack Wednesday 90 3 Jill Monday 40 4 Jill Wednesday 150
источник
name
andday
asmultiIndex
, что имеет больший смысл (reset_index()
чтобы получитьint
индекс, если хотите ). 2)level=[0]
средствоgroupby
должно работать на 1-м уровнеMultiIndex
, а именно на колонкеname
.groupby()
умолчанию используется сортировка ключей, поэтому, если вы добавите строку «Джек-Четверг» внизу входного набора данных, вы получите неожиданные результаты. И поскольку яgroupby()
могу работать с названиями уровней, я нахожу ихdf.groupby(['name', 'day'], sort=False).sum().groupby(by='name').cumsum().reset_index()
менее загадочными.Это работает в пандах 0.16.2
In[23]: print df name day no 0 Jack Monday 10 1 Jack Tuesday 20 2 Jack Tuesday 10 3 Jack Wednesday 50 4 Jill Monday 40 5 Jill Wednesday 110 In[24]: df['no_cumulative'] = df.groupby(['name'])['no'].apply(lambda x: x.cumsum()) In[25]: print df name day no no_cumulative 0 Jack Monday 10 10 1 Jack Tuesday 20 30 2 Jack Tuesday 10 40 3 Jack Wednesday 50 90 4 Jill Monday 40 40 5 Jill Wednesday 110 150
источник
name
иday
до вычисления кумулятивной суммыname
(примечание: в результате есть 2 строки для Джек + вторник). Это то, что делает его проще, чем ответ CT Zhu .Модификация к ответу @Dmitry. Это проще и работает в pandas 0.19.0:
print(df) name day no 0 Jack Monday 10 1 Jack Tuesday 20 2 Jack Tuesday 10 3 Jack Wednesday 50 4 Jill Monday 40 5 Jill Wednesday 110 df['no_csum'] = df.groupby(['name'])['no'].cumsum() print(df) name day no no_csum 0 Jack Monday 10 10 1 Jack Tuesday 20 30 2 Jack Tuesday 10 40 3 Jack Wednesday 50 90 4 Jill Monday 40 40 5 Jill Wednesday 110 150
источник
ты должен использовать
df['cum_no'] = df.no.cumsum()
http://pandas.pydata.org/pandas-docs/version/0.19.2/generated/pandas.DataFrame.cumsum.html
Другой способ сделать это
import pandas as pd df = pd.DataFrame({'C1' : ['a','a','a','b','b'], 'C2' : [1,2,3,4,5]}) df['cumsum'] = df.groupby(by=['C1'])['C2'].transform(lambda x: x.cumsum()) df
источник
90
как сумма всех значений Джека, +40
, значение для Джилл-Понедельник).Вместо
df.groupby(by=['name','day']).sum().groupby(level=[0]).cumsum()
(см. Выше) вы также можете сделатьdf.set_index(['name', 'day']).groupby(level=0, as_index=False).cumsum()
df.groupby(by=['name','day']).sum()
фактически просто перемещает оба столбца в MultiIndexas_index=False
означает, что вам не нужно впоследствии вызывать reset_indexисточник
groupby().sum()
это не просто перемещение обоих столбцов в MultiIndex - он также суммирует два значения для Jack + Tuesday. Иas_index=False
, похоже, не имеет никакого эффекта в этом случае, поскольку индекс уже был установлен доgroupby
. А такgroupby().cumsum()
как имя / день извлекается из столбцов фрейма данных, вам нужно либо добавить результирующий числовой столбец в исходный фрейм данных (как предложили vjayky и Дмитрий), либо переместить имя / день в индекс, а затем reset_index.data.csv:
name,day,no Jack,Monday,10 Jack,Tuesday,20 Jack,Tuesday,10 Jack,Wednesday,50 Jill,Monday,40 Jill,Wednesday,110
Код:
import numpy as np import pandas as pd df = pd.read_csv('data.csv') print(df) df = df.groupby(['name', 'day'])['no'].sum().reset_index() print(df) df['cumsum'] = df.groupby(['name'])['no'].apply(lambda x: x.cumsum()) print(df)
Выход:
name day no 0 Jack Monday 10 1 Jack Tuesday 20 2 Jack Tuesday 10 3 Jack Wednesday 50 4 Jill Monday 40 5 Jill Wednesday 110 name day no 0 Jack Monday 10 1 Jack Tuesday 30 2 Jack Wednesday 50 3 Jill Monday 40 4 Jill Wednesday 110 name day no cumsum 0 Jack Monday 10 10 1 Jack Tuesday 30 40 2 Jack Wednesday 50 90 3 Jill Monday 40 40 4 Jill Wednesday 110 150
источник