Centralización de datos de viajes de taxi de NYC desde una API REST paginada hacia un warehouse local estructurado, permitiendo reportes analíticos interactivos sobre patrones de tarifas, comportamiento de propinas y demanda temporal — reduciendo la fricción entre la disponibilidad de datos crudos y el consumo de insights de negocio.
Arquitectura y Stack
- Ingesta →
dltcon una clase personalizadaQueryParamPaginatorque obtiene registros JSON paginados desde un endpoint de API REST - Almacenamiento → DuckDB (archivo local
taxi_pipeline.duckdb, datasetnyc_taxi_data) - Transformación y Análisis → Ibis (motor de consultas DuckDB) y Pandas para agregaciones a nivel columna, filtrado y métricas derivadas (porcentaje de propina, agrupación por hora)
- Visualización / BI → Notebook reactivo Altair + Marimo (5 gráficas interactivas: histograma, dispersión, barras, líneas, mapa de calor)
- Entorno →
uvconuv.lockcongelado; Python 3.14 fijado vía.python-version
Logros Técnicos Clave
Motor de paginación personalizado — Se implementó una clase QueryParamPaginator que extiende el BasePaginator de dlt, manejando paginación de API basada en páginas con terminación elegante ante respuestas vacías — previniendo bucles infinitos y asegurando una extracción confiable del dataset completo a través de las páginas de la API.
Código modular y entornos reproducibles — Separación de responsabilidades entre módulos distintos (taxi_pipeline.py para ingesta, taxi_insights_marimo.py para analítica); dependencias gestionadas con uv y un lock file versionado que garantiza builds reproducibles bit a bit.
Tabla de hechos append-only con inferencia de esquema — dlt infiere y evoluciona automáticamente el esquema de nyc_taxi_trips a partir de payloads JSON crudos, escribiendo en una única tabla de hechos desnormalizada lista para evolucionar hacia un modelo dimensional.
Controles de calidad de datos en consulta — Validación a nivel de valor en la capa de transformación: filtros fare_amt > 0 y tip_amt >= 0 excluyen registros corruptos; trip_distance <= 20 limita valores atípicos para precisión del histograma; las gráficas de dispersión se limitan a 2,000 filas muestreadas por rendimiento de renderizado.