Entender el lenguaje utilizado en Power BI
Empezando con DAX
En este enlace accederá a un artículo donde Alberto Ferrari de SQLBI da siete razones que explicarían porqué DAX, aun siendo simple, no es fácil. Para alguien que se esté iniciando en DAX es de obligada lectura, extraerá sabios consejos que seguro le ahorraran tiempo y más de un dolor de cabeza.
El título del tercer motivo, de los siete que componen ese artículo, dice “Hay pocos conceptos importantes”, en él enumera los cuatro sobre los que se basa el lenguaje DAX :
- Contextos de evaluación
- Iteradores
- Transición de contexto
- Tablas expandidas
Tal como dice Alberto, estos son los conceptos fundamentales y difícilmente podrá entender los tres últimos si el primero no ha sido bien interiorizado. La intención del presente artículo es la de ayudar a quien se inicia en DAX a comprender qué son los “Contextos de evaluación”. Asumo que el lector ya tiene instalado Power BI y que ya ha visto la visualización que Power BI genera por defecto, arrastrando alguna columna al panel de Reporting.
Habrá descubierto que es posible construir un gráfico que muestre la evolución en el tiempo de algún valor que sea calculable, por ejemplo, la columna “Cantidad” de una tabla de ventas.
Las imágenes mostradas aquí, junto con los cálculos que se explican, se han realizado a partir de un sencillo modelo que contiene una única tabla, en ella se recogen las ventas realizadas en un periodo de tiempo determinado. Cada fila contiene la información de cada movimiento, en nuestro caso una venta.
Un consejo para los habituados a trabajar con Excel o cualquier otro programa de Hojas de cálculo, aquí olvídese del concepto de celda, sencillamente no existe. Power BI trabaja con columnas y tablas, junto con la relación establecida entre estas últimas.
Contexto de Filtro
La forma más sencilla de mostrar qué son los Contextos de evaluación es empezar construyendo una medida en su forma más simple :
Para ello debemos clicar con el botón derecho sobre la tabla de Ventas que se muestra en la parte derecha, y entre las opciones mostradas seleccionamos “Nueva medida”. Otra forma sería clicando directamente sobre el icono que se encuentra en la parte derecha de la pestaña inicio.
Si arrastramos la medida a una visualización del tipo tabla, obtenemos el resultado de 248, que es la suma de las cantidades recogidas en la columna “Cantidad” de la tabla de “Ventas”. Si
hacemos lo mismo con el campo cliente y lo incorporamos a la tabla, tendremos la cantidad vendida para cada cliente. Obteniendo una visualización como la que se muestra:
¿Cómo? ¿Sin modificar la medida?
Aquí es cuando se empieza a descubrir la “magia” de DAX, de hecho, será magia mientras no se entienda cómo funciona. ¿Cómo es posible que la misma medida nos dé resultados distintos?.
La respuesta es sencilla: porque el cálculo se realiza para distintos grupos de filas de la tabla (subconjuntos).
El criterio para generar estos subconjuntos de tabla lo establece el Contexto de filtro. En nuestro ejemplo el Contexto de filtro viene determinado por el campo cliente. Por tanto, para cada “Contexto” distinto y antes de aplicar la medida de cálculo, DAX recibe de la tabla de ventas sólo aquellas filas que pertenecen al cliente de ese Contexto de filtro. Será entonces cuando la medida nos dará el resultado aplicado sobre las únicas filas que le son visibles.
El Contexto de filtro no son solamente los campos incluidos en una tabla, son todos aquellos que pueden incorporarse a la visualización a través de columnas (o filas) en una matriz, selectores o filtros de distintos campos. Como ejemplo ilustrativo, podemos cambiar nuestra visualización de tabla por una matriz e incorporar el campo fecha en las columnas. También podemos crear un selector con el campo producto y seleccionar el producto “Cama”. Veremos que el resultado ha cambiado, ahora nos muestra un total de 80, no de 248, y para cada cliente y año la cantidad vendida :
Queda claro que el Contexto de filtro ahora está determinado por los campos Producto, Cliente y Año. Bien, no es exactamente así, tenemos valores que no están filtrados por los tres campos :
- Los totales verticales sólo están filtrados por los campos Producto y Cliente
- Los totales horizontales sólo están filtrados por los campos Producto y Año
Al principio ya vimos que el Contexto de filtro lo definía el campo “Cliente”, ahora también sabemos que en una misma visualización los cálculos están afectados por distintos Contextos de filtro.
Llegados a este punto podemos afirmar que, cada cálculo de la medida se verá afectado por el Contexto de filtro que le corresponda, de acuerdo con el lugar que ocupe en la visualización.
El Contexto de filtro siempre estará presente cada vez que se realice un cálculo en nuestro modelo, olvidarse de este detalle nos llevará a resultados erróneos.
Contexto de Fila
Puesto que estamos hablando de “Contextos de evaluación” y hasta ahora sólo hemos visto uno, el Contexto de filtro, nos faltará al menos otro. El que nos queda por ver es el “Contexto de fila”.
Los dos Contextos siempre actúan juntos y los dos forman lo que llamamos “Contexto de evaluación”.
La forma más transparente de explicar el Contexto de Fila es mostrándolo allí donde se genera de forma automática, creando una Columna calculada. Para crear esta columna usaremos una función DAX, igual que hicimos al crear una medida, pero ahora estamos incorporando nuevos valores a la tabla al añadir esta nueva Columna. Estos valores, a su vez, los podríamos utilizar al crear nuestras “medidas”, incorporando este nuevo campo de tabla cómo parámetros de la medida, cuando se nos pida una columna.
Si volvemos a nuestro ejemplo de Power BI, habiendo situado el cursor encima de la tabla ventas, clicamos con el botón derecho del ratón para seleccionar “Nueva columna”. Debajo del menú, igual que cuando creábamos la medida, aparecerá el nombre “Columna” seguido del signo igual. Aquí le indicaremos que queremos multiplicar el precio por la cantidad. Muy importante observar que cuando creamos una medida o una columna calculada, DAX nos ayuda mostrándonos en cada paso los parámetros del modelo que tenemos disponibles para ser utilizados en ese momento.
Si no los muestra es porque en el contexto en que estamos no es posible utilizarlo. Si clicamos “pre” nos ofrecerá directamente seleccionar la columna “Precio” y después de añadir el signo asterisco (multiplicación) haremos lo mismo con la cantidad, según se ve a continuación :
ya podremos validar la operación y tendremos la columna creada.
Para cada fila habrá realizado la operación que le hemos pedido, es decir, habrá recorrido toda la tabla iterándola desde la primera a la última fila. Es importante resaltar que, en ningún momento al construir la fórmula para crear la columna, le hemos dicho qué fila tenía que utilizar para el valor del “precio” y qué otra fila debía usar para el valor “cantidad”. DAX sabía que debían ser los dos valores de la misma fila gracias a que lo calculaba bajo el “Contexto de Fila”, definido en la iteración de la tabla.
Al crear la “columna calculada” no hemos utilizado ninguna función DAX, solamente hemos multiplicado los valores de dos columnas. ¿Qué ocurriría si creamos una columna calculada con la misma función utilizada al explicar el Contexto de Filtro? Haríamos exactamente lo mismo, pero en vez de crear una “medida” crearíamos una “Columna calculada”. El resultado no es intuitivo pero es de suma importancia entenderlo :
En cada fila de la nueva columna aparecerá el mismo resultado, exactamente los 248 que ya calculamos con la medida desde el apartado “Informe”. Ya dije más arriba que el contexto de filtro siempre está presente y que los dos (de filtro y de fila) siempre actúan juntos.
Por tanto, al incluir en una columna calculada la función “SUM”, crea el contexto de fila que recorre toda la tabla, pero a su vez, a la función SUM le afecta el Contexto de Filtro en el que se encuentre. Y ¿Cuál es el contexto de filtro, para cada una de las filas?, pues todo el modelo.
Aquí no hay selectores, ni filtros, ni cualquier otro parámetro que fuerce a la función “SUM” a calcular sobre un subconjunto de la tabla Ventas, para cada fila su Contexto de filtro es toda la tabla de ventas.
Ahora podríamos hacer el ejercicio inverso. Utilizar la primera operación que hemos usado al insertar la Columna Calculada, para crear una medida. De nuevo clicamos en insertar medida,
pero en vez de utilizar la función SUM, le pedimos que multiplique la columna “precio” con la de “cantidad”, validamos y se nos mostrará un error del tipo :
No puede determinar un valor único porque le falta el Contexto de fila, no sabe cómo desplazarse por la tabla para realizar el cálculo que se le pide. De hecho, al intentar crear la medida, habrá podido comprobar que DAX no nos ofrecía cómo opción ninguna columna de la tabla, si antes no especificamos una función. Recordemos que con SUM no necesitamos el contexto de fila, porque sólo había una columna (no es exactamente de esta manera, pero aclararlo requiere haber avanzado más en DAX).
Para resolver el problema debemos crear ese contexto de fila que nos falta, y esto lo podemos lograr usando una función que lo cree. Para este propósito tenemos los iteradores, que son funciones que recorren la tabla creando el Contexto de fila. Uno de los muchos iteradores es SUMX, en esta caso la fórmula quedaría como sigue :
Aquí la tabla Ventas será el subconjunto resultante de aplicar el Contexto de Filtro y la función SUMX se encargará de iterarla creando el contexto de fila, para multiplicar precio y cantidad por cada una de las filas y finalmente, sumando todos los valores para obtener el resultado final.
Si creamos un nuevo visual clicando sobre el icono “Matriz” e incorporamos nuestra medida «TotalVtas» a los “Valores”, el campo “Cliente” a las “Filas” y el campo “Fecha” a las “Columnas”, deberíamos ver lo que se muestra aquí :
Si en el selector de “Producto” que hemos creado antes en Power BI, seleccionamos el producto “Cama”, laMatriz nos mostrará los valores sólo de ese producto y para los clientes y años según corresponda a cada “Contexto”.
Una vez que los dos Contextos con los que DAX funciona hayan quedado claros, tocaría hablar de la Transición de contexto y como se transmiten los contextos entre las tablas del modelo, pero el edificio DAX se escala peldaño a peldaño y siempre hay que practicar.
Un buen ejercicio siempre es entender el porqué de un resultado inesperado, el tiempo invertido dará buenos frutos. Justo al contrario si opta por el prueba y error, cuando intente construir una medida, más pronto que tarde obtendrá resultados extraños y acumulará frustraciones.
Cómo decía Alberto Ferrari , simple. ¿Cierto?