Para calcular el promedio por grupo en pandas, agrupa por la columna de categoría y promedia la columna numérica: df.groupby("region")["monto"].mean(). Obtienes una Serie con un promedio por región. Si quieres varias medidas a la vez usa .agg(["mean", "median", "count"]), y si quieres pegar el promedio del grupo a cada fila usa .transform("mean").
Sintaxis
df.groupby("grupo")["valor"].mean() # Serie: un promedio por grupo
df.groupby("grupo", as_index=False)["valor"].mean() # DataFrame con el grupo como columna
df.groupby(["g1", "g2"])["valor"].mean() # varios niveles
df.groupby("grupo").agg(promedio=("valor", "mean"),
ventas=("valor", "size")) # agregación con nombre
df.groupby("grupo")["valor"].transform("mean") # mismo largo que df
Paso a paso
- Identifica la columna que define los grupos (región, materia, mes) y la que vas a promediar.
- Llama a
groupbycon la primera y selecciona la segunda entre corchetes. - Aplica
.mean()para una tabla resumen, o.transform("mean")si necesitas comparar cada fila con su grupo. - Ordena con
.sort_values()y redondea con.round(2)para presentar.
Los datos de todos los ejemplos:
import pandas as pd
v = pd.DataFrame({
"region": ["Norte", "Sur", "Norte", "Centro", "Sur", "Centro", "Norte"],
"vendedor": ["Eva", "Raúl", "Iván", "Paz", "Raúl", "Paz", "Eva"],
"monto": [1500, 2300, 1800, 900, 2100, 1300, 1100],
})
Ejemplos resueltos
Ejemplo 1: tabla resumen con varias medidas
print(v.groupby("region")["monto"].agg(["mean", "median", "count"]).round(2))
mean median count
region
Centro 1100.00 1100.0 2
Norte 1466.67 1500.0 3
Sur 2200.00 2200.0 2
En Norte, el promedio (1,466.67) queda por debajo de la mediana (1,500) porque la venta de 1,100 tira hacia abajo. Mostrar count junto al promedio evita sacar conclusiones de grupos con muy pocas filas. Si prefieres nombres propios para las columnas, usa la agregación con nombre: .agg(promedio=("monto", "mean"), ventas=("monto", "size")).
Ejemplo 2: comparar cada venta con el promedio de su región
v["prom_region"] = v.groupby("region")["monto"].transform("mean").round(2)
v["dif"] = (v["monto"] - v["prom_region"]).round(2)
print(v)
region vendedor monto prom_region dif
0 Norte Eva 1500 1466.67 33.33
1 Sur Raúl 2300 2200.00 100.00
2 Norte Iván 1800 1466.67 333.33
3 Centro Paz 900 1100.00 -200.00
4 Sur Raúl 2100 2200.00 -100.00
5 Centro Paz 1300 1100.00 200.00
6 Norte Eva 1100 1466.67 -366.67
transform devuelve un resultado del mismo largo que la tabla original, con el promedio del grupo repetido en cada fila. Con eso puedes filtrar las ventas por encima del promedio de su región: v[v["dif"] > 0].
Ejemplo 3: dos niveles de agrupación
print(v.groupby(["region", "vendedor"])["monto"].mean())
region vendedor
Centro Paz 1100.0
Norte Eva 1300.0
Iván 1800.0
Sur Raúl 2200.0
Name: monto, dtype: float64
El resultado tiene un índice de dos niveles. Para verlo como tabla cruzada, con regiones en filas y vendedores en columnas, usa pd.pivot_table(v, values="monto", index="region", columns="vendedor", aggfunc="mean"); las combinaciones sin ventas quedan como NaN.
Filtrar y ordenar grupos
Para quedarte con las regiones cuyo promedio supera 1,300 y ordenarlas de mayor a menor:
prom = v.groupby("region")["monto"].mean()
print(prom[prom > 1300].sort_values(ascending=False).round(2))
region
Sur 2200.00
Norte 1466.67
Name: monto, dtype: float64
Es lo mismo que hace HAVING AVG(monto) > 1300 en SQL, explicado en promedio en SQL.
Errores comunes
TypeErroral promediar todo el grupo.v.groupby("region").mean()intenta promediar también la columnavendedor, que es texto. Selecciona la columna numérica o pasanumeric_only=True.- El grupo queda como índice y no como columna. Agrega
as_index=Falseo encadena.reset_index()antes de exportar a Excel o CSV. - Grupos con
NaNdesaparecen. Las filas cuyo grupo esNaNse excluyen por omisión. Usagroupby("region", dropna=False)para verlas. - Promediar promedios de grupos de distinto tamaño. El promedio de 1,100, 1,466.67 y 2,200 es 1,588.89, pero el promedio de las 7 ventas es 1,571.43. Para el promedio general usa
v["monto"].mean(). - Ponderar sin querer. Si cada fila ya es un subtotal con distinto número de unidades, el promedio por grupo debe ponderarse; mira promedio ponderado en Python.
Fuentes
- pandas, Group by: split-apply-combine. Agregación con nombre, transform. Consultado el 11 de noviembre de 2026.