(+351) 21 24 10006  ·  info@bconcepts.pt
Carnaxide, Lisboa

Cómo calcular media ponderada por grupo en DAX: paso a paso

João Barros 03 de August de 2026 5 min de lectura

Vamos a calcular una media ponderada por grupo en DAX — por ejemplo, la media de precios ponderada por cantidad por categoría. Esto es útil cuando quieres un valor representativo que tenga en cuenta el peso de cada fila (cantidad, importancia, puntuación). En informes comerciales, por ejemplo, una media simple puede engañar: si vendiste 2 unidades a 100€ y 100 unidades a 50€, la media simple de los precios es (100+50)/2 = 75€, mientras que la media ponderada por cantidad es (100*2 + 50*100) / (2+100) = 51,92€, que refleja mejor el precio medio efectivo.

Requisitos previos

  • Power BI Desktop (o Excel con modelo de datos y DAX).
  • Una tabla de hechos con columnas: Category, Price, Quantity. Idealmente, la tabla se llama 'Sales' y las columnas 'Sales'[Price], 'Sales'[Quantity], 'Sales'[Category].
  • Conocimientos básicos de medidas y contexto de filtro en DAX: entender row context vs filter context, y cómo CALCULATE altera filtros.
  • Datos de ejemplo con algunas decenas a miles de filas — el enfoque funciona en ambos casos; solo atención al rendimiento si tienes millones de filas.

Paso 1: Entender qué es una media ponderada

Una media ponderada calcula la suma(Valor * Peso) dividida por la suma(Peso). En términos prácticos, para cada categoría queremos: SUMX(lines, Price * Quantity) / SUM(Quantity). Para ver con números concretos, supongamos Category = "A" con tres registros:

  • Fila 1: Price = 10, Quantity = 2
  • Fila 2: Price = 12, Quantity = 3
  • Fila 3: Price = 9, Quantity = 5

El numerador es 10*2 + 12*3 + 9*5 = 20 + 36 + 45 = 101. El denominador es 2+3+5 = 10. La media ponderada es 101 / 10 = 10,1. Observa que usar SUM('Sales'[Price]) / COUNTROWS('Sales') daría una media simple diferente; por eso necesitamos multiplicar por Quantity en cada fila.

Paso 2: Crear las medidas base

Primero crea dos medidas simples: el numerador (suma ponderada) y el denominador (suma de los pesos). Estas medidas quedan reutilizables y evitan repeticiones. Usar SUMX asegura que el cálculo se hace por fila de la tabla de hechos antes de agregar — eso es crucial cuando tienes varias columnas o expresiones por fila.

WeightedAmount = SUMX( 'Sales', 'Sales'[Price] * 'Sales'[Quantity] )
TotalQuantity = SUM( 'Sales'[Quantity] )

Notas prácticas: si la columna Quantity puede tener nulos, asegúrate de que esté a cero o usa COALESCE('Sales'[Quantity],0). Formatea TotalQuantity como entero y WeightedAmount como decimal con 2-4 decimales según sea necesario.

Paso 3: Crear la medida de la media ponderada segura

Ahora creamos la medida final que divide el numerador por el denominador. Usamos DIVIDE para evitar división por cero y garantizar resultados limpios cuando no hay datos en el contexto. Además, es buena práctica usar VAR para calcular cada componente una sola vez, lo que ayuda al rendimiento y a la legibilidad.

WeightedAverage Price =
DIVIDE(
    [WeightedAmount],
    [TotalQuantity]
)

Otra opción, con VARs explícitas, es:

WeightedAverage Price =
VAR Num = [WeightedAmount]
VAR Den = [TotalQuantity]
RETURN DIVIDE(Num, Den)

Formatear la medida a dos decimales es común. Si tienes porcentajes o puntuaciones con escala diferente, ajusta el formato según el caso.

Paso 4: Tratar escenarios con filtros o diferentes granularidades

Si quieres calcular la media ponderada siempre por Category, independientemente de otros filtros, usa ALL o ALLEXCEPT. Por ejemplo, si tienes un slicer por Product y quieres la media por Category ignorando el slicer de producto, ALLEXCEPT mantiene el filtro de Category y elimina los restantes.

WeightedAverage Price by Category =
VAR Num =
    CALCULATE(
        SUMX('Sales', 'Sales'[Price] * 'Sales'[Quantity]),
        ALLEXCEPT('Sales', 'Sales'[Category])
    )
VAR Den =
    CALCULATE(
        SUM('Sales'[Quantity]),
        ALLEXCEPT('Sales', 'Sales'[Category])
    )
RETURN
DIVIDE(Num, Den)

Ejemplo: si Category = "A" tiene 100 unidades, pero un slicer de Product limita a 20 unidades, la medida normal mostrará el valor para las 20 unidades; la versión con ALLEXCEPT mostrará el valor para las 100 unidades de la Category. Usa este enfoque con cuidado — puedes contravenir las expectativas de los usuarios si ignoras filtros aplicados en el informe.

Paso 5: Ejemplo con filtros complejos (fechas y productos)

Cuando tienes dimensiones separadas (Date, Product, Category), asegúrate de usar la tabla de hechos para pesos y valores y emplea relaciones adecuadas. Si quieres la media ponderada solo para el año en curso, combina con FILTER. Una forma robusta es filtrar la tabla de fechas explícitamente:

WeightedAvg This Year =
VAR Num =
    CALCULATE(
        SUMX('Sales', 'Sales'[Price] * 'Sales'[Quantity]),
        FILTER(ALL('Date'), YEAR('Date'[Date]) = YEAR(TODAY()))
    )
VAR Den =
    CALCULATE(
        SUM('Sales'[Quantity]),
        FILTER(ALL('Date'), YEAR('Date'[Date]) = YEAR(TODAY()))
    )
RETURN
DIVIDE(Num, Den)

Así puedes combinar filtros de tiempo con otros slicers. Si las relaciones entre tablas no están activas, puedes necesitar USERELATIONSHIP; si tienes múltiples años y quieres ALLSELECTED para respetar selecciones del usuario, usa ALLSELECTED('Date').

Verificar el resultado

Coloca Category en una tabla visual y añade las medidas WeightedAverage Price y TotalQuantity. Verifica manualmente una fila: calcula en una hoja de cálculo la suma(Price*Quantity) y la suma(Quantity) para la category y confirma que la división coincide. Errores comunes: olvidar SUMX (llevando a la multiplicación de agregados como SUM(Price)*SUM(Quantity) que está mal), no usar DIVIDE (puede dar error por división por cero) o aplicar ALLEXCEPT de forma incorrecta y perder filtros importantes. Prueba también escenarios con 0 cantidades y valores nulos.

Conclusión

Con estas medidas puedes calcular medias ponderadas robustas en diferentes contextos de filtro. Próximos pasos: aplicar la técnica a otras variables (costes, puntuaciones) y comparar con medias simples. Consejo práctico: valida siempre al menos 3 filas manualmente (pequeño conjunto de ejemplo) y luego prueba con agregados mayores; eso ayuda a entender dónde el contexto de filtro influye en el resultado. Si necesitas, comparte un ejemplo concreto y te ayudo a depurar.