Planteamiento del Problema

Se busca analizar la distribución espacial y temporal de los eventos reportados en Waze, para un día específico (el día 26). Se evaluarán y visualizarán los eventos en un mapa interactivo, analizando patrones temporales y espaciales.

La aplicación Waze es una plataforma de navegación colaborativa que proporciona datos valiosos sobre las condiciones del tráfico en tiempo real, incluyendo reportes de peligros, congestión, accidentes y cierres de vías. La información recopilada a partir de eventos reportados por los usuarios es esencial para la planificación urbana y la gestión eficiente del tráfico, permitiendo a las autoridades tomar decisiones informadas para mejorar la movilidad y la seguridad vial.

Se identificarán patrones de tráfico y áreas críticas para orientar acciones de gestión y planificación urbana.

# Cargue de librerías
library(readxl)            
library(dplyr)
library(knitr)
library(kableExtra)
library(summarytools)
library(lubridate) 
library(mapview)
library(leaflet)
library(leaflet.extras)
library(spatstat)

Análisis exploratorio

Se obtienen los datos de eventos reportados en Waze. Se analiza la estructura de los datos, tipos de eventos y su distribución espacial.

Trama_Waze <- read_excel("D:/MaestriaCienciaDatos/S2_AnalisisInfoGeografica/M2U2_PatronesPuntuales/CasoAccion/Trama Waze.xlsx")
#View(Trama_Waze)            

Se cuenta con los siguientes atributos de interés:

Preparación de los Datos

Se realiza la preparación de las variables necesarias para el análisis:

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

# Cambiar los nombres de los subtipos de eventos a español
Trama_Waze$subtipo_evento <- recode(Trama_Waze$subtype,
                                 "ACCIDENT_MAJOR" = "Accidente grave",
                                 "HAZARD_ON_ROAD" = "Peligro en la vía",
                                 "HAZARD_ON_ROAD_CONSTRUCTION" = "Obra en la víaN",
                                 "HAZARD_ON_ROAD_OBJECT" = "Objeto en la vía",
                                 "HAZARD_ON_ROAD_POT_HOLE" = "Bache",
                                 "HAZARD_ON_ROAD_TRAFFIC_LIGHT_FAULT" = "Semáforo dañado",
                                 "HAZARD_ON_SHOULDER_CAR_STOPPED" = "Vehículo detenido",
                                 "HAZARD_WEATHER" = "Peligro por condiciones climáticas",
                                 "HAZARD_WEATHER_FLOOD" = "Peligro por inundación",
                                 "HAZARD_WEATHER_FOG" = "Peligro por niebla",
                                 "HAZARD_WEATHER_HEAVY_SNOW" = "Peligro por nevada intensa",
                                 "JAM_HEAVY_TRAFFIC" = "Tráfico pesado",
                                 "JAM_STAND_STILL_TRAFFIC" = "Tráfico detenido",
                                 "ROAD_CLOSED_EVENT" = "Vía cerrada")

# Selección de fecha de interés 26 de septiembre de 2024
df <- Trama_Waze %>%
  filter(as.Date(fecha) == as.Date("2024-09-26"))

# Extracción de la hora del evento
fecha_hora = ymd_hms(df$creation_Date)
hora = hour(fecha_hora)

# Agregar la columna de hora a los datos
df$hora = hora

# Mostrar análisis descriptivo de los tipos y subtipos de eventos
df %>%
  select(country, tipo_evento, subtipo_evento, hora) %>%
  dfSummary() %>%
  print(method = "render")

Data Frame Summary

df

Dimensions: 1804 x 4
Duplicates: 1734
No Variable Stats / Values Freqs (% of Valid) Graph Valid Missing
1 country [character] 1. CO
1804(100.0%)
1804 (100.0%) 0 (0.0%)
2 tipo_evento [character]
1. ACCIDENTE
2. CONGESTIÓN
3. PELIGRO
4. VÍA CERRADA
39(2.2%)
960(53.2%)
148(8.2%)
657(36.4%)
1804 (100.0%) 0 (0.0%)
3 subtipo_evento [character]
1. Objeto en la vía
2. Peligro en la vía
3. Peligro por condiciones c
4. Peligro por nevada intens
5. Peligro por niebla
6. Tráfico detenido
7. Tráfico pesado
8. Vehículo detenido
9. Vía cerrada
14(0.9%)
25(1.6%)
10(0.6%)
6(0.4%)
7(0.4%)
360(22.5%)
458(28.6%)
86(5.4%)
636(39.7%)
1602 (88.8%) 202 (11.2%)
4 hora [integer]
Mean (sd) : 17.4 (4.5)
min ≤ med ≤ max:
1 ≤ 18 ≤ 23
IQR (CV) : 7 (0.3)
16 distinct values 1804 (100.0%) 0 (0.0%)

Generated by summarytools 1.1.4 (R version 4.5.1)
2025-12-05

# Mostrar la tabla de frecuencia de tipos de eventos vs hora
tabla <- table(df$tipo_evento, df$hora)

kable(tabla, caption = "Tabla de frecuencia de tipo de evento por hora") %>%
  kable_styling(full_width = FALSE, bootstrap_options = c("striped", "hover"))
Tabla de frecuencia de tipo de evento por hora
1 2 10 11 12 13 14 15 16 17 18 19 20 21 22 23
ACCIDENTE 0 0 0 0 30 6 0 0 0 0 0 0 0 0 0 3
CONGESTIÓN 0 0 17 111 106 28 8 21 50 102 54 88 58 82 75 160
PELIGRO 12 25 0 7 11 8 0 3 0 0 11 5 0 16 17 33
VÍA CERRADA 0 0 0 0 0 54 63 60 60 60 60 60 60 60 60 60
# Mostrar la tabla de frecuencia de tipos de eventos vs subtipos
tabla <- table(df$tipo_evento, df$subtipo_evento)

kable(tabla, caption = "Tabla de frecuencia de tipo de evento vs subtipo") %>%
  kable_styling(full_width = FALSE, bootstrap_options = c("striped", "hover"))
Tabla de frecuencia de tipo de evento vs subtipo
Objeto en la vía Peligro en la vía Peligro por condiciones climáticas Peligro por nevada intensa Peligro por niebla Tráfico detenido Tráfico pesado Vehículo detenido Vía cerrada
ACCIDENTE 0 0 0 0 0 0 0 0 0
CONGESTIÓN 0 0 0 0 0 360 458 0 0
PELIGRO 14 25 10 6 7 0 0 86 0
VÍA CERRADA 0 0 0 0 0 0 0 0 636

Modelado

El análisis geoespacial se centrará en los eventos de Congestión generando mapas interactivos que permitan visualizar su distribución y su concentración geográfica a partir de la densidad. Se abordan los siguientes procesos de análisis:

  1. Filtrado eventos de CONGESTIÓN, focalizando el análisis en las situaciones de tráfico que dificultan el flujo vehícular.

  2. Visualización de los eventos de CONGESTIÓN en un mapa interactivo que permita conocer la localización exacta de las situaciones reportadas y agrupándolos en cluster para mejorar la legibilidad.

  3. Creación de mapas de calor que permiten identificar las zonas más críticas, generados a partir de patrones de puntos espaciales utilizando funciones de estimación de densidad.

  4. Evaluación del patrón presente en el evento Congestión.

Visualización de eventos de Congestión

# Filtrado de eventos de congestión
select <- which(df$tipo_evento == "CONGESTIÓN")
congestion <- df[select,]

# Visualización de eventos de congestión
# Ajustar las coordenadas de latitud y longitud
congestion$lat <- congestion$location_y / 10^(nchar(congestion$location_y) - 1)
congestion$long <- congestion$location_x / 10^(nchar(congestion$location_x) - 3)

# Filtrar eventos dentro del rango geográfico adecuado
congestion <- congestion[congestion$lat > 4 & congestion$lat < 5,]

# Crear un mapa interactivo con leaflet
mcongestion <- leaflet() %>%
  addTiles() %>%
  addCircleMarkers(lng = congestion$long, lat = congestion$lat,
                   clusterOptions = markerClusterOptions(),
                   label = congestion$hora) %>%
  addControl(html = "<h3>Mapa de Congestion</h3>", position = "topleft")

# Mostrar el mapa
mcongestion

Análisis espacial de la distribución de eventos de Congestión

# Filtrar datos relevantes de congestion
congestion <- congestion %>%
  filter(lat > 4 & lat < 5, long > -75 & long < -73)  # Ajustar las coordenadas de interés

# Crear un mapa interactivo con leaflet y addHeatmap
congestionm <- leaflet(congestion) %>%
  addProviderTiles("OpenStreetMap") %>%  # Añadir la capa base del mapa
  addHeatmap(
    lng = ~long, lat = ~lat,               # Especificar las columnas de longitud y latitud
    intensity = 1,                         # Densidad pura
    blur = 30,                             # Nivel de desenfoque del mapa de calor
    max = 0.05,                            # Ajustar el valor máximo para la intensidad
    radius = 20                            # Radio de cada punto en el mapa de calor
  ) %>%
  addLegend("bottomright",                 # Añadir leyenda
            title = "Mapa de Calor de Congestión",
            colors = c("blue", "green", "yellow", "red"),
            labels = c("Bajo", "Moderado", "Alto", "Muy Alto"))
congestionm
# Visualización de eventos de congestión por Tráfico detenido

# Filtrado de eventos de congestión por Tráfico detenido
select <- which(congestion$subtipo_evento == "Tráfico detenido")
congestionTd <- congestion[select,]

# Crear un mapa interactivo con leaflet y addHeatmap
congestionTdm <-leaflet(congestionTd) %>%
  addProviderTiles("OpenStreetMap") %>%  # Añadir la capa base del mapa
  addHeatmap(
    lng = ~long, lat = ~lat,               # Especificar las columnas de longitud y latitud
    intensity = 1,                         # Densidad pura
    blur = 30,                             # Nivel de desenfoque del mapa de calor
    max = 0.05,                            # Ajustar el valor máximo para la intensidad
    radius = 20                            # Radio de cada punto en el mapa de calor
  ) %>%
  addLegend("bottomright",                 # Añadir leyenda
            title = "Mapa de Calor de Congestión por Tráfico detenido",
            colors = c("blue", "green", "yellow", "red"),
            labels = c("Bajo", "Moderado", "Alto", "Muy Alto"))
congestionTdm
# Visualización de eventos de congestión por Tráfico pesado

# Filtrado de eventos de congestión por Tráfico pesado
select <- which(congestion$subtipo_evento == "Tráfico pesado")
congestionTp <- congestion[select,]

# Crear un mapa interactivo con leaflet y addHeatmap
congestionTpm <- leaflet(congestionTp) %>%
  addProviderTiles("OpenStreetMap") %>%  # Añadir la capa base del mapa
  addHeatmap(
    lng = ~long, lat = ~lat,               # Especificar las columnas de longitud y latitud
    intensity = 1,                         # Densidad pura
    blur = 30,                             # Nivel de desenfoque del mapa de calor
    max = 0.05,                            # Ajustar el valor máximo para la intensidad
    radius = 20                            # Radio de cada punto en el mapa de calor
  ) %>%
  addLegend("bottomright",                 # Añadir leyenda
            title = "Mapa de Calor de Congestión por Tráfico pesado",
            colors = c("blue", "green", "yellow", "red"),
            labels = c("Bajo", "Moderado", "Alto", "Muy Alto"))
congestionTpm

Prueba Chi2

Se evalúa la intensidad del evento de congestión para establecer si tiene un comportamiento homogéneo o no.

Ho: Los eventos siguen un patrón aleatorio

Ha: Los eventos no siguen un patrón aleatorio
# 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$long, y = congestion$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")

# Prueba Chi2
chi_test <- quadrat.test(patron_congestion)
chi_test
## 
##  Chi-squared test of CSR using quadrat counts
## 
## data:  patron_congestion
## X2 = 2612.9, df = 24, p-value < 2.2e-16
## alternative hypothesis: two.sided
## 
## Quadrats: 5 by 5 grid of tiles

Función K

Teniendo en cuenta que se rechaza Ho estableciendo que el patrón no es aleatorio, se implementa la Función K, para definir que tipo de patrón: agregado o regular sigue el evento de Congestión

# Calcular la función K-estimación
plot(Kest(patron_congestion))

Consolidación de Mapas de Congestión, Congestión por Tráfico detenido y Congestión por Tráfico pesado

Se consolidan estos mapas, para facilitar el análisis de los subtipos de eventos que conforman el evento Congestión.

# Sincronizar los mapas interactivos de distintos tipos de eventos
leafsync::sync(mcongestion, congestionm, congestionTdm, congestionTpm)

Hallazgos

Recomendaciones

Conclusiones

El análisis espacial evidencia que la congestión no ocurre al azar en el área estudiada: existen agrupamientos consistentes que justifican acciones focalizadas.

Los puntos calientes detectados son robustos entre los subtipos (Tráfico detenido, Tráfico pesado), lo que indica puntos de mayor vulnerabilidad urbana.

Implementar este tipo de análisis de ciencia de datos, permite promover una mejor movilidad urbana al contribuir en procesos de planificación y de gestión con un bajo costo, considerando que actualmente se cuenta con mucha información disponible libremente.