# Instalación y cargue de librerías
library(readxl)
library(dplyr)
library(lubridate)
library(leaflet)
library(sf)
library(mapview)
library(spatstat)
library(terra)
library(leaflet.extras)
library(ggplot2)
library(leafsync) El presente ejercicio tiene como objetivo analizar la frecuencia y localización de eventos que afectan la movilidad en unas vías específicas de Cundinamarca, a partir de los registros de una base de datos construida a partir de información relativa a la plataforma Waze.
Se carga y presenta la estructura de los datos a utilizar en el análisis, la cual contiene un total de 19 atributos que caracterizan a 5070 entradas, a partir de las siguientes variables:
creation_Date: Fecha y hora en que se creó el reporte del evento.
type: Tipo de evento reportado, que puede ser uno de los siguientes:
PELIGRO: Reportes de peligros en la vía, como objetos en la carretera, vehículos detenidos, etc.
CONGESTIÓN: Reportes de congestión o trancones en el tráfico.
ACCIDENTE: Reportes de accidentes de tráfico.
VÍA CERRADA: Reportes de cierres de vías.
latitude: Latitud geográfica donde ocurrió el evento.
longitude: Longitud geográfica donde ocurrió el evento.
información_adicional: Información adicional proporcionada por el usuario sobre el evento (si está disponible).
otros_campos: Otras variables relevantes incluidas en el conjunto de datos, como el identificador del evento, estado del evento, etc.
# Cargue de base de datos
trama_waze <- read_excel("C:/Users/Juan/Desktop/Maestría/Casos - Información Geográfica/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")
head(trama_waze)#Análisis del tipo de evento
Siendo el tipo de evento la variable de interés del análisis, se presenta un análisis descriptivo del comportamiento de la variable.
##
## ACCIDENTE CONGESTIÓN PELIGRO VÍA CERRADA
## 125 3205 719 1021
Como se puede ver, la congestión vehicular representa el incidente con mayor frecuencia en la zona de estudio.
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 predefinidaDado que hay un interés particular por entender la ocurrencia de peligros específicos el día 26, se hace el filtrado de la base de datos a analizar.
# Identificar eventos PELIGRO del día 26
# 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
pos <- which(trama_waze$tipo_evento == "PELIGRO" & dia == 26)
peligro26 <- trama_waze[pos,]Posteriormente, se realiza la visualización de los eventos en el día priorizado.
# 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_peligroAsí mismo, se realiza un análisis espacial que permita generar mapas de calor para denotar las zonas más afectadas por este tipo de evento.
# 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"))En este sentido, siendo la variable hora la que define la intensidad del mapa de calor, se entiende que las zonas más rojas son aquellas donde los eventos tienden a ocurrir a altas horas de la noche.
En esta sección, se identifican las zonas más afectadas por cierre de vías en la zona de interés.
# Filtrar eventos VÍA CERRADA del día 26
pos2 <- which(trama_waze$tipo_evento == "VÍA CERRADA" & dia == 26)
via_cerrada_26 <- trama_waze[pos2,]
# 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,]
# 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_cerradaAdemás se hace una análisis estadístico espacial de la ocurrencia de este evento.
# 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")# Gráfico independiente: Función K-Estimación
plot(Kest(patron_via_cerrada), main = "Función K-Estimación")Además, se realiza un mapa de calor que denote la intensidad con la que tiene lugar este evento en la zona de interés.
# 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"))A continuación, se replica análisis con la ocurrencia de accidentes.
# Filtrar eventos de accidentes del día 26
pos3 <- which(trama_waze$tipo_evento == "ACCIDENTE" & dia == 26)
accidente_26 <- trama_waze[pos3,]
# 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,]
# 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_accidenteAdemás, para identificar si hay patrones espaciales en la ocurrencia del fenómeno se realiza el siguiente ejercicio:
# 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" )En cuanto al análisis de la densidad de accidentes se identifica:
# Calcular la densidad espacial
im2 <- density(patron_accidente)
# Convertir la densidad a un objeto raster usando terra
mapa_accidente <- rast(im2)
# 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"))# Filtrar eventos de congestión del día 26
pos4 <- which(trama_waze$tipo_evento == "CONGESTIÓN" & dia == 26)
congestion_26 <- trama_waze[pos4,]
# 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,]
# 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_congestion# 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")# Calcular la densidad espacial del patrón de puntos
im3 <- density(patron_congestion)
# Convertir la densidad en un raster utilizando terra
mapa_congestion <- rast(im3)
# 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"))Con el fin de analizar de forma integral, en un mismo espacio geográfico, el comportamiento e interacción de eventos, se utiliza la sincronización de mapas interactivos de leaflet.
El análisis de la forma como se concentran distintos eventos en el transporte y el tránsito de un territorio, como accidentes, cierres viales, congestiones y otros peligros, permite planificar de manera más precisa la movilidad y gestionar soluciones de acuerdo a la identificación de patrones en la ocurrencia de dichos fenómenos, ya sea generando infraestructura, señalización u opciones de movilidad motorizada y no motorizada. Esto, evidencia la relevancia de tomar decisiones basadas en evidencia y la importancia, por ende, de registrar y procesar datos de manera correcta.