Pandas: agrupar por y diferencia de tabla dinámica

4 minutos de lectura

avatar de usuario
usuario4943236

Acabo de empezar a aprender Pandas y me preguntaba si hay alguna diferencia entre groupby() y pivot_table() funciones ¿Alguien puede ayudarme a entender la diferencia entre ellos?

avatar de usuario
David Maust

Ambas cosas pivot_table y groupby se utilizan para agregar su marco de datos. La diferencia es sólo con respecto a la forma del resultado.

Usando pd.pivot_table(df, index=["a"], columns=["b"], values=["c"], aggfunc=np.sum) se crea una tabla donde a está en el eje de la fila, b está en el eje de la columna, y los valores son la suma de c.

Ejemplo:

df = pd.DataFrame({"a": [1,2,3,1,2,3], "b":[1,1,1,2,2,2], "c":np.random.rand(6)})
pd.pivot_table(df, index=["a"], columns=["b"], values=["c"], aggfunc=np.sum)

b         1         2
a                    
1  0.528470  0.484766
2  0.187277  0.144326
3  0.866832  0.650100

Usando groupbylas dimensiones proporcionadas se colocan en columnas y se crean filas para cada combinación de esas dimensiones.

En este ejemplo, creamos una serie de la suma de valores cagrupados por todas las combinaciones únicas de a y b.

df.groupby(['a','b'])['c'].sum()

a  b
1  1    0.528470
   2    0.484766
2  1    0.187277
   2    0.144326
3  1    0.866832
   2    0.650100
Name: c, dtype: float64

Un uso similar de groupby es si omitimos el ['c']. En este caso, crea un marco de datos (no una serie) de las sumas de todas las columnas restantes agrupadas por valores únicos de a y b.

print df.groupby(["a","b"]).sum()
            c
a b          
1 1  0.528470
  2  0.484766
2 1  0.187277
  2  0.144326
3 1  0.866832
  2  0.650100

  • Gracias por su respuesta. Tengo una duda con respecto a lo que publicaste. Cómo df.groupby(["a","b"])["c"].sum() es diferente de df.groupby(["a","b"]["c"]).sum()

    – usuario4943236

    10 de enero de 2016 a las 7:06

  • La línea que publicaste no es sintácticamente correcta, pero creo que quieres decir df.groupby(["a","b","c"]).sum(). Esto agrupará por las combinaciones únicas de a, b y c, y sumará las columnas restantes (que en los ejemplos anteriores no están presentes).

    – David Maust

    10 de enero de 2016 a las 7:09

  • Si mueves “b” de columns a indexes decir pd.pivot_table(df, index=["a", "b"], values=["c"], aggfunc=np.sum)la salida es la misma que desde df.groupby(["a", "b"]).sum().

    – HenriV

    4 de mayo de 2018 a las 10:11

  • Para mí, esto parece dos enfoques para llegar al mismo resultado. los pivot_table salida es lo que obtendríamos si llamamos unstack en el resumido groupby salida, ¿verdad?

    – timgeb

    6 de agosto de 2018 a las 13:04

avatar de usuario
kiramichel

Es más apropiado usar .pivot_table() en vez de .groupby() cuando necesite mostrar agregados con etiquetas de filas y columnas.

.pivot_table() facilita la creación de etiquetas de fila y columna al mismo tiempo y es preferible, aunque puede obtener resultados similares utilizando .groupby() con unos pocos pasos adicionales.

  • es un punto de vista, podemos decir que groupby es una forma de verificar el paso de multiindex y la tabla dinámica simplemente ocultarlo. Creo que es mejor entender el mecanismo groupby y unstack que solo la tabla dinámica y su lista de argumentos. (Lo siento por mi ingles)

    – Yo

    2 sep 2020 a las 20:27


avatar de usuario
no es un robot

pivot_table = agrupar por + desapilar y groupby = tabla_pivote + pila consideramos verdaderos.

En particular, si columns parámetro de pivot_table() no se usa entonces groupby() y pivot_table() ambos producen el mismo resultado (si se usa la misma función de agregador).

# sample
df = pd.DataFrame({"a": [1,1,1,2,2,2], "b": [1,1,2,2,3,3], "c": [0,0.5,1,1,2,2]})

# example
gb = df.groupby(['a','b'])[['c']].sum()
pt = df.pivot_table(index=['a','b'], values=['c'], aggfunc="sum")

# equality test
gb.equals(pt) #True

En general, si comprobamos la código fuente, pivot_table() llamadas internas __internal_pivot_table(). Esta función crea una sola lista plana a partir de índices, columnas y llamadas groupby() con esta lista como el mero. Luego, después de la agregación, las llamadas unstack() en la lista de columnas.

Si las columnas nunca se pasan, no hay nada que desapilar, por lo que groupby y pivot_table producir trivialmente la misma salida.

Una demostración de esta función es:

gb = (
    df
    .groupby(['a','b'])[['c']].sum()
    .unstack(['b'])
)
pt = df.pivot_table(index=['a'], columns=['b'], values=['c'], aggfunc="sum")

gb.equals(pt) # True

Como stack() es la operación inversa de unstack()lo siguiente también es verdadero:

(
    df
    .pivot_table(index=['a'], columns=['b'], values=['c'], aggfunc="sum")
    .stack(['b'])
    .equals(
        df.groupby(['a','b'])[['c']].sum()
    )
) # True

En conclusión, dependiendo del caso de uso, uno es más conveniente que el otro, pero ambos pueden usarse en lugar del otro y después de aplicar correctamente stack()/unstack()ambos darán como resultado el mismo resultado.

¿Ha sido útil esta solución?