¿Agrupar el marco de datos y obtener la suma Y el recuento?

82

Tengo un marco de datos que se parece a esto:

              Company Name              Organisation Name  Amount
10118  Vifor Pharma UK Ltd  Welsh Assoc for Gastro & Endo 2700.00
10119  Vifor Pharma UK Ltd    Welsh IBD Specialist Group,  169.00
10120  Vifor Pharma UK Ltd             West Midlands AHSN 1200.00
10121  Vifor Pharma UK Ltd           Whittington Hospital   63.00
10122  Vifor Pharma UK Ltd                 Ysbyty Gwynedd   75.93

¿Cómo sumo Amounty cuento Organisation Namepara obtener un nuevo marco de datos que se ve así?

              Company Name             Organisation Count   Amount
10118  Vifor Pharma UK Ltd                              5 11000.00

Sé sumar o contar:

df.groupby('Company Name').sum()
df.groupby('Company Name').count()

¡Pero no cómo hacer ambas cosas!

Ricardo
fuente

Respuestas:

147

prueba esto:

In [110]: (df.groupby('Company Name')
   .....:    .agg({'Organisation Name':'count', 'Amount': 'sum'})
   .....:    .reset_index()
   .....:    .rename(columns={'Organisation Name':'Organisation Count'})
   .....: )
Out[110]:
          Company Name   Amount  Organisation Count
0  Vifor Pharma UK Ltd  4207.93                   5

o si no desea restablecer el índice:

df.groupby('Company Name')['Amount'].agg(['sum','count'])

o

df.groupby('Company Name').agg({'Amount': ['sum','count']})

Manifestación:

In [98]: df.groupby('Company Name')['Amount'].agg(['sum','count'])
Out[98]:
                         sum  count
Company Name
Vifor Pharma UK Ltd  4207.93      5

In [99]: df.groupby('Company Name').agg({'Amount': ['sum','count']})
Out[99]:
                      Amount
                         sum count
Company Name
Vifor Pharma UK Ltd  4207.93     5
MaxU
fuente
2
@MaxU hay una manera de aplicar la suma y el recuento a diferentes pero múltiples coulmns. Cuando trato de dar las columnas como una lista como esta: agg ({['hotel_name', 'hotel_country']: 'cuenta', ['costo', 'ingresos', 'clics']: 'suma'}) da Error "TypeError: unhashable type: 'list'"
CanCeylan
@CanCeylan no sé si es posible hacerlo en una cláusula groupby, pero puede lograrlo agregando una columna de conteo ficticia al marco de datos de antemano y luego hacer una suma groupby:df['count'] = 1
Karl Anka
1
Finalmente, 2 horas de búsqueda de cómo hacer esto ... solo la tercera opción: df.groupby ('Nombre de la empresa'). Agg ({'Amount': ['sum', 'count']}) funcionó para mí .
charo
Hola, gracias por esa gran solución. En mi caso particular, estoy usando su solución en dos columnas diferentes para obtener la suma y contar el número de filas. Desafortunadamente, obtengo el número de filas dos veces (ofc. Porque cuenta para ambas columnas). ¿Hay alguna forma de eliminar uno de los .counts para que mi mesa se vea limpia? df.groupby(df['L2 Name'])[["Amount arrear","VSU"]].agg(['sum','count'])
MLAlex
Hola gracias por tu gran respuesta. ¿Sabes cómo interpretar las nuevas columnas que se crean y cómo aplanarlas de una forma más tradicional?
Solal
20

En caso de que se pregunte cómo cambiar el nombre de las columnas durante la agregación, aquí se explica cómo

pandas> = 0.25: Agregación con nombre

df.groupby('Company Name')['Amount'].agg(MySum='sum', MyCount='count')

O,

df.groupby('Company Name').agg(MySum=('Amount', 'sum'), MyCount=('Amount', 'count'))

                       MySum  MyCount
Company Name                       
Vifor Pharma UK Ltd  4207.93        5
cs95
fuente
Esta debería ser la respuesta exceptuada, ¿hay alguna manera de actualizar las preguntas / respuestas antiguas con la nueva forma mejor de hacer las cosas? La respuesta exceptuada no es incorrecta, simplemente ya no es la mejor manera.
JSharm
@JSharm obviamente no puede cambiar la opinión del OP, pero ciertamente puede votar las publicaciones que siente que merecen estar en la parte superior. Si suficientes personas piensan y actúan de la misma manera que usted, llegaremos allí algún día;) PD: no echar sombra a la respuesta aceptada, sigo pensando que es la mejor respuesta para esta pregunta siempre que los pandas continúen apoyando la sintaxis, que estoy razonablemente seguro de que será por un buen tiempo todavía.
cs95
4

Si tiene muchas columnas y solo una es diferente, puede hacer:

In[1]: grouper = df.groupby('Company Name')
In[2]: res = grouper.count()
In[3]: res['Amount'] = grouper.Amount.sum()
In[4]: res
Out[4]:
                      Organisation Name   Amount
Company Name                                   
Vifor Pharma UK Ltd                  5  4207.93

Tenga en cuenta que puede cambiar el nombre de la columna Nombre de la organización como desee.

JSharm
fuente
1
df.groupby('Company Name').agg({'Organisation name':'count','Amount':'sum'})\
    .apply(lambda x: x.sort_values(['count','sum'], ascending=False))
cvsnow
fuente