Del dato crudo a la visualización interactiva en Tableau Public
Diagnóstico post-entrenamiento, pipeline de datos, migración y automatización
De boletines epidemiológicos a un dashboard interactivo embebido en la web
Tras la fase de entrenamiento, las fechas futuras desaparecían al filtrar por entidad o padecimiento en Tableau. La persistencia del error incluso en vistas simplificadas reveló que el defecto no era visual sino estructural: estaba en la integración de datos aguas abajo del entrenamiento. El diagnóstico completo, la reconstrucción del pipeline y la migración a un dataset único (tableau.csv) constituyen el núcleo de este reporte.
Pipeline completo: desde SINAVE hasta Tableau Public
El pipeline fallaba por inconsistencias en el dataset, no por Tableau
Se detectaron duplicados reales en el histórico INEGI en fechas específicas (2014-12-29 y 2025-12-29) por colisión entre Semana 53 y Semana 1. Esto rompía la unicidad esperada para los joins y provocaba filas fantasma que desaparecían al filtrar.
Se decidió no inventar datos: no rellenar yhat donde no existe, no mezclar valores reales con forecast, y mantener NaN como ausencia real de información. El dataset se construye con outer join y una validación mínima correcta: prohibir NaN solo en llaves críticas.
Al expandir el histórico a general/hombres/mujeres, se evitó inflar SUM(Incrementos_*) en Tableau dejando poblado solo el incremento correspondiente al modo y poniendo NaN en los otros dos. Así, filtrar por meta_modo=hombres solo cuenta hombres.
build_tableau.py8 pasos para construir el dataset integrado de visualización
La llave compuesta del dataset final es:
meta_modo indica la segmentación por sexo: general (ambos sexos), hombres o mujeres. Cada combinación de padecimiento, entidad y modo genera un modelo independiente.
El pipeline exige unicidad por esta llave en ambas entradas (histórico expandido y forecast) antes de hacer el merge. El merge es outer para no perder histórico ni forecast, y se usa validate="m:1" para controlar cardinalidad.
meta_modoEl campo meta_modo es la tercera dimensión de la llave compuesta que permite segmentar los datos y las predicciones por sexo. Cada valor genera un modelo Prophet independiente:
Ambos sexos combinados. Usa la columna incrementos_total del histórico. Es la vista por defecto del dashboard.
Solo población masculina. Usa la columna incrementos_hombres del histórico.
Solo población femenina. Usa la columna incrementos_mujeres del histórico.
Cada combinación padecimiento × entidad × meta_modo genera un modelo Prophet independiente. Esto significa que Jalisco-Depresión produce 3 modelos distintos, cada uno entrenado con su propia serie de incidencia.
expand_real_by_modo): La función expand_real_by_modo() triplica el histórico INEGI generando una fila por cada modo. Solo el incremento correspondiente al modo queda poblado; los otros dos se dejan como NaN. Esto permite que Tableau filtre por meta_modo sin inflar las sumas agregadas (SUM(incrementos_*)).
Ejemplo: una sola fila de Jalisco-Depresión en el histórico se expande en 3 registros independientes:
| padecimiento | entidad | meta_modo | y_real | Modelo Prophet (.pkl) |
|---|---|---|---|---|
Depresión |
Jalisco |
general | incrementos_total |
Prophet_Depresion_Jalisco_general.pkl |
Depresión |
Jalisco |
hombres | incrementos_hombres |
Prophet_Depresion_Jalisco_hombres.pkl |
Depresión |
Jalisco |
mujeres | incrementos_mujeres |
Prophet_Depresion_Jalisco_mujeres.pkl |
| Paso | Función | Descripción |
|---|---|---|
| A | load_inputs() | Lee data_inegi_General.csv (histórico INEGI) y all_forecast.csv (predicciones) |
| B | prepare_inputs() | Parsea Fecha→ds, mapea columnas del forecast, elimina fechas inválidas |
| C | Fix Semana 53 | Desambigua 2014-12-29 y 2025-12-29 prefiriendo Semana 53 sobre Semana 1 |
| D | expand_real_by_modo() | Triplica histórico en 3 modos; solo el incremento correspondiente queda poblado |
| E | Validación de duplicados | Verifica unicidad en [ds, padecimiento, entidad, meta_modo] en ambas entradas |
| F | outer merge | Join histórico + forecast por las 4 llaves, validate="m:1" |
| G | RMSE por modelo | Calcula RMSE solo donde coexisten y_real y yhat |
| H | Escritura | Renombra, fill numérico (excluyendo incrementos), valida llaves, escribe tableau.csv |
Trazabilidad completa del fallback híbrido en predice.py
Para los 256 modelos con confianza suficiente, archivo_modelo_original y archivo_modelo_usado apuntan al mismo .pkl. Las métricas original y usado son idénticas.
Para los 41 modelos insuficientes, el forecast viene del modelo regional pero se desnormaliza con la población estatal individual. Las métricas se desdoblan:
rmse_original, mase_original — del modelo estatal propiormse_usado, mase_usado — del modelo regional fallbackconfianza_original = "insuficiente"confianza_usado = "suficiente"297 modelos estatales + 15 regionales de fallback
Embebidas en EpiDashboard.html via Tableau Public JavaScript API
De dos fuentes fragmentadas a un único tableau.csv con llave homogénea
tableau.csv con llave compuestaLa migración no fue un simple "cambiar fuente": requirió reconstruir sistemáticamente múltiples componentes:
Todas las hojas apuntadas al nuevo CSV con tipos validados
Condiciones logicas basadas en meta_modo, WINDOW_* revisadas
SUM, AVG, FIXED recalibrados para evitar duplicaciones
Globales remapeados, acciones de resaltado verificadas
Diseño centrado en interpretabilidad, no en decoración
Línea de referencia COVID-19 y ajuste a fecha continua (condición necesaria para bandas en Tableau). Títulos con referencias temporales claras sin sobrecargar.
Clasificación interpretable: Excelente (<0.7), Bueno (0.7-1.0), Mejora (>1.0). El usuario entiende sin interpretar la métrica cruda.
RMSE, MAE, MAPE, MASE y modelo utilizado bajo demanda. La visualización principal queda limpia; el detalle técnico aparece al hover.
Worksheets de predicciones y desempeño se integraron en un único dashboard "Predicciones" con una nueva worksheet "KPIs" (confianza + modelo Prophet).
Normalización min-max para variables con magnitudes muy diferentes (densidad, superficie, casos). El gradiente de color es consistente al alternar variables.
52 semanas históricas + 52 proyectadas. Controlada por parámetro de selección única (workaround a limitación de Tableau). En desarrollo
Tres avances iterativos: de tablas básicas a un pipeline integrado
Primeras 5 visualizaciones: tabla de datos interactiva, mapa de México, vista por categorías, casos anuales y semanales. Dashboard ejecutivo comparativo con los 3 padecimientos. Modelo baseline Prophet con cross-validation temporal.
Se implementó normalización min-max para mapas con variables de magnitudes dispares. Modelo expandido a nivel estatal (99 modelos por padecimiento). Dashboard integral con heatmaps y bump charts de rendimiento.
Diagnóstico post-entrenamiento, corrección de Semana 53, política de NaN explícitos, contrato de llaves, expansión por modo, build_tableau.py. Migración a dataset único. Experimento de automatización GitHub Actions → Google Sheets → Tableau Public.
Crecimiento acumulativo de funcionalidad
Validación del principio pipeline → publicación → consumo
Service account de Google Cloud como identidad técnica. Credenciales en GitHub Secrets (no versionadas). El Sheet se comparte con el correo de la service account.
| Componente | Responsabilidad |
|---|---|
| Google Cloud / IAM | Control de acceso |
| GitHub Actions | Ejecución automatizada |
| Google Sheets | Persistencia de datos |
La escritura a Google Sheets funciona correctamente en cada ejecución. La incertidumbre está en el lado de Tableau Public: no ofrece control sobre triggers ni schedules de refresh.
Excelente para difusión, no diseñada como plataforma de automatización
| Producto | Costo aprox. | Refresh programado | Uso principal |
|---|---|---|---|
| Tableau Public | Gratis | Solo Google Sheets (~1x/día) | Publicación abierta |
| Tableau Desktop | ~70 USD/mes | No | Desarrollo y autoría |
| Tableau Cloud (Creator) | ~75 USD/mes | Sí | Desarrollo + publicación |
| Tableau Cloud (Explorer) | ~42 USD/mes | Sí | Exploración interactiva |
| Tableau Cloud (Viewer) | ~15 USD/mes | Sí | Consumo de dashboards |
viz_epiforecastmx.twb.
Del diagnóstico del Avance 4 al estado actual del pipeline
Los errores en Tableau no se resolvieron con ajustes visuales. El problema estaba en la estructura del dataset. Los NaN no son errores: son semántica. La visualización es consecuencia de datos bien construidos.
Definir un contrato explícito de llaves (ds, padecimiento, entidad, meta_modo) y validarlo con validate="m:1" previene errores silenciosos que solo se manifiestan en producción.
El desdoblamiento original vs usado en métricas permite auditar exactamente qué modelo generó cada predicción. Con 41 modelos en fallback, la transparencia es crítica.
make tableau es un único comando que genera el dataset final. Cualquier miembro del equipo puede reconstruir tableau.csv desde cero en cualquier momento.
tableau.csvColumnas clave agrupadas por propósito
Resumen de scripts, archivos y comandos del pipeline de visualización
| Componente | Archivo / Comando | Propósito |
|---|---|---|
| Predicción | scripts/predice.py / make predict | Genera all_forecast.csv con yhat + métricas orig/usado |
| Dataset Tableau | scripts/build_tableau.py / make tableau | Integra histórico + forecast en tableau.csv |
| Workbook | viz/viz_epiforecastmx.twb | 8 visualizaciones interactivas en Tableau |
| Web embed | EpiDashboard.html | Página web con embeds Tableau Public JS API |
| Automatización | hourly.yml + update_sheet.py | Experimento GitHub Actions → Google Sheets |
| Notebook | notebooks/Avance4_Luis_Reconstruido.ipynb | Documentación completa del proceso (6 secciones) |