El crecimiento de las ciudades y el aumento del parque automotor han hecho que la gestión del tráfico y la seguridad vial dependan cada vez más del análisis de grandes volúmenes de datos. En este contexto, las aplicaciones de navegación colaborativa como Waze se han consolidado como una fuente estratégica de información en tiempo real sobre accidentes, congestión, cierres de vías y peligros en la calzada. El ejercicio original analiza, para un día específico, la distribución temporal y espacial de estos eventos mediante técnicas de análisis geoespacial y minería de datos en R, apoyándose en librerías como leaflet, spatstat y terra para generar mapas interactivos y mapas de densidad que permiten identificar zonas críticas y patrones de riesgo en la ciudad.
El presente trabajo tiene como propósito replicar dicho ejercicio, siguiendo la metodología CRISP-DM para garantizar un proceso sistemático y reproducible. A partir de los datos de Waze, se llevará a cabo la carga, limpieza y preparación de la base; posteriormente, se desarrollará un análisis descriptivo y temporal de los eventos, seguido de un análisis espacial que incluye la construcción de mapas interactivos y mapas de calor para los distintos tipos de incidentes (PELIGRO, CONGESTIÓN, ACCIDENTE y VÍA CERRADA). Esta replicación no solo busca reproducir los resultados originales, sino también consolidar el uso de herramientas de ciencia de datos y análisis geoespacial para apoyar la planificación urbana y la toma de decisiones en movilidad.
El análisis temporal permite identificar en qué horas del día 26 se concentran más eventos, facilitando la detección de patrones como horas pico de congestión o momentos con mayor ocurrencia de accidentes.
# Cargar la librería lubridate
library(lubridate)
# Convertir la fecha y extraer la hora y el día
fecha_hora = ymd_hms(Trama_Waze$creation_Date)
hora = hour(fecha_hora)
dia = day(fecha_hora)
# Agregar la columna de hora a los datos
Trama_Waze$hora = hora
# Mostrar la tabla de frecuencia de tipos de eventos
table(Trama_Waze$tipo_evento)##
## ACCIDENTE CONGESTIÓN PELIGRO VÍA CERRADA
## 125 3205 719 1021
El análisis descriptivo permite identificar qué tipos de eventos son más frecuentes en Waze, mostrando su distribución mediante un gráfico de barras que ayuda a priorizar los problemas de tráfico que requieren mayor atención.
# Calcular la frecuencia de cada tipo de evento en Trama_Waze
frecuencia_eventos <- Trama_Waze %>%
group_by(tipo_evento) %>% # Agrupar por tipo de evento
summarise(Frecuencia = n()) %>% # Contar la frecuencia de cada tipo
arrange(desc(Frecuencia)) # Ordenar por frecuencia descendente
# Crear un gráfico de barras con ggplot2 usando los datos de Trama_Waze
ggplot(frecuencia_eventos, aes(x = tipo_evento, y = Frecuencia, fill = tipo_evento)) +
geom_bar(stat = "identity") +
theme_minimal() +
labs(title = "Distribución de Tipos de Eventos en Trama Waze",
x = "Tipo de Evento", y = "Frecuencia") +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) + # Rotar etiquetas para mejor visualización
scale_fill_brewer(palette = "Set2") # Utilizar una paleta de colores predefinidaLa gráfica evidencia que la congestión es, por amplio margen, el evento más reportado, superando los 3.000 registros. Le siguen los cierres de vías y los peligros en la vía, con frecuencias intermedias, mientras que los accidentes son relativamente pocos en comparación con las demás categorías. Esto sugiere que la principal problemática de movilidad reportada por los usuarios es la congestión, y que los esfuerzos de gestión del tráfico deberían centrarse prioritariamente en las zonas donde estos embotellamientos son más recurrentes.
# Identificar eventos PELIGRO del día 26
pos <- which(Trama_Waze$tipo_evento == "PELIGRO" & dia == 26)
peligro26 <- Trama_Waze[pos,]Este mapa permite explorar las ubicaciones exactas de los peligros reportados, representando los eventos sobre un mapa geográfico y agrupándolos en clusters para mejorar la legibilidad.
# Cargar librerías necesarias para visualización
library(mapview)
library(leaflet)
# Ajustar las coordenadas de latitud y longitud
peligro26$lat <- peligro26$location_y / 10^(nchar(peligro26$location_y) - 1)
peligro26$long <- peligro26$location_x / 10^(nchar(peligro26$location_x) - 3)
# Filtrar eventos dentro del rango geográfico adecuado
peligro26 <- peligro26[peligro26$lat > 4 & peligro26$lat < 5,]
# Crear un mapa interactivo con leaflet
m26_peligro <- leaflet() %>%
addTiles() %>%
addCircleMarkers(lng = peligro26$long, lat = peligro26$lat,
clusterOptions = markerClusterOptions(),
label = peligro26$hora) %>%
addControl(html = "<h3>Mapa de Riesgos</h3>", position = "topleft")
# Mostrar el mapa
m26_peligroEl análisis espacial de los eventos PELIGRO del día 26 permite identificar, mediante mapas de calor, las zonas donde estos riesgos se concentran, proporcionando información clave para la gestión del tráfico y la planificación urbana.
# Cargar las librerías necesarias
library(leaflet)
library(dplyr)
library(leaflet.extras)
# Filtrar datos relevantes de peligro26
peligro26 <- peligro26 %>%
filter(lat > 4 & lat < 5, long > -75 & long < -73) # Ajustar las coordenadas de interés
# Crear un mapa interactivo con leaflet y addHeatmap
leaflet(peligro26) %>%
addProviderTiles("OpenStreetMap") %>% # Añadir la capa base del mapa
addHeatmap(
lng = ~long, lat = ~lat, # Especificar las columnas de longitud y latitud
intensity = ~hora, # Intensidad opcional basada en la hora (o cualquier otra variable)
blur = 20, # Nivel de desenfoque del mapa de calor
max = 0.08, # Ajustar el valor máximo para la intensidad
radius = 15 # Radio de cada punto en el mapa de calor
) %>%
addLegend("bottomright", # Añadir leyenda
title = "Mapa de Calor de Riesgos",
colors = c("blue", "green", "yellow", "red"),
labels = c("Bajo", "Moderado", "Alto", "Muy Alto"))Este mapa interactivo permite explorar geográficamente las áreas afectadas por los cierres de vías, proporcionando una herramienta visual poderosa para la planificación y gestión del tráfico en la ciudad.
# Filtrar eventos VÍA CERRADA del día 26
pos <- which(Trama_Waze$tipo_evento == "VÍA CERRADA" & dia == 26)
via_cerrada_26 <- Trama_Waze[pos,]
# Ajustar las coordenadas de latitud y longitud
via_cerrada_26$lat <- via_cerrada_26$location_y / 10^(nchar(via_cerrada_26$location_y) - 1)
via_cerrada_26$long <- via_cerrada_26$location_x / 10^(nchar(via_cerrada_26$location_x) - 3)
# Filtrar eventos dentro del rango geográfico adecuado
via_cerrada_26 <- via_cerrada_26[via_cerrada_26$lat > 4 & via_cerrada_26$lat < 5,]# Cargar librería leaflet
require(leaflet)
# Crear el mapa interactivo
m26_via_cerrada = leaflet(via_cerrada_26) %>%
addTiles() %>%
addCircleMarkers(lng = ~long, lat = ~lat,
clusterOptions = markerClusterOptions(),
label = ~hora) %>%
addControl(html = "<h3>Mapa de Cierre de Vías<h3>", position = "topleft")
# Mostrar el mapa interactivo
m26_via_cerrada# Cargar las librerías necesarias
library(spatstat)
# Definir la zona de interés
zona <- owin(xrange = c(-74.04331, -73.9929), yrange = c(4.885736, 4.948562))
# Crear un patrón de puntos espaciales a partir de los eventos VÍA CERRADA
patron_via_cerrada <- ppp(x = via_cerrada_26$long, y = via_cerrada_26$lat, window = zona)
# Graficar el test de cuadrantes
plot(quadratcount(patron_via_cerrada), main = "Patrón de Puntos y Test de Cuadrantes")
# Superponer los puntos sobre los cuadrantes
points(patron_via_cerrada, col = "red")La gráfica del Patrón de Puntos y Test de Cuadrantes muestra una distribución altamente concentrada de los eventos en solo dos cuadrantes, mientras que el resto permanece vacío. En particular, un cuadrante contiene 21 eventos y otro concentra 636 eventos, evidenciando una acumulación extrema en zonas muy específicas del área analizada.
# Gráfico independiente: Función K-Estimación
plot(Kest(patron_via_cerrada), main = "Función K-Estimación")La Función K-Estimación permite evaluar si los puntos (cierres de vía) siguen un patrón aleatorio, disperso o agrupado. En la gráfica, la curva observada (las líneas negra, roja y verde según la corrección usada) se compara con la curva teórica de un proceso de Poisson (línea azul), que representa una distribución completamente aleatoria.
Los cierres de vías no están distribuidos aleatoriamente, sino que presentan clústeres o concentraciones específicas dentro del área de estudio, reforzando lo que se observó también en el test de cuadrantes.
El uso de este mapa es clave para comprender la severidad de los cierres de vías en ciertas áreas de la ciudad y cómo pueden afectar la movilidad en general.
# Cargar las librerías necesarias
library(terra)
library(leaflet)
library(spatstat)
# Asegurarse de que el objeto patron_via_cerrada esté correctamente definido
# Crear un patrón de puntos espaciales utilizando los datos correctos (via_cerrada_26)
zona <- owin(xrange = c(-74.04331, -73.9929), yrange = c(4.885736, 4.948562))
patron_via_cerrada <- ppp(x = via_cerrada_26$long, y = via_cerrada_26$lat, window = zona)## Warning: data contain duplicated points
# Calcular la densidad espacial
im1 <- density(patron_via_cerrada, sigma = 0.01) # Ajusta sigma según sea necesario
# Convertir la densidad a un objeto raster usando terra
mapa_via_cerrada <- rast(im1)
# Convertir el raster a data.frame para leaflet
df_via_cerrada <- as.data.frame(mapa_via_cerrada, xy = TRUE)
colnames(df_via_cerrada) <- c("long", "lat", "intensity")
# Normalizar los valores de intensidad entre 0 y 1
df_via_cerrada$intensity <- (df_via_cerrada$intensity - min(df_via_cerrada$intensity)) /
(max(df_via_cerrada$intensity) - min(df_via_cerrada$intensity))
# Crear un mapa interactivo usando leaflet
leaflet(df_via_cerrada) %>%
addProviderTiles("OpenStreetMap") %>% # Añadir la capa base
addHeatmap(
lng = ~long, lat = ~lat, # Coordenadas de longitud y latitud
intensity = ~intensity, # Intensidad normalizada
blur = 20, # Nivel de desenfoque
max = 1, # Valor máximo de la intensidad normalizada
radius = 15 # Radio para reflejar la densidad
) %>%
addLegend("bottomright", # Añadir la leyenda
title = "Mapa de Calor de Cierres de Vías",
colors = c("blue", "green", "yellow", "red"),
labels = c("Bajo", "Moderado", "Alto", "Muy Alto"))El análisis de accidentes es crucial para identificar áreas peligrosas y planificar medidas de seguridad vial, como la instalación de señalización adicional o la mejora de la infraestructura vial en zonas críticas.
# Filtrar eventos de accidentes del día 26
pos <- which(Trama_Waze$tipo_evento == "ACCIDENTE" & dia == 26)
accidente_26 <- Trama_Waze[pos,]
# Ajustar las coordenadas de latitud y longitud
accidente_26$lat <- accidente_26$location_y / 10^(nchar(accidente_26$location_y) - 1)
accidente_26$long <- accidente_26$location_x / 10^(nchar(accidente_26$location_x) - 3)
# Filtrar eventos dentro del rango geográfico adecuado
accidente_26 <- accidente_26[accidente_26$lat > 4 & accidente_26$lat < 5,]# Cargar librerías necesarias
library(leaflet)
# Crear el mapa interactivo
m26_accidente <- leaflet(accidente_26) %>%
addTiles() %>%
addCircleMarkers(lng = ~long, lat = ~lat,
clusterOptions = markerClusterOptions(),
label = ~hora) %>%
addControl(html = "<h3>Mapa de Accidentes</h3>", position = "topleft")
# Mostrar el mapa interactivo
m26_accidente# Cargar las librerías necesarias
require(spatstat)
# Definir la zona de interés
zona = owin(xrange = c(-74.04331, -73.9929), yrange = c(4.885736, 4.948562))
# Crear un patrón de puntos espaciales a partir de los eventos ACCIDENTE
patron_accidente = ppp(x = accidente_26$long, y = accidente_26$lat, window = zona)
# Gráfico combinado: Test de Cuadrantes y Patrón de Puntos
par(mfrow = c(1, 1)) # Asegurarse de que solo haya una gráfica
# Graficar el test de cuadrantes
plot(quadratcount(patron_accidente), main = "Patrón de Puntos y Test de Cuadrantes")
# Superponer los puntos sobre los cuadrantes
points(patron_accidente, col = "red" )El uso de mapas de densidad en el análisis de accidentes es crucial para visualizar las áreas más afectadas y planificar intervenciones que mejoren la seguridad vial. Este tipo de visualización permite observar patrones espaciales que pueden no ser evidentes a través de simples tablas de datos.
# Cargar las librerías necesarias
library(terra)
library(leaflet)
library(spatstat)
# Asegurarse de que el objeto patron_accidente esté correctamente definido
# Usar las coordenadas correctas de los accidentes
zona <- owin(xrange = c(-74.04331, -73.9929), yrange = c(4.885736, 4.948562))
patron_accidente <- ppp(x = accidente_26$long, y = accidente_26$lat, window = zona)
# Calcular la densidad espacial
im1 <- density(patron_accidente)
# Convertir la densidad a un objeto raster usando terra
mapa_accidente <- rast(im1)
# Convertir el raster a data.frame para leaflet
df_accidente <- as.data.frame(mapa_accidente, xy = TRUE)
colnames(df_accidente) <- c("long", "lat", "intensity")
# Normalizar los valores de intensidad entre 0 y 1
df_accidente$intensity <- (df_accidente$intensity - min(df_accidente$intensity)) /
(max(df_accidente$intensity) - min(df_accidente$intensity))
# Crear un mapa interactivo usando leaflet
leaflet(df_accidente) %>%
addProviderTiles("OpenStreetMap") %>% # Añadir la capa base
addHeatmap(
lng = ~long, lat = ~lat, # Coordenadas de longitud y latitud
intensity = ~intensity, # Intensidad normalizada
blur = 15, # Nivel de desenfoque
max = 0.5, # Valor máximo de la intensidad normalizada
radius = 10 # Ajustar el radio de los puntos
) %>%
addLegend("bottomright", # Añadir la leyenda para interpretar el mapa de calor
title = "Mapa de Calor de Accidentes",
colors = c("blue", "green", "yellow", "red"),
labels = c("Bajo", "Moderado", "Alto", "Muy Alto"))El análisis de la congestión del día 26 permite identificar dónde y cuándo se concentran los mayores problemas de tráfico, información clave para optimizar semáforos, rutas alternas y la gestión general de la movilidad urbana.
# Filtrar eventos de congestión del día 26
pos <- which(Trama_Waze$tipo_evento == "CONGESTIÓN" & dia == 26)
congestion_26 <- Trama_Waze[pos,]
# Ajustar las coordenadas de latitud y longitud
congestion_26$lat <- congestion_26$location_y / 10^(nchar(congestion_26$location_y) - 1)
congestion_26$long <- congestion_26$location_x / 10^(nchar(congestion_26$location_x) - 3)
# Filtrar eventos dentro del rango geográfico adecuado
congestion_26 <- congestion_26[congestion_26$lat > 4 & congestion_26$lat < 5,]# Cargar las librerías necesarias
library(leaflet)
# Crear el mapa interactivo
m26_congestion <- leaflet(congestion_26) %>%
addTiles() %>%
addCircleMarkers(lng = ~long, lat = ~lat,
clusterOptions = markerClusterOptions(),
label = ~hora) %>%
addControl(html = "<h3>Mapa de Congestión</h3>", position = "topleft")
# Mostrar el mapa interactivo
m26_congestionEl análisis espacial de la congestión del día 26 permite identificar patrones y zonas donde el tráfico se concentra, información clave para orientar mejoras en infraestructura y ajustes en las rutas para reducir la congestión.
# Cargar las librerías necesarias
library(spatstat)
# Definir la zona de interés
zona <- owin(xrange = c(-74.04331, -73.9929), yrange = c(4.885736, 4.948562))
# Crear un patrón de puntos espaciales a partir de los eventos CONGESTIÓN
patron_congestion <- ppp(x = congestion_26$long, y = congestion_26$lat, window = zona)
# Visualizar el patrón de puntos
par(mfrow = c(1, 1)) # Asegurarse de que solo haya una gráfica
# Graficar el test de cuadrantes
plot(quadratcount(patron_congestion), main = "Patrón de Puntos y Test de Cuadrantes")
# Superponer los puntos sobre los cuadrantes
points(patron_congestion, col = "red")El mapa de densidad de eventos de congestión del día 26 permite identificar visualmente las zonas donde el tráfico es más intenso, ofreciendo una herramienta clave para detectar puntos críticos y orientar acciones que mejoren la movilidad urbana.
# Cargar las librerías necesarias
library(leaflet)
library(terra)
# Definir el patrón de puntos
zona <- owin(xrange = c(-74.04331, -73.9929), yrange = c(4.885736, 4.948562))
patron_congestion <- ppp(x = congestion_26$long, y = congestion_26$lat, window = zona)
# Calcular la densidad espacial del patrón de puntos
im1 <- density(patron_congestion)
# Convertir la densidad en un raster utilizando terra
mapa_congestion <- rast(im1)
# Convertir el objeto raster a un data.frame para usarlo en leaflet
df_congestion <- as.data.frame(mapa_congestion, xy = TRUE)
colnames(df_congestion) <- c("long", "lat", "intensity")
# Normalizar los valores de intensidad entre 0 y 1
df_congestion$intensity <- (df_congestion$intensity - min(df_congestion$intensity)) /
(max(df_congestion$intensity) - min(df_congestion$intensity))
# Crear un mapa interactivo usando leaflet
leaflet(df_congestion) %>%
addProviderTiles("OpenStreetMap") %>% # Añadir la capa base
addHeatmap(
lng = ~long, lat = ~lat, # Coordenadas de longitud y latitud
intensity = ~intensity, # Intensidad normalizada
blur = 35, # Incrementar el desenfoque para suavizar el mapa
max = max(df_congestion$intensity) * 2, # Ajustar el valor máximo de intensidad
radius = 25 # Aumentar el radio para que se vea más suave
) %>%
addLegend("bottomright", # Añadir la leyenda para interpretar el mapa de calor
title = "Mapa de Calor de Congestión",
colors = c("blue", "green", "yellow", "red"),
labels = c("Bajo", "Moderado", "Alto", "Muy Alto"))La consolidación de los mapas interactivos permite visualizar en una sola interfaz los eventos de peligro, accidentes, congestión y cierres de vías, facilitando la comparación entre ellos y ofreciendo una visión integral que apoya la planificación de soluciones coordinadas para los principales problemas de tráfico de la ciudad.
# Sincronizar los mapas interactivos de distintos tipos de eventos
leafsync::sync(m26_peligro, m26_accidente, m26_congestion, m26_via_cerrada)El análisis de los datos de Waze del día 26 permitió identificar patrones espaciales y temporales de peligros, accidentes, congestión y cierres de vías, evidenciando que los trancones y los riesgos en la vía son los eventos más frecuentes. Los mapas de densidad revelaron zonas críticas donde se concentran accidentes y cierres, así como áreas con congestión persistente en horas pico. Estos hallazgos resaltan la necesidad de implementar rutas alternas, mejorar la infraestructura vial y mantener un monitoreo continuo en tiempo real. En conjunto, el uso de datos crowdsourcing demuestra ser una herramienta clave para fortalecer la gestión del tráfico y promover una movilidad urbana más segura y eficiente.
Este tipo de análisis es valioso porque permite comprender de manera precisa cómo se distribuyen los eventos que afectan la movilidad urbana, identificando patrones espaciales y temporales que no son evidentes a simple vista. Al integrar datos colaborativos y herramientas de análisis geoespacial, se generan insumos clave para planificar intervenciones más efectivas, optimizar la gestión del tráfico y priorizar recursos en las zonas de mayor impacto. Además, estos resultados fortalecen la toma de decisiones basada en evidencia, contribuyendo a desarrollar ciudades más seguras, eficientes y sostenibles.
Priorizar intervenciones en zonas críticas identificadas por los mapas de densidad, enfocándose en mejoras de infraestructura vial, señalización y mantenimiento preventivo.
Optimizar la gestión del tráfico mediante ajustes semafóricos basados en evidencia y el diseño de rutas alternas que reduzcan la congestión en horas pico.
Integrar sistemas de monitoreo en tiempo real como Waze en los centros de gestión de movilidad para mejorar la respuesta ante incidentes y fortalecer la toma de decisiones basada en datos.