Un promedio ponderado en Python se calcula como la suma de cada valor por su peso dividida entre la suma de los pesos. Sin librerías: sum(x * w for x, w in zip(valores, pesos)) / sum(pesos). Con NumPy: np.average(valores, weights=pesos). Con pandas: (df["valor"] * df["peso"]).sum() / df["peso"].sum(). Los pesos no tienen que sumar 1.
x̄w = Σ x·wΣ w
Sintaxis
# Python puro
sum(x * w for x, w in zip(valores, pesos)) / sum(pesos)
# statistics, Python 3.11 o posterior
import statistics as st
st.fmean(valores, weights=pesos)
# NumPy
import numpy as np
np.average(valores, weights=pesos)
np.average(valores, weights=pesos, returned=True) # (promedio, suma de pesos)
Paso a paso
- Pon los valores y los pesos en dos listas del mismo largo y en el mismo orden.
- Revisa que ningún peso sea negativo y que la suma de pesos no sea cero.
- Multiplica cada valor por su peso y suma los productos.
- Divide entre la suma de los pesos (no entre la cantidad de valores).
- Redondea solo el resultado final.
Ejemplos resueltos
Ejemplo 1: calificación final con porcentajes
Un curso evalúa examen (40 %), tareas (35 %) y proyecto (25 %). Las notas son 8.5, 7.0 y 9.0:
import numpy as np
notas = np.array([8.5, 7.0, 9.0])
pesos = np.array([0.4, 0.35, 0.25])
print(np.average(notas, weights=pesos))
8.1
8.5 × 0.4 + 7.0 × 0.35 + 9.0 × 0.25 = 3.4 + 2.45 + 2.25 = 8.1. El promedio simple de las tres notas sería 8.17: el examen y las tareas, que pesan más, lo bajan.
Ejemplo 2: promedio por créditos con Python puro
Cuatro materias con calificación y créditos:
cal = [9.0, 7.5, 8.0, 6.0]
cred = [8, 6, 4, 2]
print(sum(c * w for c, w in zip(cal, cred)) / sum(cred))
print(np.average(cal, weights=cred, returned=True))
8.05
(np.float64(8.05), np.float64(20.0))
Los productos suman 72 + 45 + 32 + 12 = 161, y 161 / 20 créditos = 8.05. Con returned=True, NumPy devuelve también la suma de pesos, útil para mostrar «8.05 sobre 20 créditos».
Ejemplo 3: precio promedio por sucursal con pandas
Cada fila es una venta con precio y unidades. El precio promedio real de cada sucursal pondera por unidades vendidas:
import pandas as pd
ventas = pd.DataFrame({
"sucursal": ["Norte", "Norte", "Sur", "Sur", "Sur"],
"precio": [120.0, 95.5, 80.0, 99.0, 110.0],
"unidades": [30, 50, 20, 10, 40],
})
ventas["importe"] = ventas["precio"] * ventas["unidades"]
g = ventas.groupby("sucursal")[["importe", "unidades"]].sum()
print(g["importe"] / g["unidades"])
sucursal
Norte 104.687500
Sur 99.857143
dtype: float64
Primero se crea la columna de productos (importe), luego se suman importes y unidades por grupo y al final se divide. Hacer groupby(...)["precio"].mean() daría 107.75 para Norte, porque trata igual una venta de 30 unidades que una de 50.
Errores comunes
ZeroDivisionError: Weights sum to zero, can't be normalized. Todos los pesos son cero, o se anulan entre positivos y negativos. Revisa los datos.TypeError: Axis must be specified when shapes of a and weights differ.Las listas tienen distinto largo. Conzip, en cambio, no hay error: la lista larga se corta en silencio y el resultado sale mal. Desde Python 3.10 puedes escribirzip(valores, pesos, strict=True)para que falle.- Dividir entre
len(valores). Solo es correcto si los pesos suman exactamente 1. Dividir entresum(pesos)funciona siempre. - Usar
np.meanconweights. No existe ese parámetro; la función ponderada esnp.average. - Pesos en porcentaje con símbolo.
"40%"es texto; conviértelo a 40 o a 0.4. Da igual cuál uses mientras todos estén en la misma escala.
Comprueba el resultado con la calculadora de promedio ponderado. Si trabajas en hoja de cálculo, el equivalente es SUMAPRODUCTO, explicado en el promedio ponderado en Excel.
Fuentes
- NumPy, numpy.average. Parámetros weights y returned. Consultado el 11 de noviembre de 2026.