Análisis de Datos de Waze para Planeación

Objetivo

El objetivo de este análisis es estudiar la distribución espacial y temporal de los eventos reportados en Waze, entre el 26 y 28 de septiembre de 2024. Se evaluarán y visualizarán los eventos en un mapa interactivo, analizando patrones temporales y espaciales. El uso de herramientas de análisis espacial en R, como leaflet para la visualización geoespacial y spatstat para la densidad y distribución de puntos, permitirá crear mapas de calor que resalten las áreas con mayor incidencia de eventos. A lo largo del análisis se integrarán diversos gráficos y mapas que facilitarán la interpretación de los datos y contribuirán a mejorar la planificación y gestión del tráfico.

Datos

# Cargar los datos de Waze
Trama_Waze <- read_excel("D:/Documentos/Maestria_Ciencia_de_datos/Analisis_espacial/Unidad 3/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")
# 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

Distribución de Eventos

# 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") +
  geom_text(aes(label = Frecuencia), vjust = 0, size = 3.5) + 
  theme_minimal() +
  labs(title = "Distribución de Tipos de Eventos en Trama Waze", 
       x = " ", y = "Frecuencia")+
  theme(legend.position = "none"
        )

##PELIGROS

Filtrado de Eventos PELIGRO

# Identificar eventos PELIGRO
pos <- which(Trama_Waze$tipo_evento == "PELIGRO")
peligro <- Trama_Waze[pos,]

Visualización de Eventos PELIGRO

# Ajustar las coordenadas de latitud y longitud
peligro$lat <- peligro$location_y / 10^(nchar(peligro$location_y) - 1)
peligro$long <- peligro$location_x / 10^(nchar(peligro$location_x) - 3)

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

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

# Mostrar el mapa
m_peligro

Análisis Espacial de la Distribución de Riesgos

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

# Crear un mapa interactivo con leaflet y addHeatmap
leaflet(peligro) %>%
  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"))

VÍA CERRADA

Mapa de Densidad de Cierres de Vías

# Filtrar eventos VÍA CERRADA
pos <- which(Trama_Waze$tipo_evento == "VÍA CERRADA")
via_cerrada <- Trama_Waze[pos,]

# Ajustar las coordenadas de latitud y longitud
via_cerrada$lat <- via_cerrada$location_y / 10^(nchar(via_cerrada$location_y) - 1)
via_cerrada$long <- via_cerrada$location_x / 10^(nchar(via_cerrada$location_x) - 3)

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

Mapa Interactivo de Cierres de Vías

# Crear el mapa interactivo
m_via_cerrada = leaflet(via_cerrada) %>%
  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
m_via_cerrada

Análisis Espacial de Cierres de Vías

# 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$long, y = via_cerrada$lat, window = zona)
## Warning: data contain duplicated points
# Graficar el test de cuadrantes
plot(quadratcount(patron_via_cerrada), main = "Patrón de Puntos y Test de Cuadrantes")

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

La distribución es agregada porque las curvas están por encima de la poisson

Mapa de Densidad de Cierres de Vías

# Asegurarse de que el objeto patron_via_cerrada esté correctamente definido
# Crear un patrón de puntos espaciales utilizando los datos correctos (via_cerrada)
zona <- owin(xrange = c(-74.04331, -73.9929), yrange = c(4.885736, 4.948562))
patron_via_cerrada <- ppp(x = via_cerrada$long, y = via_cerrada$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"))

ACCIDENTES

Análisis de Accidentes

# Filtrar eventos de accidentes
pos <- which(Trama_Waze$tipo_evento == "ACCIDENTE")
accidente <- Trama_Waze[pos,]

# Ajustar las coordenadas de latitud y longitud
accidente$lat <- accidente$location_y / 10^(nchar(accidente$location_y) - 1)
accidente$long <- accidente$location_x / 10^(nchar(accidente$location_x) - 3)

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

Mapa Interactivo de Accidentes

# Crear el mapa interactivo
m_accidente <- leaflet(accidente) %>%
  addTiles() %>%
  addCircleMarkers(lng = ~long, lat = ~lat,
                   clusterOptions = markerClusterOptions(),
                   label = ~hora) %>%
  addControl(html = "<h3>Mapa de Accidentes</h3>", position = "topleft")

# Mostrar el mapa interactivo
m_accidente

Análisis Espacial de Accidentes

# 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$long, y = accidente$lat, window = zona)
## Warning: data contain duplicated points
# 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")

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

La distribución es agregada porque las curvas están por encima de la poisson

Mapa de Densidad de Accidentes

# 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$long, y = accidente$lat, window = zona)
## Warning: data contain duplicated points
# 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"))

CONGESTIÓN

Análisis de Congestión

# Filtrar eventos de congestión
pos <- which(Trama_Waze$tipo_evento == "CONGESTIÓN")
congestion <- Trama_Waze[pos,]

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

Mapa Interactivo de Congestión

# Crear el mapa interactivo
m_congestion <- leaflet(congestion) %>%
  addTiles() %>%
  addCircleMarkers(lng = ~long, lat = ~lat,
                   clusterOptions = markerClusterOptions(),
                   label = ~hora) %>%
  addControl(html = "<h3>Mapa de Congestión</h3>", position = "topleft")

# Mostrar el mapa interactivo
m_congestion

Análisis Espacial de Congestión

# 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)
## Warning: data contain duplicated points
# 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")

# Calcular la función K-estimación
patron_congestion_sub <- patron_congestion[sample(npoints(patron_congestion), 2500)]
plot(Kest(patron_congestion_sub))

La distribución es agregada porque las curvas están por encima de la poisson

Mapa de Densidad de Congestión

# 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$long, y = congestion$lat, window = zona)
## Warning: data contain duplicated points
# 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"))

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

# Sincronizar los mapas interactivos de distintos tipos de eventos
leafsync::sync(m_peligro, m_accidente, m_congestion, m_via_cerrada)

Conclusión

El análisis realizado sobre los datos proporcionados por Waze para los días 26 al 28, permite obtener una visión integral de los eventos que afectan la movilidad urbana, como peligros en las vías (PELIGRO), congestión (CONGESTIÓN), accidentes (ACCIDENTE) y cierres de vías (VÍA CERRADA). A través de la utilización de herramientas de análisis espacial y la visualización en mapas interactivos, se han identificado patrones importantes en la distribución espacial y temporal de estos eventos.

Sin embargo, se requiere contar con más datos para realizar un análisis más detallado que permita identificar de manera más precisa los puntos críticos de movilidad en la ciudad.