Objetivo

Replicar el cuaderno de Análisis de Datos de Waze para Planeación, cuyo objetivo es estudiar la distribución espacial y temporal de los eventos reportados en Waze, el día 26, donde se evaluan y visualizan los eventos en un mapa interactivo, analizando patrones temporales y espaciales; y además podría facilitar la interpretación de los datos y contribuirán a mejorar la planificación y gestión del tráfico.

Carga de Datos de Librerías Necesarias

## Cargando paquete requerido: readxl
## Cargando paquete requerido: dplyr
## 
## Adjuntando el paquete: 'dplyr'
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
## Cargando paquete requerido: lubridate
## 
## Adjuntando el paquete: 'lubridate'
## The following objects are masked from 'package:base':
## 
##     date, intersect, setdiff, union
## Cargando paquete requerido: leaflet
## Cargando paquete requerido: sf
## Linking to GEOS 3.12.2, GDAL 3.9.3, PROJ 9.4.1; sf_use_s2() is TRUE
## Cargando paquete requerido: mapview
## Cargando paquete requerido: spatstat
## Cargando paquete requerido: spatstat.data
## Cargando paquete requerido: spatstat.univar
## spatstat.univar 3.1-1
## Cargando paquete requerido: spatstat.geom
## spatstat.geom 3.3-4
## Cargando paquete requerido: spatstat.random
## spatstat.random 3.3-2
## Cargando paquete requerido: spatstat.explore
## Cargando paquete requerido: nlme
## 
## Adjuntando el paquete: 'nlme'
## The following object is masked from 'package:dplyr':
## 
##     collapse
## spatstat.explore 3.3-3
## Cargando paquete requerido: spatstat.model
## Cargando paquete requerido: rpart
## spatstat.model 3.3-3
## Cargando paquete requerido: spatstat.linnet
## spatstat.linnet 3.2-3
## 
## spatstat 3.3-0 
## For an introduction to spatstat, type 'beginner'
## Cargando paquete requerido: terra
## terra 1.7.83
## 
## Adjuntando el paquete: 'terra'
## The following objects are masked from 'package:spatstat.geom':
## 
##     area, delaunay, is.empty, rescale, rotate, shift, where.max,
##     where.min
## Cargando paquete requerido: leaflet.extras
## Cargando paquete requerido: ggplot2
## Cargando paquete requerido: leafsync

Importe de Base de Datos

Los datos utilizados en este análisis fueron obtenidos a partir de la plataforma Waze, que permite la recopilación de eventos reportados por usuarios en tiempo real. Estos eventos incluyen peligros en las vías (PELIGRO), congestión (CONGESTIÓN), accidentes (ACCIDENTE), y cierres de vías (VÍA CERRADA).

Trama_Waze = read_excel("Trama Waze.xlsx")

#convertir la columna de fechas a formato adecuado
Trama_Waze$fecha = as.Date(Trama_Waze$creation_Date, format ="%Y-%m-%d %H:%M")

#cambiar los nombres de los tipos de eventos a español
Trama_Waze$tipo_evento <- recode(Trama_Waze$type,
                                 "ACCIDENT" = "ACCIDENTE",
                                 "HAZARD" = "PELIGRO",
                                 "JAM" = "CONGESTIÓN",
                                 "ROAD_CLOSED" = "VÍA CERRADA")

Análisis Temporal de los Eventos

El objetivo es analizar si existen concentraciones de eventos en ciertas franjas horarias y cómo estos se distribuyen a lo largo del día, lo que podría revelar horas pico de congestión o momentos críticos con mayor cantidad de accidentes.

# 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

Distribución de Eventos

#frecuencia de cada tipo de evento
frecuencia_eventos <- Trama_Waze %>%
  group_by(tipo_evento) %>%                 #Agrupar por tipo de evento
  summarise(Frecuencia = n()) %>%     #frecuencia de cada tipo
  arrange(desc(Frecuencia))           #Ordenar  descendente

#gráfico
ggplot(frecuencia_eventos, aes(x = tipo_evento, y = Frecuencia, fill = tipo_evento)) +
  geom_bar(stat = "identity") +
  theme_minimal() +
  labs(x = "Tipo de Evento", y = "Frecuencia") +
  theme(axis.text.x = element_text(angle = 45, hjust = 1)) +  #Rotar etiquetas
  scale_fill_brewer(palette = "Set2") 

Figura 1. Distribución de los eventos reportados para el 26.

La mayor cantidad de eventos reportados para el 26 son las congestiones (3205), seguido de vía cerrada (1021), después vía cerrada (719) y finalmente accidentes (125)

Análisis de evento Peligro

Ahora se filtran los eventos de tipo PELIGRO que ocurrieron específicamente el día 26.

#filtrar eventos PELIGRO del día 26
pos <- which(Trama_Waze$tipo_evento == "PELIGRO" & dia == 26)
peligro26 <- Trama_Waze[pos,]

# 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,]

Mapa Interactivo

# Crear un mapa interactivo con leaflet
m26_peligro <- leaflet() %>%
  addTiles() %>%
  addCircleMarkers(lng = peligro26$long, lat = peligro26$lat,
                   clusterOptions = markerClusterOptions(),
                   label = peligro26$hora)

# Mostrar el mapa
m26_peligro

Figura 2. Mapa de evento Peligro.

De acuerdo con la Figura 2, se puede observar que la mayor cantidad de los eventos de peligros se encuentran cerca de las vías principales (Autopistas).

Análisis Espacial

Vamos a estudiar cómo están distribuidos geográficamente los eventos de cierre de vías reportados el día 26 y analizar si existen patrones en la concentración de estos eventos.

#zona de interés
zona <- owin(xrange = c(-74.04331, -73.9929), yrange = c(4.885736, 4.948562))

#patrón de puntos espaciales
patron_peligro <- ppp(x = peligro26$long, y = peligro26$lat, window = zona)

#graficar el test de cuadrantes
plot(quadratcount(patron_peligro), main = "")

#Superponer los puntos sobre los cuadrantes
points(patron_peligro, col = "red")

Figura 3. Patrón de Puntos y Test de Cuadrantes de Peligro.

# Gráfico independiente: Función K-Estimación
plot(Kest(patron_peligro), main= "")

Figura 4. Función de K-Estimación de Peligro.

De acuerdo con la Figura 3 y Figura 4 los datos de peligros reportados en Waze muestra una distribución espacial agrupada. Celdas como aquellas con 34, 28 y 25 eventos indican zonas críticas donde los reportes de peligro sonmás frecuentes. Por otro lado, las celdas con valores de 0 sugieren zonas con baja o nula incidencia de reportes. No se muestra un patrón aleatorio en los eventos de Peligro

Ahora, se estudia la distribución geográfica de los eventos de peligro, generando mapas de calor que destaquen las áreas más afectadas.

Mapa de Calor

#filtrar datos relevantes de peligro26
peligro26 <- peligro26 %>%
  filter(lat > 4 & lat < 5, long > -75 & long < -73) #coordenadas de interes

#Crear un mapa interactivo 
leaflet(peligro26) %>%
  addProviderTiles("OpenStreetMap") %>%  #capa base del mapa
  addHeatmap(
    lng = ~long, lat = ~lat,
    intensity = ~hora,                    
    blur = 20,  #nivel de desenfoque del mapa de calor
    max = 0.08,     #valor de intensidad
    radius = 15   #radio de cada punto en el mapa de calor
  ) %>%
  addLegend("bottomright",                 #leyenda
            title = "Mapa de Calor de Riesgos",
            colors = c("blue", "green", "yellow", "red"),
            labels = c("Bajo", "Moderado", "Alto", "Muy Alto"))

Figura 5. Mapa de Calor de evento Peligro.

De acuerdo con la Figura 5, se puede observar que hay concentración los eventos de peligros se encuentran cerca de las vías principales. Se destaca principalmente en el sector de Hato Grande y la Vía Cajicá - Chía la concentración de eventos tipo Peligro.

Análisis de evento Cierre de vías

En esta sección se identifican las zonas más afectadas por los cierres de vías, lo que podría ayudar en la planificación de desvíos y la optimización de la movilidad urbana.

#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,]

Mapa Interactivo

m26_via_cerrada = leaflet(via_cerrada_26) %>%
  addTiles() %>%
  addCircleMarkers(lng = ~long, lat = ~lat,
                   clusterOptions = markerClusterOptions(),
                   label = ~hora)

# Mostrar el mapa interactivo
m26_via_cerrada

Figura 6. Mapa de Cierre de vías.

De acuerdo con la Figura 6, se presentan cierres en la Calle 9 sur y alrededor del Parque Ciudad Pomar.

Análisis Espacial

Vamos a estudiar cómo están distribuidos geográficamente los eventos de cierre de vías reportados el día 26 y analizar si existen patrones en la concentración de estos eventos.

#zona de interés
zona <- owin(xrange = c(-74.04331, -73.9929), yrange = c(4.885736, 4.948562))

#patrón de puntos espaciales
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 = "")

#Superponer los puntos sobre los cuadrantes
points(patron_via_cerrada, col = "red")

Figura 7. Patrón de Puntos y Test de Cuadrantes para Cierres de Vías.

# Gráfico independiente: Función K-Estimación
plot(Kest(patron_via_cerrada), main= "")

Figura 8. Función de K-Estimación para Cierres de Vías.

De acuerdo con la Figura 7 y la Figura 8, no se muestra un patrón aleatorio, sino concetrado en ciertas zonas de la ciudad.

Mapa de Densidad

A continuación se destacan las zonas con la mayor cantidad de eventos de cierre de vías.

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)

#Calcular la densidad espacial
im1 <- density(patron_via_cerrada, sigma = 0.01)

#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))

#mapa interactivo
leaflet(df_via_cerrada) %>%
  addProviderTiles("OpenStreetMap") %>%  
  addHeatmap(
    lng = ~long, lat = ~lat,             
    intensity = ~intensity,               
    blur = 20,                            
    max = 1,                              
    radius = 15                           
  ) %>%
  addLegend("bottomright",              
            colors = c("blue", "green", "yellow", "red"),
            labels = c("Bajo", "Moderado", "Alto", "Muy Alto"))

Figura 9. Mapa de Calor de Cierres de Vías.

Se presentan cierres de vías en la zona de Canelon por al vía Cajicá- Chía.

Análisis de evento Accidente

En esta sección se realiza un análisis de los eventos de accidentes (ACCIDENTE) ocurridos el día 26

pos <- which(Trama_Waze$tipo_evento == "ACCIDENTE" & dia == 26)
accidente_26 <- Trama_Waze[pos,]

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)

accidente_26 <- accidente_26[accidente_26$lat > 4 & accidente_26$lat < 5,]

Mapa Interactivo

m26_accidente <- leaflet(accidente_26) %>%
  addTiles() %>%
  addCircleMarkers(lng = ~long, lat = ~lat,
                   clusterOptions = markerClusterOptions(),
                   label = ~hora)

# Mostrar el mapa interactivo
m26_accidente

Figura 10. Mapa de evento Accidente.

De acuerdo con la Figura 10, se presentan accidentes principalmente en la Avenida de la Carrera 9.

Análisis Espacial

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)

par(mfrow = c(1, 1))  

#test de cuadrantes
plot(quadratcount(patron_accidente), main = "")

points(patron_accidente, col = "red" )

Figura 11. Patrón de Puntos y Test de Cuadrantes de Accidentes.

# Calcular la función K-estimación
plot(Kest(patron_accidente), main = "")

Figura 12. Función K-estimación de Accidentes.

De acuerdo con la Figura 11 y la Figura 12, los accidentes no tienen un patrón aleatorio, sino que estan concentrados en dos zonas de la ciudad (principalmente donde encuentran la celda con 34).

Mapa de Densidad

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)

#densidad espacial
im1 <- density(patron_accidente)

mapa_accidente <- rast(im1)

df_accidente <- as.data.frame(mapa_accidente, xy = TRUE)
colnames(df_accidente) <- c("long", "lat", "intensity")

df_accidente$intensity <- (df_accidente$intensity - min(df_accidente$intensity)) / 
                          (max(df_accidente$intensity) - min(df_accidente$intensity))

#mapa
leaflet(df_accidente) %>%
  addProviderTiles("OpenStreetMap") %>%
  addHeatmap(
    lng = ~long, lat = ~lat,              
    intensity = ~intensity,               
    blur = 15,                            
    max = 0.5,                             
    radius = 10                           
  ) %>%
  addLegend("bottomright",                
            title = "Mapa de Calor de Accidentes",
            colors = c("blue", "green", "yellow", "red"),
            labels = c("Bajo", "Moderado", "Alto", "Muy Alto"))

Figura 13. Mapa de Densidad de Accidentes.

De acuerdo con la Figura 13, se presenta una concentración moderada de Accidentes en la carrera 9.

Análisis de evento Congestión

Finalmente, se analizó la congestión reportada (CONGESTIÓN) el día 26.

pos <- which(Trama_Waze$tipo_evento == "CONGESTIÓN" & dia == 26)
congestion_26 <- Trama_Waze[pos,]

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)

congestion_26 <- congestion_26[congestion_26$lat > 4 & congestion_26$lat < 5,]

Mapa Interactivo

m26_congestion <- leaflet(congestion_26) %>%
  addTiles() %>%
  addCircleMarkers(lng = ~long, lat = ~lat,
                   clusterOptions = markerClusterOptions(),
                   label = ~hora)

# Mostrar el mapa interactivo
m26_congestion

Figura 14. Mapa de evento Congestión.

De acuerdo con la Figura 14, se presentan congestiones alrededor de la avenidas y vías principales.

Análisis Espacial

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)

par(mfrow = c(1, 1))  

plot(quadratcount(patron_congestion), main = "")

# Superponer los puntos sobre los cuadrantes
points(patron_congestion, col = "red")

Figura 15. Patrón de Puntos y Test de Cuadrantes de Congestión de vías.

# Calcular la función K-estimación
plot(Kest(patron_congestion), main = "")

Figura 16. Función K-estimación de Congestión de vías.

De acuerdo con la Figura 15 y Figura 16, se presentan puntos concentrados en zonas de la ciudad. No se aprecia un patrón aleatorio del evento de congestión en las vías.

Mapa de Densidad

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)

im1 <- density(patron_congestion)

mapa_congestion <- rast(im1)

df_congestion <- as.data.frame(mapa_congestion, xy = TRUE)
colnames(df_congestion) <- c("long", "lat", "intensity")

df_congestion$intensity <- (df_congestion$intensity - min(df_congestion$intensity)) / 
                           (max(df_congestion$intensity) - min(df_congestion$intensity))

#mapa
leaflet(df_congestion) %>%
  addProviderTiles("OpenStreetMap") %>% 
  addHeatmap(
    lng = ~long, lat = ~lat,    
    intensity = ~intensity,               
    blur = 35,                            
    max = max(df_congestion$intensity) * 2,  
    radius = 25                           
  ) %>%
  addLegend("bottomright",                
            title = "Mapa de Calor de Congestión",
            colors = c("blue", "green", "yellow", "red"),
            labels = c("Bajo", "Moderado", "Alto", "Muy Alto"))

Figura 17. Mapa de Calor de la Congestión de Vías.

De acuerdo con la Figura 17, se presetan grandes congestiones en la zona norte de la ciudad, entre las zonas de Canelon, Hato Grande y Calahorra.

Consolidación de Mapas de Riesgo, Accidentes, Congestión y Cierres Viales

leafsync::sync(m26_peligro, m26_accidente, m26_congestion, m26_via_cerrada)

Figura 18. Mapas de Riesgo, Accidentes, Congestión y Cierres Viales.

Conclusiones

  • La mayor cantidad de eventos reportados en la plataforma Waze el día 26 corresponde a congestiones vehiculares, lo que sugiere que el tráfico es el principal problema. Los eventos de tipo “Vía Cerrada” y “Peligro” también son relevenantes para la movilidad en esta ciudad.

  • Los eventos de “Peligro” tienden a concentrarse cerca de vías principales, como autopistas y avenidas, destacándose sectores como Hato Grande y la vía Cajicá - Chía. Esto sugiere que podrian hacerse intervenciones en estas zonas para mejorar la seguridad vial.

  • Los cierres de vías se encuentran principalmente alrededor de lugares específicos, como la Calle 9 Sur y el Parque Ciudad Pomar, indicando zonas de alta actividad o problemas estructurales que afectan la movilidad.

  • Los mapas interactivos y de calor destacan áreas con mayor frecuencia de eventos, lo que permite la visualización y priorización de zonas donde se presentes muchos de estos eventos y nos pueden ayudar a tomar decisiones para el mejoramiento de la movilidad.

  • Con estos análisis se puede obtener información significativa para mejorar la gestión del tráfico y la seguridad vial. La identificación de patrones espaciales permite priorizar acciones correctivas y optimizar la asignación de recursos en las zonas más afectadas.

Referencia

Cuantico. 2024. Análisis de Datos de Waze para Planeación.Tomado de: https://rpubs.com/JuanMAriasG2206/1247156