Pandas group-by y sum

207

Estoy usando este marco de datos:

Fruit   Date      Name  Number
Apples  10/6/2016 Bob    7
Apples  10/6/2016 Bob    8
Apples  10/6/2016 Mike   9
Apples  10/7/2016 Steve 10
Apples  10/7/2016 Bob    1
Oranges 10/7/2016 Bob    2
Oranges 10/6/2016 Tom   15
Oranges 10/6/2016 Mike  57
Oranges 10/6/2016 Bob   65
Oranges 10/7/2016 Tony   1
Grapes  10/7/2016 Bob    1
Grapes  10/7/2016 Tom   87
Grapes  10/7/2016 Bob   22
Grapes  10/7/2016 Bob   12
Grapes  10/7/2016 Tony  15

Quiero agregar esto por nombre y luego por fruta para obtener un número total de frutas por nombre.

Bob,Apples,16 ( for example )

Intenté agrupar por nombre y fruta, pero ¿cómo obtengo la cantidad total de fruta?

Tratando duro
fuente

Respuestas:

211

Uso GroupBy.sum:

df.groupby(['Fruit','Name']).sum()

Out[31]: 
               Number
Fruit   Name         
Apples  Bob        16
        Mike        9
        Steve      10
Grapes  Bob        35
        Tom        87
        Tony       15
Oranges Bob        67
        Mike       57
        Tom        15
        Tony        1
Steven G
fuente
95
¿Cómo pueden saber los pandas que quiero sumar el nombre de la columna Number?
Kingname
12
@Kingname es la última columna que queda si eliminas NAME y FRUIT. si agrega 2 columnas restantes, sumaría ambas columnas
Steven G
9
¿Cómo especificar qué columna sumar?
tgdn
36
@tgdn df.groupby (['Nombre', 'Fruta']) ['Número']. sum ()
Steven G
2
@StevenG Para la respuesta proporcionada para resumir una columna específica, el resultado sale como una serie Pandas en lugar de Dataframe. Del comentario de Jakub Kukul (en la respuesta a continuación), podemos usar corchetes dobles alrededor de 'Número' para obtener un Marco de datos.
skdhfgeq2134
179

También puedes usar la función agg,

df.groupby(['Name', 'Fruit'])['Number'].agg('sum')
Saurabh
fuente
1
Esto difiere de la respuesta aceptada en que esto devuelve un Seriesmientras que el otro devuelve un GroupByobjeto.
Gaurang Tandon
11
@GaurangTandon para obtener el DataFrameobjeto en su lugar (como en la respuesta aceptada), use corchetes dobles 'Number', es decir:df.groupby(['Name', 'Fruit'])[['Number']].agg('sum')
Jakub Kukul
1
Muy útil para limpiar informes de consultas mal codificados.
avirr
93

Si desea mantener las columnas originales Fruity Name, use reset_index(). De lo contrario Fruit, y Namepasarán a formar parte del índice.

df.groupby(['Fruit','Name'])['Number'].sum().reset_index()

Fruit   Name       Number
Apples  Bob        16
Apples  Mike        9
Apples  Steve      10
Grapes  Bob        35
Grapes  Tom        87
Grapes  Tony       15
Oranges Bob        67
Oranges Mike       57
Oranges Tom        15
Oranges Tony        1

Como se ve en las otras respuestas:

df.groupby(['Fruit','Name'])['Number'].sum()

               Number
Fruit   Name         
Apples  Bob        16
        Mike        9
        Steve      10
Grapes  Bob        35
        Tom        87
        Tony       15
Oranges Bob        67
        Mike       57
        Tom        15
        Tony        1
Gazala Muhamed
fuente
43

Las otras dos respuestas logran lo que quieres.

Puede usar la pivotfuncionalidad para organizar los datos en una buena tabla

df.groupby(['Fruit','Name'],as_index = False).sum().pivot('Fruit','Name').fillna(0)



Name    Bob     Mike    Steve   Tom    Tony
Fruit                   
Apples  16.0    9.0     10.0    0.0     0.0
Grapes  35.0    0.0     0.0     87.0    15.0
Oranges 67.0    57.0    0.0     15.0    1.0
Demetri Pananos
fuente
19
df.groupby(['Fruit','Name'])['Number'].sum()

Puede seleccionar diferentes columnas para sumar números.

Jared
fuente
7

Puede configurar la groupbycolumna para index luego usar sumconlevel

df.set_index(['Fruit','Name']).sum(level=[0,1])
Out[175]: 
               Number
Fruit   Name         
Apples  Bob        16
        Mike        9
        Steve      10
Oranges Bob        67
        Tom        15
        Mike       57
        Tony        1
Grapes  Bob        35
        Tom        87
        Tony       15
YOBEN_S
fuente
3

Una variación de la función .agg (); proporciona la capacidad de (1) persistir el DataFrame tipo, (2) aplicar promedios, recuentos, sumas, etc. y (3) habilita groupby en varias columnas mientras mantiene la legibilidad.

df.groupby(['att1', 'att2']).agg({'att1': "count", 'att3': "sum",'att4': 'mean'})

usando tus valores ...

df.groupby(['Name', 'Fruit']).agg({'Number': "sum"})
xxyjoel
fuente