En mi empleo como consultor BI con Tableau he escuchado mucho la frase “Tableau no es un ETL” donde me ha tocado estar de acuerdo la mayor parte del tiempo. Independientemente de los recientes cambios que Tableau ha aplicado a su producto Tableau Desktop para mejorar el rendimiento con grandes volúmenes de datos, en la mayoría de los casos es necesario agregar un proceso de ETL como Talend o Pentaho previo al análisis y creación de reportes con Tableau Desktop. Conscientes de esto último, el año pasado (2018) Tableau libera al público el producto Tableau Prep Builder con la intención de brindar una herramienta Drag & Drop previa a la exploración de datos con Tableau Desktop. Como consultor de esta herramienta me vi entonces en el deber de explorar su potencial, conocer sus ventajas y su capacidad real para evaluar si es viable ofrecer a los clientes usarlo dentro de sus proyectos BI. Para ello, me propuse replicar el proceso de limpieza que alguna vez realicé en Python al popular dataset del Titanic estando atento al punto en el que la herramienta pueda llegar a quedarse corta y si de verdad es lo suficientemente cumplidora como para aplicarla a un proyecto más grande. Contexto previo y especificaciones Como parte de mi aprendizaje en ciencia de datos participé en la popular competición de Kaggle “ Titanic: Machine Learning from Disaster” hace más de un año, para este proyecto realicé la limpieza del dataset y la predicción con Python integrándose con exploración y análisis del dataset en Tableau. El proyecto puede leerse en este link y replicar el trabajo en Python de la preparación de los datos en la versión 2019.3 de Tableau Prep Builder. A lo largo de este artículo intentaré explicar las funcionalidades generales de Tableau Prep pero enfocándose en la comparación del trabajo realizado en Python vs el flujo creado en la herramienta.
Sección 1: Cargar el dataset
Como en la mayor parte de los datasets de Kaggle, el proceso de limpieza inicia con la lectura del archivo CSV de entrenamiento. Se utiliza pandas para asegurarse que la estructura de los datos sea la correcta y conocer, usando la función describe(), estadísticas descriptivas del dataset tales como la cantidad de registros, los valores máximos y mínimos de cada columna, entre otras.
Lectura del dataset en Python
Todo esto, debido a la incorporación de un sofisticado motor estadístico en Tableau, que cuando se lanza analiza automáticamente todos los datos en nombre del usuario, trae posibles explicaciones de los factores más relevantes que están impulsando un punto de datos en particular.
Descripción del dataset
En Tableau Prep la conexión con fuentes de datos en archivos de texto plano es tan simple como en Pandas, además, posee los ya conocidos asistentes de conexión nativos en Tableau Desktop para una gran cantidad de servidores como Hadoop, Teradata, MySQL, BigQuery, entre otros.
Algunas de las conexiones disponibles en Tableau Prep
En este punto Tableau Prep empieza a mostrar algunas de sus características que nos permitirán ahorrar tiempo. En caso de poseer múltiples archivos con la misma estructura, es posible realizar un ‘Wildcard Union’ que con un solo click solucionaría las múltiples concatenaciones que requerirían en Pandas. También, una vez conectados a con los datos podemos definir una muestra para trabajar en el flujo. Esto con el fin de que cada proceso dentro del flujo tenga un mejor rendimiento, ya que de todas formas al terminar el flujo en Prep la limpieza se aplicará a la totalidad de los datos.
Opciones disponibles al momento de conectarse a una fuente en Tableau Prep
También encontramos que la información que se obtiene desde el describe() de Pandas puede encontrarse en el ‘Profile Pane’ de Tableau Prep, donde encontraremos una descripción resumida de cada campo y podremos contrastar con la estructura tabular original (e inclusive aprovechar los efectos visuales).
Sección 2: Limpieza de valores nulos
Decidir qué hacer con los registros donde hay campos con valores nulos es una de las tareas más comunes de la limpieza de datos. Para este paso, construí una función para poder visualizar la cantidad de registros nulos de cada campo y el porcentaje del total que estos representan (dato que puede consultarse en Prep desde el ‘Profile Pane’).
Pandas en Python vs Profile Pane en Tableau Prep
A partir de la información de los campos en nulo decidí eliminar la columna ‘Cabin’ por la alta cantidad de nulos (recomendado incluso por Tableau Prep también), eliminar los dos registros nulos de la columna ‘Embarked’ y rellenar los valores nulos de ‘Age’ con un valor arbitrario para transformarlos luego.
Replicar estas acciones en Tableau Prep fue sencillo, intuitivo y solo requirió de un par de clicks. (El cambio a la variable Age lo trabajé en un punto más adelante en el flujo)
A este punto en el proceso de limpieza con Python empiezo a analizar el dataset en Tableau y decidido, a partir de los resultados, aplicar distintas transformaciones a las variables. Cabe resaltar que desde Tableau Prep podemos cargar los cambios en Tableau Desktop en cualquier momento del flujo.
Sección 3: Transformación de columnas
La primera transformación a partir del análisis en Tableau Desktop fue la creación de un campo ‘Family Size’ que se compone de la suma de los campos ‘Parch’ y ‘SibSp’. Para replicar el comportamiento en Tableau Prep solo fue necesario crear un campo calculado cuya fórmula es: [SibSp] + [Parch] Y luego simplemente eliminar las columnas sobrantes en el menú.
El siguiente paso fue la extracción del título en cada nombre. Dado que el nombre del pasajero como tal no agrega ninguna información al modelo, decidí extraer su titulo (Mr, Miss, Mrs, etc.) con el que se puede generalizar más a los pasajeros. Esto requirió de tan solo un par de clicks en Tableau Prep.
Luego se hizo un agrupamiento en el que solo los títulos ‘Master’, ‘Miss’, ‘Mr’ y ‘Mrs’ se mantuvieran, el resto sería agrupado como ‘Other’.
Para este comportamiento Tableau Prep brinda varias opciones de agrupamiento (entre las que se incluye agrupar por similitud de las palabras e inclusive pronunciación parecida).
El siguiente paso de la limpieza es quizá el más complejo, apoyado de Tableau Desktop obtuve la edad promedio de cada título y completé los registros nulos del campo edad con dicho valor.
Para emular este comportamiento de forma automática en Tableau Prep requerí crear un campo con este valor promedio (usando un proceso de agregación de Tableau Prep) y luego integrarlo al dataset mediante un proceso join, finalmente creé un campo calculado copia del campo ‘Age’ que tomaba el valor del campo del promedio si el registro es nulo.
Procesos de agregación y join de Tableau Prep
La fórmula usada en el campo calculado fue:
IF ISNULL([Age]) THEN
[Average Age]
ELSE
[Age]
END
Finalmente, el proceso de transformación de columnas termina con la eliminación del campo con el ID del pasajero y el número de tiquete (Similar al paso de eliminación de Cabin).
Sección 4: Adaptación del dataset para modelado
Hasta este punto el dataset está limpio en su totalidad y puede ser utilizado para análisis de patrones y creación de reportes. Como se ha podido evidenciar, todos los pasos se pudieron realizar en un mínimo esfuerzo con un conjunto de clicks y Tableau Prep ha cumplido su funcionalidad (limpiar los datos antes de la creación de reportes con Tableau Desktop). En este punto se puede agregar un proceso de salida que aplicaría todos los cambios al dataset y exportará el resultado en formato CSV o como extracto de Tableau Desktop para crear reportes. Sin embargo, hacen falta dos transformaciones adicionales que dejarían el dataset listo para entrenar modelos (Transformar las variables categóricas en un formato numérico de 1 y 0 para finalmente normalizarlas). En mi experiencia no pude encontrar una forma con la que pudiera aplicar estas dos trasformaciones de forma nativa en Tableau Prep (o que no requiera muchisimos procesos adicionales) pero fui capaz de integrar un script personalizado de Python para responder a mi necesidad. En este punto de integración con Python (aunque también se puede integrar con R) fue donde encontré las mayores falencias de Tableau Prep y es donde realmente puede llegar a quedarse corto. Primero, para la integración es necesario utilizar la librería TabPy de configuración bastante sencilla, un bloc que ayuda mucho a entender cómo hacer la integración de Python/R a Tableau Prep se encuentra aquí. Introducing support for custom R and Python scripts in Tableau Prep flows In the example in this post, Anton explains how to configure Prep Builder to run Python scripts and show some of the… www.tableau.com Básicamente es necesario que el script tenga una función principal que recibirá por parámetro un dataframe de Pandas y en ella debemos realizar toda nuestra transformación. Esta función la vincularemos en el UI de Tableau Prep solo digitando su nombre. Sin embargo, la verdadera desventaja es que debemos obligatoriamente incluir la función get_output_schema() que le indicará a Tableau Prep la estructura con la que quedará nuestro dataset al finalizar el script. El problema con esto es que debemos crear casi que manualmente la estructura, tarea bastante tediosa si nuestro dataset tiene muchas columnas (con más de 20 ya sería inviable).
Tras incluir estos scripts al flujo fui capaz de cumplir mi requerimiento. Inclusive pude dividir el flujo para en cualquier momento generar la matriz de los campos independientes X y el vector columna con la variable dependiente Y.
Conclusiones
Llegando al final de este experimento la conclusión final que puedo sacar es que, a pesar de su poco tiempo disponible al público, Tableau Prep sería capaz de simplificar muchos procesos comunes y algunos más complejos que se suelen hacer en ETL o en un proyecto de ciencia de datos. Específicamente para este proyecto, con poco esfuerzo permitió replicar el trabajo de más de 100 líneas de código antes de requerir la utilización de scripts externos. En general, son muy buenas las sensaciones que deja Tableau Prep y definitivamente es una herramienta que merece la oportunidad en algún proyecto de la industria. Evidentemente quedó expuesto en qué momento su capacidad quedó corta y qué problemas podrían presentarse en su utilización.
Como una última ventaja cabe resaltar lo simple que es replicar un flujo a una fuente de datos con la misma estructura. En Python por ejemplo se necesitaría replicar el código y ajustar los nombres de las variables si queremos aplicar la misma transformación al dataset de pruebas, en Tableau Prep con solo copiar y pegar obtendríamos el mismo resultado.
Adicionalmente, es interesante el hecho de que los flujos puedan guardarse en un formato empaquetado que incluye los scripts y archivos necesarios para replicar el flujo en cualquier otro equipo con Tableau Prep.
En fin, definitivamente es una herramienta que recomiendo usar y darle una oportunidad y de la que personalmente me emociona ver que nuevas funcionalidades pueda incluir en sus siguientes versiones.