Un escenario común a la hora de analizar datos es el querer mostrar distintas medidas evaluadas bajo el mismo contexto de filtro. Podemos hacer esto creando varias visualizaciones, cada una de ellas con una medida distinta. Una opción mejor, ya que hablamos del mismo contexto de filtro, sería dejar al usuario del informe la posibilidad de seleccionar en cada momento la medida a mostrar, y que una sola visualización se actualizara dinámicamente en función de esta selección.
Actualmente Power BI no nos ofrece esta posibilidad como función integrada, pero con un poco de DAX podemos llevarla a cabo. Esto es lo que vamos a ver en este artículo.
Creación de las medidas
En primer lugar, vamos a crear una serie de medidas sencillas con DAX, que serán las opciones disponibles de intercambiar para los usuarios del informe:
VentasTotales =
SUMX ( Sales; Sales[SalesQuantity] * Sales[UnitPrice] )
CostesTotales =
SUMX ( Sales; Sales[SalesQuantity] * Sales[UnitCost] )
DevolucionesTotales =
SUM ( Sales[ReturnAmount] )
Rentabilidad =
[VentasTotales] – [CostesTotales]
Rentabilidad% =
DIVIDE ( [Rentabilidad]; [VentasTotales] )
PesoContinente =
DIVIDE (
[‘VentasTotales’];
CALCULATE ( [VentasTotales]; ALL ( ‘Geography’ ) );
0
)
Tabla de parámetros
Posteriormente crearemos una tabla de forma manual en Power BI, que almacenará el nombre de cada una de las medidas tal y como se mostrará en el informe al usuario y un índice que utilizaremos para ordenarlas en el slicer y para el cambio de medida a mostrar en la visualización.
Una vez cargada la nueva tabla al modelo de datos, ordenaremos desde la vista de datos de nuestro modelo, los nombres de las medidas en función del número índice asignado.
Esta tabla no debe tener ninguna relación con otras tablas del modelo, por lo que vamos a echar un vistazo a la vista de relaciones para asegurarnos de que al cargarla, Power BI no la ha auto-relacionado con ninguna otra tabla ya presente.
Una vez tenemos creadas las medidas que intercambiaremos y cargada la tabla anterior al modelo de datos, es hora de crear la medida que nos permitirá llevar a cabo nuestro objetivo de dejar al usuario del informe la posibilidad de seleccionar la medida a mostrar en una visualización. Vamos a echar un vistazo al código y seguidamente explicaremos su funcionamiento:
La medida que hace la magia
MedidaVariable =
VAR Ventas = [VentasTotales]
VAR Costes = [CostesTotales]
VAR Devoluciones = [DevolucionesTotales]
VAR RentabilidadUSD = [Rentabilidad]
VAR RentabilidadPorcent = [Rentabilidad%]
VAR PesoRelativo = [PesoContinente]
VAR SeleccionMedida =
MIN ( SelecMedida[CodMedida] )
RETURN
IF (
HASONEVALUE ( SelecMedida[NombreMedida] );
SWITCH (
SeleccionMedida;
1; Ventas;
2; Costes;
3; Devoluciones;
4; RentabilidadUSD;
5; RentabilidadPorcent;
6; PesoRelativo
)
)
En primer lugar, crearemos una serie de variables locales a la formula a las que asignaremos nuestras medidas creadas al principio del artículo. La variable SeleccionMedida
la definimos como el mínimo de los números del campo CodMedida para que nos devuelva un único valor escalar.
Despues, como primer parámetro de la función lógica IF()
, vamos a introducir como condición a verificar HASONEVALUE(SelecMedida[NombreMedida])
. La función HASONEVALUE()
devuelve TRUE
en caso de que la columna solo tenga un valor visible en el contexto de filtro actual, por lo que solo devolverá TRUE
en caso de que el usuario haya seleccionado una, y solo una, de las medidas en el slicer.
Ya solo nos queda usar la función SWITCH()
que funciona igual que si anidamos varias funciones IF()
, (de hecho el motor de DAX convierte SWITCH() en varios IF() aninados por lo que el rendimiento es el mismo, pero hace el código mucho más fácil de leer). Su sintaxis es:
SWITCH(< expresión >, < valor >, < resultado >) [, < valor >, < resultado >]…[, < en otro caso >]
En nuestro caso vamos a comparar la variable SeleccionMedida
(expresión), con los valores posibles que puede devolvernos dicha variable (1, 2, 3, 4, 5 o 6), y como resultado en cada caso la variable asignada a la medida correspondiente.
Resultado
Ahora solo nos queda añadir la columna NombreMedida
en forma de slicer a nuestro informe, y la medida MedidaVariable
al área de valores de nuestra visualización principal.
Ya tenemos resuelto el problema y es el propio usuario el que puede seleccionar la medida que quiere ver evaluada en una visualización bajo el contexto de filtro actual.
Si queremos que la visualización muestre una medida por defecto en caso de que el usuario no haya seleccionado ninguna o haya seleccionado más de una, podemos introducir en el tercer parámetro de la función IF()
, la medida (o la variable correspondiente) deseada. Por ejemplo, si queremos que la medida por defecto sea VentasTotales
, el código de MedidaVariable
sería:
MedidaVariable =
VAR Ventas = [VentasTotales]
VAR Costes = [CostesTotales]
VAR Devoluciones = [DevolucionesTotales]
VAR RentabilidadUSD = [Rentabilidad]
VAR RentabilidadPorcent = [Rentabilidad%]
VAR PesoRelativo = [PesoContinente]
VAR SeleccionMedida =
MIN ( SelecMedida[CodMedida] )
RETURN
IF (
HASONEVALUE ( SelecMedida[NombreMedida] );
SWITCH (
SeleccionMedida;
1; Ventas;
2; Costes;
3; Devoluciones;
4; RentabilidadUSD;
5; RentabilidadPorcent;
6; PesoRelativo
);
[VentasTotales]
)
Podemos añadir también cualquier otro atributo a la página del informe, que proporcione la capacidad al usuario de modificar el contexto de filtro bajo el que se evaluará la fórmula de la medida seleccionada. Por ejemplo vamos a añadir un gráfico de barras apiladas con el canal de venta y la subcategoría de producto, y un nuevo slicer con la categoría de producto:
Como vemos, este pequeño truco nos abre la puerta a un sin fin de posibilidades a la hora de configurar nuestros informes y nos aporta una inmensa flexibilidad en el diseño de los mismos, algo que personalmente aprecio mucho. En una sola página podemos tener un análisis interactivo muy completo con varias métricas y distintos escenarios sobre los que evaluarlas.
Todo el código DAX de este artículo ha sido formateado con «DAX Formatter»
arles flores blandon
Hola.
Muchas gracias por la publicacion de este articulo, me aclaro muchas dudas…
estoy intentanto replicar la idea de las medidas dinamicas solo que en el Switch me da un error:
/*
MedidaVariable =
Var Segundos = [PromedioSegundos]
Var Horas =[PromedioHoras]
Var Minutos = [PromedioMinutos]
Var SeleccionMedida = Min(SelectMedida[CodMedida])
return
if(
HASONEVALUE(SelectMedida[NombreMedida]),
SWITCH(SeleccionMedida,
1,Segundos,
2,Horas,
3,Minutos )
)
*/
me indica un error: la sintaxis de ‘Segundos’ es incorrecta…
si coloco los numeros asi: «1» se soluciona el error de sintaxis pero luego indica que el case no admite valores no numericos.
Gracias por la ayuda