python pandas aggregate pandas-groupby

python - Agregado de pandas con nombres de columna dinámicos



aggregate pandas-groupby (5)

Desafortunadamente, tendrá que aplicar ambas funciones de agregación por separado (eso o repetir "valn": "mean" tantas veces como columnas valx ). Groupby.agg puede tomar un diccionario pero las claves deben ser columnas individuales.

La forma en que haría esto es usar DataFrame.filter para seleccionar el subconjunto del marco de datos con las columnas siguiendo el formato de valx , agregar con la media y luego asignar nuevas columnas con los resultados agregados en las otras columnas:

(df.filter(regex=r''^val'').groupby(df.group).mean() .assign(color = df.group_color.groupby(df.group).first())) val1 val2 color group A 3.333333 4.666667 green B 4.500000 6.000000 blue

Tengo un script que genera un marco de datos de pandas con un número variable de columnas de valor. Como ejemplo, este df podría ser

import pandas as pd df = pd.DataFrame({ ''group'': [''A'', ''A'', ''A'', ''B'', ''B''], ''group_color'' : [''green'', ''green'', ''green'', ''blue'', ''blue''], ''val1'': [5, 2, 3, 4, 5], ''val2'' : [4, 2, 8, 5, 7] }) group group_color val1 val2 0 A green 5 4 1 A green 2 2 2 A green 3 8 3 B blue 4 5 4 B blue 5 7

Mi objetivo es obtener la media agrupada para cada una de las columnas de valor. En este caso específico (con 2 columnas de valor), puedo usar

df.groupby(''group'').agg({"group_color": "first", "val1": "mean", "val2": "mean"}) group_color val1 val2 group A green 3.333333 4.666667 B blue 4.500000 6.000000

pero eso no funciona cuando el marco de datos en cuestión tiene más columnas de valor (val3, val4, etc.). ¿Hay alguna manera de tomar dinámicamente la media de "todas las otras columnas" o "todas las columnas que contienen val en sus nombres"?


Más fácil como

df.groupby(''group'').agg(lambda x : x.head(1) if x.dtype==''object'' else x.mean()) Out[63]: group_color val1 val2 group A green 3.333333 4.666667 B blue 4.500000 6.000000


Por comentario de OP

Podemos agrupar por ''group'' y ''group_color'' sin el riesgo de que haya más de un único ''group_color'' por ''group''

Por consiguiente:

df.groupby([''group'', ''group_color'']).mean().reset_index(level=1) group_color val1 val2 group A green 3.333333 4.666667 B blue 4.500000 6.000000


Puedes ir con 2 diccionarios que puedes combinar así:

df.groupby(''group'').agg({**{''group_color'': ''first''}, **{c: ''mean'' for c in df.columns if c.startswith(''val'')}})

En este caso, tiene un dict con agregaciones fijas y otro con selección de columna dinámica.


Si su group_color es siempre el mismo dentro de un grupo, puede hacer:

df.pivot_table(index=[''group'',''group_color''],aggfunc=''mean'')

Salida:

val1 val2 group group_color A green 3.333333 4.666667 B blue 4.500000 6.000000

En el otro caso, puede construir el diccionario y pasarlo a agg :

agg_dict = {f: ''first'' if f==''group_color'' else ''mean'' for f in df.columns[1:]} df.groupby(''group'').agg(agg_dict)

Qué salida:

group_color val1 val2 group A green 3.333333 4.666667 B blue 4.500000 6.000000