La idea
Una medida DAX es una sola fórmula, pero un informe le hace muchas preguntas. Una matriz con seis filas
de categoría, un total y dos segmentadores evalúa Sales siete veces, y cada vez la medida ve filas
distintas de los datos. El conjunto de filtros bajo el que corre una sola evaluación es su contexto
de filtro.
Tú nunca le pasas los filtros. Lo hace la celda: sus encabezados de fila y de columna, cada segmentador
de la página, el panel Filtros y cualquier resaltado cruzado aportan algo. CALCULATE es la única
función que permite a una medida cambiar ese conjunto a propósito.
Por qué existe
Imagina el mismo informe sin contexto de filtro. Necesitarías una medida de ventas de Lighting, una de
ventas de Furniture, una de ventas web de Lighting en 2025, y así para cada combinación en la que un
lector pueda hacer clic. Las hojas de cálculo funcionan así: cada SUMIFS escribe sus propias
condiciones.
Power BI le da la vuelta. Defines una vez lo que significa un número (Sales suma line_total) y el
informe decide de qué filas se trata. Por eso una misma medida funciona en una tarjeta, una matriz y
un gráfico sin cambios, y por eso los segmentadores "simplemente funcionan".
El precio es que las filas detrás de un número no se ven. Cuando una cifra parece incorrecta, la fórmula rara vez es el problema. El problema es el contexto de filtro, y solo puedes arreglarlo si puedes imaginarlo.
Cómo funciona por dentro
Evaluar una celda sigue siempre el mismo orden.
- Reunir los filtros. Todo lo que rodea la celda agrega un filtro sobre una columna: el encabezado
de fila sobre
products[category], el segmentador de Year sobre'Date'[Year], el segmentador de Channel sobreorders[channel]. Los filtros sobre columnas distintas se combinan con AND. - Poner cada filtro en su propia tabla, la que es dueña de la columna.
- Dejar que los filtros fluyan por las relaciones, del lado uno al lado muchos, hasta llegar a la
tabla que lee la medida. En el modelo de Harbor & Pine todos los caminos terminan en
order_items. - Evaluar la medida sobre las filas que sobrevivieron a todos los filtros.
Figura 1
Cómo llegan a order_items los filtros de una celda
'Date'
- Date
- Year
- Month
Year = 2025
orders
- order_id
- order_date
- channel
- status
channel = "web"
status = "completed"
customers
- customer_id
- segment
- state
products
- product_id
- category
category = "Lighting"
order_items
- order_id
- product_id
- line_total
- El modelo de Harbor & Pine. Cada línea va de un lado uno (1) a un lado muchos (*).
order_itemsguarda los números;Salessuma suline_total. - La fila de Lighting en la matriz pone un filtro sobre
products[category]. Ese filtro baja por la relación hastaorder_items: solo quedan las líneas de Lighting. - El segmentador de Year filtra
'Date'. Ese filtro llega primero aordersy luego aorder_items: dos saltos. - El segmentador de Channel cae sobre
ordersy sigue el mismo camino hacia abajo. Los tres filtros se encuentran ahora enorder_itemsy se combinan con AND. - Los filtros solo fluyen de uno a muchos. El filtro de categoría no sube de vuelta a
orders, así queCOUNTROWS(orders)seguiría contando pedidos de todas las categorías. CALCULATE(..., orders[status] = "completed")agrega un filtro más antes de que se haga la suma. Fluye hacia abajo como los demás.
El paso 3 explica muchos números "equivocados". Con relaciones de una sola dirección, un filtro nunca
fluye de muchos a uno. Un filtro de categoría reduce order_items pero deja orders intacta, y por eso
"pedidos por categoría" necesita DISTINCTCOUNT(order_items[order_id]) y no COUNTROWS(orders).
Aquí está la misma celda como filas reales. Los filtros quitan filas una tras otra; la suma solo se hace al final.
Figura 2
Una celda, filtro por filtro: Lighting, 2025, web
| order_item_id | category | channel | status | line_total |
|---|---|---|---|---|
| 19660 | Lighting | web | completed | 54.99 |
| 19663 | Lighting | web | completed | 189.00 |
| 19749 | Lighting | web | cancelled | 189.00 |
| 19675 | Lighting | app | completed | 219.96 |
| 19679 | Furniture | web | completed | 746.30 |
| 19792 | Textiles | marketplace | completed | 23.99 |
| 19662 | Lighting | web | completed | 31.99 |
| Sales |
|---|
| $275.98 |
- Siete líneas de pedido reales. Antes de cualquier filtro, una medida las vería todas.
- Encabezado de fila:
category = "Lighting". Furniture y Textiles quedan fuera. - Segmentador de Channel:
channel = "web". La línea de app también queda fuera. Los filtros sobre columnas distintas siempre se acumulan. CALCULATEagregastatus = "completed". La línea cancelada se elimina.SUM(order_items[line_total])se ejecuta sobre lo que queda: 54.99 + 189.00 + 31.99.
Qué hace CALCULATE
CALCULATE(expression, filter1, filter2, ...) trabaja en tres pasos:
- Toma una copia del contexto de filtro actual (los filtros de la celda).
- Aplica cada argumento de filtro a la copia. Si la columna todavía no está filtrada, el filtro se
agrega. Si la columna ya está filtrada, el nuevo filtro reemplaza al anterior.
ALL,ALLEXCEPTyREMOVEFILTERS, en cambio, quitan filtros. - Evalúa la expresión en la copia modificada. El contexto original no se toca, así que las celdas vecinas y las demás medidas no se ven afectadas.
La regla de "reemplazar" es la que sorprende a la gente, y es justo en la que se apoyan los porcentajes
del total: CALCULATE([Sales], REMOVEFILTERS(products[category])) le da a cada fila de categoría el
total de todas las categorías para dividir.
Figura 3
La misma matriz, tres medidas: CALCULATE agrega un filtro o reemplaza uno
| channel | Gross Sales | Completed Sales | Web Sales |
|---|---|---|---|
| app | $2,262,479 | $2,024,728 | $3,323,593 |
| marketplace | $930,273 | $837,483 | $3,323,593 |
| web | $3,323,593 | $3,032,073 | $3,323,593 |
| Total | $6,516,344 | $5,894,283 | $3,323,593 |
Gross Sales = SUM(order_items[line_total]). Cada fila filtraorders[channel], así que cada celda suma las líneas de ese canal.Completed Sales = CALCULATE([Gross Sales], orders[status] = "completed"). Status es una columna nueva, así que el filtro se agrega: cada canal conserva su filtro de fila y pierde sus líneas canceladas, reembolsadas y pendientes.Web Sales = CALCULATE([Gross Sales], orders[channel] = "web"). Channel ya está filtrado por la fila, así que CALCULATE reemplaza ese filtro. Todas las filas muestran el número de web.- La fila Total son las mismas medidas sin ningún filtro de canal, no una suma de las filas. Con un SUM simple las dos cosas coinciden; con proporciones y conteos distintos, no.
Cuando quieras que un argumento de filtro reduzca el filtro existente en vez de sobrescribirlo,
envuélvelo en KEEPFILTERS. Así la fila de web de una medida App Sales quedaría en blanco, porque
ningún pedido es web y app a la vez.
El contexto de fila es otra cosa
Una columna calculada, o un iterador como SUMX, recorre una tabla fila por fila. Esa "fila actual" es
el contexto de fila, y no es un filtro. Dentro de una columna calculada en products, la expresión
SUM(order_items[line_total]) devuelve el total general en cada fila, porque nada está filtrando
order_items: el producto actual es solo una fila que se está visitando.
CALCULATE conecta los dos. Envuelta en CALCULATE, la fila actual se convierte en un filtro
(esto se llama transición de contexto), así que CALCULATE(SUM(order_items[line_total])) en esa
columna le da a cada producto sus propias ventas. Una referencia a una medida como [Sales] lleva un
CALCULATE invisible alrededor, y por eso SUMX(products, [Sales]) funciona y SUMX(products, SUM(order_items[line_total])) repite el total.
Ver el contexto de filtro en Power BI Desktop
La matriz de práctica de este sitio te muestra los filtros de cada celda. En Power BI Desktop también puedes leerlos: pasa el cursor sobre una celda para ver su información sobre herramientas, abre el panel Filtros para ver los filtros del objeto visual, de la página y del informe, y usa Optimizar → Analizador de rendimiento → Copiar consulta para ver los filtros exactos que el objeto visual envía al modelo. Formato → Editar interacciones muestra qué segmentadores llegan a qué objetos visuales. Cuando un número te sorprenda, revisa ahí sus filtros antes de tocar la fórmula.
Errores comunes
"La fila Total suma las filas de arriba"
La fila Total es la medida evaluada otra vez, sin el filtro del encabezado de fila. Con una suma simple eso equivale a la suma de las filas. Con un promedio, un conteo distinto o una proporción normalmente no: el total del "valor promedio del pedido" es el promedio sobre todos los pedidos, no la suma de seis promedios.
"Un filtro en cualquier tabla llega a todas las demás tablas"
Los filtros se mueven por las relaciones, del lado uno al lado muchos, y ahí se detienen, salvo que una
relación esté configurada en ambas direcciones. Un segmentador sobre products nunca filtra
customers. Si un objeto visual ignora un segmentador, mira las flechas en la vista de modelo antes de
mirar el DAX.
"El filtro de CALCULATE se suma al filtro de la fila"
Solo cuando están en columnas distintas. En la misma columna gana el argumento y el filtro de la fila se
descarta, y así es como aparece "el mismo número en todas las filas". Usa KEEPFILTERS cuando quieras
decir "y además".
Ponte a prueba
Una pregunta. Al responderla, la lección queda marcada en el mapa; nunca bloquea un nivel.
No del todo. Eso pasaría si los filtros se combinaran con AND. Un argumento de filtro sobre una columna que ya está filtrada reemplaza el filtro anterior; con KEEPFILTERS obtendrías la celda en blanco.Prueba otra respuesta.
Correcto. Es la misma columna, así que CALCULATE descarta el channel = web de la fila y pone channel = app en su lugar. Todas las filas muestran la cifra de app.
No del todo. Es al revés: CALCULATE se ejecuta después de reunir los filtros de la fila y puede sobrescribirlos. Eso es lo que lo hace tan potente.Prueba otra respuesta.
No del todo. Los filtros nunca suman valores. Un filtro sobre channel conserva un conjunto de canales; este conserva solo app.Prueba otra respuesta.
Lección hecha: ya está marcada en el mapa.