pandas: groupby y pivot
Cuando el director comercial pregunta "¿cuánto factura cada sucursal por mes?", necesitás agrupar
miles de transacciones por categoría y calcular totales. groupby es la herramienta que convierte
datos transaccionales en reportes ejecutivos. Es el equivalente exacto del GROUP BY de SQL, pero
con la potencia de Python.
Concepto teórico
El patrón Split-Apply-Combine
groupby sigue un patrón de tres pasos que fue formalizado por Hadley Wickham (creador de R y
ggplot2):
- Split (dividir): pandas divide el DataFrame en grupos según los valores de una columna. Ejemplo: todas las filas de "CABA" en un grupo, todas las de "Rosario" en otro.
- Apply (aplicar): se aplica una función de agregación (
sum,mean,count, etc.) a cada grupo por separado. - Combine (combinar): los resultados de cada grupo se combinan en un nuevo DataFrame o Serie.
groupby.
# Sintaxis básica
df.groupby("columna_para_agrupar")["columna_para_calcular"].funcion()
# Ejemplo concreto
df.groupby("Sucursal")["Ventas"].sum()
# → "Agrupá por sucursal y sumá las ventas de cada una"
Funciones de agregación
| Función | Qué calcula | Equivalente SQL |
|---|---|---|
.sum() |
Suma total | SUM(col) |
.mean() |
Promedio aritmético | AVG(col) |
.count() |
Cantidad de filas (no nulas) | COUNT(col) |
.min() / .max() |
Mínimo / máximo | MIN(col) / MAX(col) |
.median() |
Mediana | (no estándar en SQL) |
.std() |
Desviación estándar | STDDEV(col) |
.first() / .last() |
Primer / último valor | (no estándar) |
.nunique() |
Cantidad de valores únicos | COUNT(DISTINCT col) |
Múltiples agregaciones con .agg()
El método más poderoso: .agg() te permite aplicar diferentes funciones a diferentes
columnas en una sola operación. Es como escribir un
SELECT SUM(ventas), AVG(margen), COUNT(*) FROM ... GROUP BY ... en SQL.
# .agg() con diccionario: columna → funciones
df.groupby("Sucursal").agg(
Ventas_Total = ("Ventas", "sum"),
Ticket_Prom = ("Monto", "mean"),
Operaciones = ("ID", "count")
)
Nombre = ("columna", "funcion")
te deja ponerle nombre a cada columna resultante directamente. Es más limpio que
.agg({"col": ["sum", "mean"]}) que genera MultiIndex en las columnas (difícil de manejar).
Pivot Tables: la tabla dinámica
pivot_table es como las tablas dinámicas de Excel: pone valores de una columna como filas, valores
de otra como columnas, y calcula una agregación en la intersección. Es ideal para reportes matriciales.
# Pivot table
pd.pivot_table(
df,
values="Ventas", # Qué calcular
index="Sucursal", # Filas
columns="Mes", # Columnas
aggfunc="sum" # Función de agregación
)
pivot_table te
convierte en la persona que genera esos reportes en 5 minutos en vez de 3 horas en Excel.Ejemplos explicados paso a paso
Ejemplo 1: groupby básico con una columna
El caso fundamental: agrupar transacciones de ventas por sucursal y calcular métricas.
Hacé clic en ▶ Ejecutar
Ejemplo 2: Agrupar por múltiples columnas
Podés agrupar por dos o más columnas — por ejemplo, ver las ventas de cada vendedor en cada sucursal.
Hacé clic en ▶ Ejecutar
Ejemplo 3: .agg() con múltiples funciones
El reporte completo: para cada sucursal queremos la suma, el promedio, el máximo y la cantidad de operaciones, todo de una vez.
Hacé clic en ▶ Ejecutar
Ejemplo 4: pivot_table — La tabla dinámica
Crear un reporte matricial donde las filas son sucursales, las columnas son canales, y las celdas son el total de ventas.
Hacé clic en ▶ Ejecutar
Ejemplo 5: Transformaciones dentro de grupos
A veces no querés resumir los datos en menos filas, sino agregar información del grupo a cada fila original. Por ejemplo: "¿cuánto representan las ventas de esta transacción sobre el total de su sucursal?"
Hacé clic en ▶ Ejecutar
agg() reduce muchas filas a una por grupo
(como GROUP BY en SQL). transform() mantiene el mismo número de filas pero agrega la
métrica del grupo a cada una (como una window function en SQL). Es la diferencia entre "dame el
total de CABA" vs "dime cuánto es el total de CABA en cada fila de CABA".Referencia rápida
| Operación | Sintaxis | Resultado |
|---|---|---|
| Agrupar y sumar | df.groupby("col")["val"].sum() |
Serie con totales |
| Múltiples columnas | df.groupby(["c1","c2"]) |
Grupos multinivel |
| Named agg | .agg(Nom=("col","func")) |
DataFrame con headers limpios |
| Pivot table | pd.pivot_table(df,...) |
Tabla matricial |
| Cross tabulation | pd.crosstab(s1, s2) |
Tabla de frecuencias |
| Transform | .groupby().transform("sum") |
Serie del mismo largo |
| Resetear índice | .reset_index() |
Índice → columnas |
Ejercicios
Ejercicio 1: groupby + sum
Calculá las ventas totales por Ciudad. Imprimí el resultado. Debe incluir 95000
(total de CABA).
Hacé clic en ▶ Ejecutar
Ejercicio 2: groupby + mean
Calculá el ticket promedio por Canal. Imprimí el promedio de "Web" redondeado. Debe incluir
25000.
Hacé clic en ▶ Ejecutar
Ejercicio 3: groupby + count (conteo)
Contá cuántas operaciones hubo por Ciudad. Debe incluir 3 (CABA tiene 3
operaciones).
Hacé clic en ▶ Ejecutar
Ejercicio 4: Agrupar por dos columnas
Agrupá por Ciudad y Canal, sumá Monto. Imprimí el resultado. Debe
incluir 55000 (CABA+Web).
Hacé clic en ▶ Ejecutar
Ejercicio 5: .agg() con named aggregations
Por cada Ciudad, calculá: venta total, ticket promedio y cantidad de operaciones usando
.agg(). Debe incluir 40000 (Rosario total).
Hacé clic en ▶ Ejecutar
Ejercicio 6: pivot_table básica
Creá una pivot_table con filas = Ciudad, columnas = Canal, valores =
Monto (suma). Debe incluir 55000.
Hacé clic en ▶ Ejecutar
Ejercicio 7: Ranking con sort_values
Agrupá por Vendedor, sumá Monto, ordenálo de mayor a menor e imprimí el nombre del
vendedor #1 usando .index[0]. Debe incluir Ana.
Hacé clic en ▶ Ejecutar
Ejercicio 8: transform para participación
Usá .transform("sum") para calcular qué porcentaje del total de su ciudad representó cada venta.
Imprimí la columna de participación. Debe incluir 31.6.
Hacé clic en ▶ Ejecutar
Ejercicio 9: pivot_table con margins
Creá una pivot_table con margins=True de ventas por Sucursal × Mes. Debe incluir la palabra
All (la fila/columna de totales).
Hacé clic en ▶ Ejecutar
Ejercicio 10: Reporte ejecutivo completo
Generá un reporte con: (1) Ventas totales por sucursal (con .agg), (2) Sucursal con más ventas, (3)
Participación % de cada sucursal. El output debe incluir CABA (la sucursal líder).
Hacé clic en ▶ Ejecutar
Resumen y conexión
groupbysigue el patrón Split-Apply-Combine: dividir, calcular, reunir.- Podés agrupar por 1 o más columnas:
df.groupby(["col1", "col2"]). .agg()con named aggregations es la forma más profesional de generar reportes.pivot_tablegenera reportes matriciales (filas × columnas), ideal para ejecutivos.transform()mantiene las filas originales y les agrega la métrica del grupo — perfecto para participaciones y comparaciones.- Siempre incluí participación porcentual (
%) en tus reportes para dar contexto relativo.
En la siguiente lección (08 · pandas: merge/join/concat) vas a aprender a combinar tablas de distintas fuentes — como cruzar la tabla de transacciones con la tabla de clientes, un patrón que vas a usar todos los días.
Recursos: pandas docs — GroupBy · pandas docs — Reshaping (pivot)