status · livebuild 2026.06.04
3 DE JUNIO DE 2026·9m read
GeoAIAnálisis espacialGeoParquetArcGIS Maps SDKColombiaElecciones

Colombia votó. Esto cuenta el territorio.

Cómo leí la primera vuelta presidencial municipio a municipio —1.121 historias, no dos colores— y qué aprendí construyendo un visor electoral cloud-native con GeoParquet, análisis espacial y ArcGIS Maps SDK.

Colombia votó. Esto cuenta el territorio.

Cómo leí la primera vuelta municipio a municipio — y qué aprendí construyéndolo.

Los mapas electorales que circularon estos días responden una sola pregunta: ¿quién va ganando?

Y esa, casi siempre, es la menos interesante.

Son mapas exploratorios y departamentales: promedian y esconden. Colombia tiene 1.121 municipios, y el nivel departamental los aplana a todos en un solo color. La pregunta que a mí me obsesiona es otra: ¿qué cuenta el territorio cuando bajas de resolución y le aplicas análisis espacial en serio?

Así que lo construí. Pero aunque el resultado sea un visor electoral, lo que de verdad quiero compartirte no es el "mira lo que hice" — es lo que aprendí en el camino. Porque si trabajas con datos del territorio, casi todo esto te sirve mañana.

El promedio nacional miente por omisión

A escala departamental, una capital que arrasa y un municipio a una hora de camino donde casi nadie votó terminan pintados del mismo color. Pero un departamento no vota: votan sus municipios, y dentro de uno mismo conviven realidades opuestas. Por eso traté la elección como lo que es — 1.121 historias distintas, no un país de dos colores.

Las fuentes, porque toda lectura honesta empieza ahí: el preconteo de la Registraduría Nacional (votos, censo, blancos y nulos por municipio) sobre la geometría oficial del MGN 2024 del DANE, simplificada con topología para aligerarla sin romper las fronteras compartidas entre vecinos. Ingesta y normalización en Python sobre un modelo estrella (territorio, candidato, resultado) — la diferencia entre un análisis reproducible y un Excel que nadie vuelve a entender en tres semanas.

La lección: la resolución no es un detalle estético. Bajar de departamento a municipio no "afina" el mapa: cambia la historia que cuenta.

Mapa a escala departamental: grandes bloques de color que promedian regiones enteras.Mapa a escala departamental: grandes bloques de color que promedian regiones enteras.

El mismo dato a escala municipal: 1.121 piezas donde afloran los contrastes internos.El mismo dato a escala municipal: 1.121 piezas donde afloran los contrastes internos.

La IA no reemplaza el criterio: lo amplifica

Seré transparente, porque es parte de lo que defiendo en GeoAI LATAM: no tecleé esto línea por línea en un fin de semana. Me apoyé en asistentes de IA con skills especializadas para el trabajo pesado — andamiar el pipeline de datos, generar y depurar las expresiones de Arcade, resolver el error de lectura de Parquet que cuento más abajo, y bosquejar análisis que luego validé contra los datos reales.

Lo importante es lo que la IA no hizo: decidir por mí. Saber qué pregunta hacerle al territorio, qué modelo tiene sentido y cuándo desconfiar de un resultado demasiado bonito sigue siendo trabajo de ingeniero. La IA me devolvió el tiempo para concentrarme justo en eso.

La lección: en geoespacial, ese es el uso que paga — delega la plomería, quédate con el criterio.

Un solo archivo para el notebook, la nube y el navegador

Todo el dataset vive en un GeoParquet de ~5,5 MB. El GeoJSON equivalente pesaría varias veces más. Es columnar y comprimido, con la geometría en WKB y metadatos estándar — y, sobre todo, se lee por rangos de bytes: la capa pide solo el pedazo que necesita, no el archivo entero.

Lo mejor es la interoperabilidad: el mismo archivo lo abren DuckDB, GeoPandas, pyarrow y el navegador, sin una sola conversión. Y ArcGIS Maps SDK 5.0 lo trae directo al cliente con ParquetLayer — render de los 1.121 municipios sin servidor de mapas detrás. Cero tiles, cero servicio publicado: el dato y el cliente, nada más.

El detalle que te ahorra horas: el lector beta de ParquetLayer pide un rango de bytes con end == filesize. El servidor de desarrollo local lo "clampa" y revienta la petición; el object storage en la nube lo tolera sin problema. En local fallaba misteriosamente, en producción funcionaba. Si te topas con eso, sírvelo desde object storage y sigue.

Arquitectura: GeoParquet en object storage → ParquetLayer → features en el cliente, sin map server en el medio.Arquitectura: GeoParquet en object storage → ParquetLayer → features en el cliente, sin map server en el medio.

La forma del mapa es un argumento

El mismo dato dice cosas distintas según cómo lo dibujes, y elegir mal no es un descuido estético: es mentir.

La coropleta —colorear municipios— es útil pero esconde una trampa: mide área, no personas. Los municipios enormes y despoblados dominan la pantalla y te hacen creer cosas que no son. El cartograma lo corrige: redimensiona el territorio por sus votantes reales, y la geografía del voto se reordena por completo — tres ciudades concentran el grueso, mientras el campo, inmenso en área, pesa mucho menos en las urnas. Y un mapa bivariado (ganador × intensidad del respaldo) recuerda que no es lo mismo ganar arrasando que ganar raspando.

Todo con renderers nativos del SDK: ClassBreaks y UniqueValue para coropletas y categorías, DotDensity (1 punto = 2.500 votos) y visual variables de tamaño para el cartograma.

La lección: antes de elegir un renderer, pregúntate qué estás midiendo de verdad. Si tu variable habla de personas, una coropleta por área te va a mentir.

Coropleta: cada municipio coloreado por ganador e intensidad del respaldo — mide área, no personas.Coropleta: cada municipio coloreado por ganador e intensidad del respaldo — mide área, no personas.

Cartograma: el territorio redimensionado por votantes reales; tres ciudades concentran el grueso del voto.Cartograma: el territorio redimensionado por votantes reales; tres ciudades concentran el grueso del voto.

Deja que la estadística te contradiga

Un mapa bonito muestra qué se ve. El análisis espacial dice qué significa — y, sobre todo, si lo que ves es un patrón real o simple ruido. Lo apliqué sobre la abstención, que terminó siendo la verdadera protagonista de la elección.

¿La abstención se parece a la de sus vecinos, o está regada al azar? El Moran's I dio 0,748: está fuertemente agrupada en el espacio, no es ruido. ¿Dónde están los focos significativos? El estadístico Getis-Ord Gi* los ubica con 95–99% de confianza, nítidos en la periferia —Pacífico y Amazonía— y diluidos en el altiplano cundiboyacense.

Pero el momento que más me enseñó fue otro. Lo intuitivo era explicar la abstención con variables internas del municipio: su tamaño, qué tan dividido está el voto. Lo modelé con una regresión y me dio un R² de 0,02. Casi nada. Y sin embargo, los residuos seguían agrupados en el espacio — el modelo se estaba perdiendo algo geográfico. Recién un modelo espacial, que incorpora lo que pasa en los municipios vecinos, capturó el patrón.

La traducción honesta: la abstención no se explica por lo que pasa dentro de cada municipio, sino por dónde está. Es estructural — distancias largas, puestos de votación lejanos, huellas del conflicto. Tiene que ver con qué tan fácil es, físicamente, llegar a la urna.

Si te llevas una sola idea de este post, que sea esta: cuando tu modelo no explica nada pero los residuos están agrupados, no es que "no haya señal" — es que la señal es espacial. (Stack: geopandas, pysal/esda, spreg, duckdb.)

Mapa de hotspots Gi* de la abstención: rojos en la periferia, azules en el altiplano.Mapa de hotspots Gi* de la abstención: rojos en la periferia, azules en el altiplano.

Un popup también puede contar una historia

Los popups del visor no son etiquetas estáticas: al tocar un municipio aparece el top-5 de candidatos de ese lugar, cada barra pintada con el color de su candidatura. Dos piezas lo hacen posible. Arcade, un lenguaje de expresiones que corre en el cliente y me deja clasificar, calcular y formatear al vuelo sin volver a pedir datos. Y popups con CustomContent, que reemplazan el popup genérico por contenido a medida. Le sumé hitTest + highlight para resaltar el municipio bajo el cursor, y un toque de bloom para la estética firefly del cartograma — los municipios brillando como luciérnagas sobre el fondo oscuro.

La lección: el popup es el rincón más desaprovechado de un mapa web. Con Arcade y CustomContent deja de ser una ficha y pasa a ser una mini-historia por cada feature.

El cartograma con el efecto bloom: la estética firefly sobre el fondo oscuro.El cartograma con el efecto bloom: la estética firefly sobre el fondo oscuro.

Un dashboard no es una historia

Tener los datos y los análisis no basta. La gente no recorre un tablero frío: recorre una historia. Por eso convertí todo en un scrollytelling de seis actos que se lee en menos de dos minutos, aunque nunca hayas tocado un mapa — de las dos fuerzas y los trece nombres, al área que distorsiona el voto, a la abstención y su geografía, al mosaico ideológico de un país que no está partido en dos, hasta los municipios donde la elección se define por nada.

El mapa es la herramienta; el territorio es lo que habla. La historia solo se asegura de que cualquiera pueda escucharlo.

No mentir con los datos es una decisión

Tres cosas que cuidé a conciencia, y que valen para cualquier proyecto de datos:

  • Distinguir las cifras. El 73,5% es el porcentaje de municipios donde la abstención superó al candidato más votado (824 de 1.121). La abstención nacional real fue del 41,5% sobre el censo. Son cosas distintas, y van rotuladas juntas para que nadie las confunda.
  • Área ≠ personas. Muestro coropleta y cartograma juntos, a propósito: para que veas el sesgo y su corrección.
  • Transparencia editorial. La clasificación por bloques (izquierda / centro / derecha) es una asignación del equipo, con su disclaimer y los shares crudos auditables. Esto es análisis descriptivo, no causal: te muestro qué pasó, con las cartas sobre la mesa, no por qué.

Un buen mapa no decora: convierte datos en entendimiento del territorio. Y hacerlo bien —reproducible, cloud-native y honesto— es justo lo que exploramos en GeoAI LATAM.

Los mapas no son para mostrar. Son para entender el territorio.

Explora el proyecto

  • Visor completo → el mapa municipio a municipio, con la historia en 6 actos, los rankings y las fichas por municipio.

Datos: preconteo de la Registraduría Nacional, primera vuelta presidencial 2026 (cifras no oficiales). Geometría: MGN 2024 (DANE). Proyecto independiente, de análisis descriptivo, sin filiación política. La clasificación por bloques ideológicos es editorial.

Cuéntame en los comentarios: ¿qué te cuenta a ti el mapa de tu región que el promedio nacional esconde?

// fin de la transmisión

¿Te gustó? Suscríbete y no te pierdas nada.

Suscribirme al newsletter
// 07 · newsletter · únete
— Una carta cada dos semanas

Únete a la red.

Experimentos, mapas, papers y proyectos que van aterrizando. Sin spam, sin algoritmos, sin tracking — solo el correo.

⌥ tu dato queda en buttondown · puedes desuscribirte en un click