Cartografiar un millón de accidentes de tráfico: seis errores que solo se ven después de cometerlos
La tercera herramienta de este dominio es un mapa de calor de accidentes de tráfico. Los datos son públicos y parece que basta con descargarlos. Esto es lo que salió mal seis veces por el camino.
2026-08-20 作者 William Hsu
- Cómo son los datos
- 1. Una fila es una persona implicada, no un accidente
- 2. El mayor punto negro de Taiwán es la puerta del ayuntamiento de Nuevo Taipéi
- 3. Estos datos no sirven para ordenar «el cruce más peligroso»
- 4. Volver a pedir toda la pantalla en cada desplazamiento
- 5. La base de datos en un bind mount iba 74 veces más lenta
- 6. Los colores mal dos veces: una todo rojo, otra todo azul
- Al ampliar, los puntos formaban una rejilla regular
- Mirando atrás
Cómo son los datos
La Agencia Nacional de Policía de Taiwán publica los accidentes con víctimas caso por caso en el portal de datos abiertos: el tipo A1 son fallecimientos en 24 horas y el A2 heridos o fallecidos pasadas 24 horas. Usé los años completos de 2024 y 2025 más los datos móviles de 2026 hasta agosto.
- Filas originales 2.287.215
- Columnas 51, con coordenadas, meteorología, luz, límite de velocidad, señalización, causa determinada y la edad y protección de cada implicado
- Periodo enero de 2024 a agosto de 2026, 32 meses
La descarga es un zip; tres años descomprimidos son 1,5 GB. Mi disco no daba, así que toda la cadena lee directamente del zip sin escribir nada.

1. Una fila es una persona implicada, no un accidente
Un accidente tiene tantas filas como implicados. Un coche que choca con una moto son dos filas con la misma hora, lugar y coordenadas; solo cambia el número de implicado.
Al deduplicar los 2,28 millones de filas quedan 1,01 millones de accidentes, con una media de 2,26 implicados. Contar filas directamente infla todas las cifras por más del doble.
2. El mayor punto negro de Taiwán es la puerta del ayuntamiento de Nuevo Taipéi
La primera vez que dibujé los datos, el punto más brillante estaba en Banqiao, Nuevo Taipéi, en 121.481, 25.009: más de dos mil accidentes al año amontonados en un solo sitio.
Esas son las coordenadas del gobierno de Nuevo Taipéi. Cuando la geocodificación falla, el sistema recurre a un valor por defecto, y ese valor es la sede del gobierno de ese municipio. Las direcciones acumuladas en ese punto abarcan 20 distritos: Sanxia, Bali, Pinglin y más.
Detectarlo es sencillo: si las direcciones de una misma coordenada abarcan tres o más distritos, el punto es falso. Un cruce real no puede estar en Sanxia y en Bali a la vez. En todo el país aparecieron 128 puntos así y 17.784 accidentes, el 1,76% del total.
No es mucho en proporción, pero como cae todo en el mismo sitio se convierte en la mancha más grande del mapa. Sin corregirlo, lo más llamativo del mapa es un error.
3. Estos datos no sirven para ordenar «el cruce más peligroso»
Esto no va de programación, es la naturaleza del dato.
Taichung es la ciudad con más accidentes del país, 70.765 al año. Pero entre los 200 mayores puntos negros nacionales, Nuevo Taipéi se lleva 121 y Taichung solo 19.
El motivo es que cada municipio geocodifica de otra manera. La tasa de reutilización de una misma coordenada es 1,38 en Nuevo Taipéi y 1,01 en la ciudad de Taipéi. Allí casi cada accidente tiene coordenada propia, así que nunca puede formarse un «punto negro».
Cualquier ranking de cruces peligrosos hecho con estos datos ordena el comportamiento de geocodificación de cada municipio, no el peligro. Por eso la herramienta no tiene tabla de clasificación, solo estadísticas por zona: en un radio de 300 a 500 metros, un error de coordenadas de unas decenas de metros se diluye.
Además, el 26,2% de las direcciones dicen «a 0,0 metros delante de la calle X», que es el punto de referencia de un tramo, no el lugar del accidente. A nivel de calle se puede interpretar; a nivel de cruce no.
4. Volver a pedir toda la pantalla en cada desplazamiento
La primera API recibía un bbox: el front-end enviaba los límites del mapa y el back-end devolvía esa zona. Funcionaba, pero mover el mapa un píxel genera otro bbox, otra URL y una recarga completa que ni el navegador ni la CDN pueden cachear. Una respuesta medida ocupaba 954 KB.
Al cortar el mapa en tiles (teselas) fijos, la URL pasó a ser /api/cells/{z}/{x}/{y}. Una URL fija se cachea, y al desplazarse solo se piden los tiles nuevos:
- Primera carga 12 tiles, 195 KB
- Desplazar 200 píxeles solo 3 tiles nuevos, unos 10 KB
- Volver atrás 0 peticiones, 14 milisegundos
5. La base de datos en un bind mount iba 74 veces más lenta
En desarrollo todo iba bien; en producción la misma consulta tardaba 5,5 segundos.
En producción la carpeta está montada (bind mount) desde el host Windows dentro del contenedor Docker. SQLite hace muchísimas lecturas pequeñas y aleatorias, y ese patrón es lentísimo sobre un bind mount. La misma consulta, de tres formas:
- Equipo de desarrollo, disco local 74 ms
- Contenedor leyendo el bind mount 5.500 ms
- Contenedor leyendo una copia local 84 ms
La solución es copiar la base de datos de forma secuencial al sistema de archivos del propio contenedor al arrancar y usar esa copia. La lectura secuencial es rápida: 122 MB tardan unos segundos. Este problema es invisible en la máquina de desarrollo y solo aparece tras desplegar.
6. Los colores mal dos veces: una todo rojo, otra todo azul
Los pesos de un mapa de calor son relativos, así que cómo se convierte el número de accidentes en un peso de 0 a 1 decide cómo se lee el mapa entero.
El primer intento fue todo rojo: al pasar la API de bbox a tiles dejé fuera el campo del peso. El front-end no lo veía, lo interpretaba como indefinido y asignaba el peso máximo a cada celda, aunque tuviera 1 accidente o 300.
El segundo fue todo azul: usé el percentil 97 como valor máximo. Pero esta distribución está enormemente sesgada: a vista nacional la celda mediana tiene 38 accidentes y la mayor 15.601, un factor de 400. Con el percentil 97 como denominador, el 97% de las celdas queda casi en cero.
La versión final toma el logaritmo respecto al máximo. La celda mediana se queda en 0,38, una de quinientos en 0,64 y la mayor en 1,0; así por fin se despliega la franja intermedia.
Al ampliar, los puntos formaban una rejilla regular
Alguien avisó de que a nivel de calle los puntos se veían sospechosamente regulares y no encajaban con las carreteras.
Porque estaba dibujando el centro de cada celda. Dibuja el centro de una celda de 13 metros y a nivel de calle se ve la rejilla, y las carreteras, claro, no pasan por el centro de todas las celdas.
La solución fue reconstruir la base de datos guardando también la suma de las coordenadas de los accidentes de cada celda, para que la consulta devuelva su centro de masas real. Ahora los puntos caen sobre las carreteras y siguen la red viaria.
Mirando atrás
De los seis, solo el cuarto y el quinto eran problemas técnicos; el resto vino de suponer que los datos estaban limpios. Los datos abiertos del gobierno son en realidad buenos —campos detallados, actualizaciones diligentes— pero están diseñados para uso administrativo, y ese uso no es dibujar mapas. Las coordenadas se añadieron después, mediante un proceso con su propia lógica, y esa lógica es inofensiva en estadística y letal en un mapa.
La próxima vez que reciba un conjunto de datos abiertos, iré a mirar de dónde salen los valores más extremos antes de dibujar nada.