1. Carga de librerías

# ------------------------------------------------------------
# Librerías de análisis geográfico y espacial
# ------------------------------------------------------------
library(sf)
library(terra)
 
# Librerías de soporte
library(readxl)
library(dplyr)
library(ggplot2)
library(viridis)
library(patchwork)
library(scales)
library(ggtext)

2. Carga y exploración de datos de encuesta

# ------------------------------------------------------------
# Carga de las hojas relevantes del archivo Excel
# ------------------------------------------------------------

# Hoja principal con registros de viajes
encuesta <- read_excel(
  path      = "EncuestaOrigenDestino.xlsx",
  sheet     = "Hoja1",
  col_types = "text"
)
# ------------------------------------------------------------
# Preparación y limpieza de datos
# ------------------------------------------------------------

# Convertir columnas clave a tipo numérico
encuesta_limpia <- encuesta %>%
  mutate(
    tipo_vehiculo  = as.numeric(`TIPO DE VEHÍCULO`),
    comuna_origen  = as.character(`comuna origen`),
    comuna_destino  = as.character(`comuna destino`)
  )

# Verificar valores únicos de tipo_vehiculo y comunas de Cali
cat("\nDistribución de tipos de vehículo:\n")
## 
## Distribución de tipos de vehículo:
print(table(encuesta_limpia$tipo_vehiculo, useNA = "ifany"))
## 
##     1     2     3     4     5     6     7     8     9    77  <NA> 
##  1731 16077 14100   459  1999   211   167    88    30    77   115
cat("\nComunas de origen (muestra):\n")
## 
## Comunas de origen (muestra):
print(unique(encuesta_limpia$`comuna origen`))
##  [1] "02"            "Fuera de Cali" "06"            "03"           
##  [5] "04"            "13"            "17"            "16"           
##  [9] "05"            "15"            "07"            "14"           
## [13] "10"            "21"            "08"            "11"           
## [17] "19"            "12"            "20"            "01"           
## [21] "0"             "18"            "09"            "22"
cat("\nComunas de destino (muestra):\n")
## 
## Comunas de destino (muestra):
print(unique(encuesta_limpia$`comuna destino`))
##  [1] "22"            "19"            "03"            "09"           
##  [5] "02"            "17"            "Fuera de Cali" "04"           
##  [9] "11"            "13"            "18"            "06"           
## [13] "20"            "10"            "21"            "05"           
## [17] "01"            "14"            "08"            "0"            
## [21] "16"            "07"            "15"            "12"
# ------------------------------------------------------------
# Filtro 1: Solo viajes cuyo origen es Cali
# Se excluyen registros con 'Fuera de Cali' o NA en comuna_origen
# ------------------------------------------------------------

encuesta_cali <- encuesta_limpia %>%
  filter(
    !is.na(comuna_origen),                  # Sin valores faltantes en comuna
    !is.na(comuna_destino),
    comuna_origen != "Fuera de Cali",       # Excluir externos a Cali
    comuna_destino != "Fuera de Cali",
    !is.na(tipo_vehiculo)                   # Solo registros con tipo de vehículo
  ) %>%
  # Normalizar código de comuna: asegurar formato de 2 dígitos
  mutate(
    codigo_comuna_o = sprintf("%02d", as.integer(comuna_origen))
  ) %>%
  mutate(
    codigo_comuna_d = sprintf("%02d", as.integer(comuna_destino))
  )

cat("Registros de Cali tras limpieza:", nrow(encuesta_cali), "\n")
## Registros de Cali tras limpieza: 23319

3. Descarga y carga de cartografía

# ============================================================
# Cartografía de comunas de Cali
# ============================================================

comunas_sf <- sf::st_read("cali/Comunas.shp", quiet = FALSE)
## Reading layer `Comunas' from data source 
##   `C:\Santi\Jave\Semestre12\Análisis T\Taller1\Taller1\cali\Comunas.shp' 
##   using driver `ESRI Shapefile'
## Simple feature collection with 22 features and 4 fields
## Geometry type: POLYGON
## Dimension:     XY
## Bounding box:  xmin: 1053868 ymin: 860190.2 xmax: 1068492 ymax: 879441.5
## Projected CRS: MAGNA_Colombia_Cali
# Inspeccionar la cartografía cargada
cat("\nNúmero de comunas en la cartografía:", nrow(comunas_sf), "\n")
## 
## Número de comunas en la cartografía: 22
# ------------------------------------------------------------
# Normalizar el código de comuna en la cartografía
# Se asume que el campo con el código de comuna puede variar;
# ajustar el nombre de columna según los datos reales descargados.
# ------------------------------------------------------------

# Identificar la columna que contiene el número/código de comuna
# (los nombres varían según la fuente del shapefile)
col_codigo <- names(comunas_sf)[
  grepl("CODIGO|CODIGO_COM|NUMERO|NUM_COM|commune|COMUNA",
        names(comunas_sf), ignore.case = TRUE)
][1]

# Si no se detecta automáticamente, usar la segunda columna como fallback
if (is.na(col_codigo)) col_codigo <- names(comunas_sf)[2]

# Crear campo estandarizado de código de 2 dígitos
comunas_sf <- comunas_sf %>%
  mutate(
    codigo_comuna_o = sprintf("%02d", as.integer(as.character(.data[[col_codigo]])))
  )

4. Agregación de viajes por comuna

# ------------------------------------------------------------
# Conteo total de viajes en cada comuna de Cali
# ------------------------------------------------------------

conteo_total_o <- encuesta_cali %>%
  count(codigo_comuna_o, name = "n_viajes") %>%
  arrange(desc(n_viajes))

cat("Top 5 comunas por número de viajes originados:\n")
## Top 5 comunas por número de viajes originados:
print(head(conteo_total_o, 5))
## # A tibble: 5 × 2
##   codigo_comuna_o n_viajes
##   <chr>              <int>
## 1 02                  2313
## 2 19                  2313
## 3 17                  1857
## 4 03                  1644
## 5 18                  1242
conteo_total_d <- encuesta_cali %>%
  count(codigo_comuna_d, name = "n_viajes") %>%
  arrange(desc(n_viajes))

cat("Top 5 comunas por número de viajes recibidos:\n")
## Top 5 comunas por número de viajes recibidos:
print(head(conteo_total_d, 5))
## # A tibble: 5 × 2
##   codigo_comuna_d n_viajes
##   <chr>              <int>
## 1 02                  3867
## 2 03                  2966
## 3 19                  2497
## 4 17                  1695
## 5 22                  1573
# ------------------------------------------------------------
# Conteo de viajes por tipo de vehículo de interés:
#   1 = Bicicleta | 2 = Moto | 3 = Automóvil
# ------------------------------------------------------------

# Etiquetas de los tipos de vehículo según la hoja Convenciones (2)
vehiculos <- c(`1` = "Bicicleta", `2` = "Moto", `3` = "Automóvil")

# Función auxiliar: contar viajes para un tipo de vehículo específico
contar_por_vehiculo <- function(datos, tipo_id) {
  datos %>%
    filter(tipo_vehiculo == tipo_id) %>%
    count(codigo_comuna_o, name = "n_viajes") %>%
    arrange(desc(n_viajes))
}

conteo_bici  <- contar_por_vehiculo(encuesta_cali, 1)
conteo_moto  <- contar_por_vehiculo(encuesta_cali, 2)
conteo_auto  <- contar_por_vehiculo(encuesta_cali, 3)

cat("Viajes en bicicleta por comuna (top 5):\n");  print(head(conteo_bici, 5))
## Viajes en bicicleta por comuna (top 5):
## # A tibble: 5 × 2
##   codigo_comuna_o n_viajes
##   <chr>              <int>
## 1 02                   124
## 2 19                   115
## 3 17                   111
## 4 03                    87
## 5 18                    87
cat("\nViajes en moto por comuna (top 5):\n");      print(head(conteo_moto, 5))
## 
## Viajes en moto por comuna (top 5):
## # A tibble: 5 × 2
##   codigo_comuna_o n_viajes
##   <chr>              <int>
## 1 02                  1096
## 2 19                  1036
## 3 17                   886
## 4 03                   726
## 5 18                   613
cat("\nViajes en automóvil por comuna (top 5):\n"); print(head(conteo_auto, 5))
## 
## Viajes en automóvil por comuna (top 5):
## # A tibble: 5 × 2
##   codigo_comuna_o n_viajes
##   <chr>              <int>
## 1 19                   954
## 2 02                   886
## 3 17                   709
## 4 03                   687
## 5 04                   452
# ------------------------------------------------------------
# Conteo de viajes RECIBIDOS por tipo de vehículo de interés:
#   1 = Bicicleta | 2 = Moto | 3 = Automóvil
# ------------------------------------------------------------

# Función auxiliar: contar viajes de destino para un tipo de vehículo
contar_por_vehiculo_d <- function(datos, tipo_id) {
  datos %>%
    filter(tipo_vehiculo == tipo_id) %>%
    count(codigo_comuna_d, name = "n_viajes") %>%
    arrange(desc(n_viajes))
}

conteo_bici_d <- contar_por_vehiculo_d(encuesta_cali, 1)
conteo_moto_d <- contar_por_vehiculo_d(encuesta_cali, 2)
conteo_auto_d <- contar_por_vehiculo_d(encuesta_cali, 3)

cat("Viajes recibidos en bicicleta por comuna (top 5):\n");   print(head(conteo_bici_d, 5))
## Viajes recibidos en bicicleta por comuna (top 5):
## # A tibble: 5 × 2
##   codigo_comuna_d n_viajes
##   <chr>              <int>
## 1 02                   201
## 2 03                   172
## 3 19                   133
## 4 17                   101
## 5 22                    96
cat("\nViajes recibidos en moto por comuna (top 5):\n");      print(head(conteo_moto_d, 5))
## 
## Viajes recibidos en moto por comuna (top 5):
## # A tibble: 5 × 2
##   codigo_comuna_d n_viajes
##   <chr>              <int>
## 1 02                  1778
## 2 03                  1364
## 3 19                  1171
## 4 22                   773
## 5 17                   764
cat("\nViajes recibidos en automóvil por comuna (top 5):\n"); print(head(conteo_auto_d, 5))
## 
## Viajes recibidos en automóvil por comuna (top 5):
## # A tibble: 5 × 2
##   codigo_comuna_d n_viajes
##   <chr>              <int>
## 1 02                  1565
## 2 03                  1140
## 3 19                   966
## 4 17                   695
## 5 04                   612

5. Unión de datos tabulares con cartografía

# ------------------------------------------------------------
# Left join: cartografía ← datos de conteo
# Se usa left_join para conservar TODAS las comunas aunque
# no tengan viajes registrados (quedarán con NA → 0)
# ------------------------------------------------------------
 
# Función que une un data.frame de conteos con la cartografía
unir_con_mapa <- function(cartografia, conteos) {
  cartografia %>%
    left_join(conteos, by = "codigo_comuna_o") %>%
    mutate(n_viajes = replace(n_viajes, is.na(n_viajes), 0))
}

mapa_total <- unir_con_mapa(comunas_sf, conteo_total_o)
mapa_bici  <- unir_con_mapa(comunas_sf, conteo_bici)
mapa_moto  <- unir_con_mapa(comunas_sf, conteo_moto)
mapa_auto  <- unir_con_mapa(comunas_sf, conteo_auto)

cat("Resumen estadístico del total de viajes por comuna:\n")
## Resumen estadístico del total de viajes por comuna:
summary(mapa_total$n_viajes)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   265.0   657.2   873.0  1034.6  1197.8  2313.0
# ------------------------------------------------------------
# Left join para datos de DESTINO: cartografía ← conteos de destino
# Se renombra el campo de unión para hacer join por codigo_comuna_d
# ------------------------------------------------------------

# Función que une conteos de destino con la cartografía
unir_con_mapa_d <- function(cartografia, conteos) {
  cartografia %>%
    left_join(conteos, by = c("codigo_comuna_o" = "codigo_comuna_d")) %>%
    mutate(n_viajes = replace(n_viajes, is.na(n_viajes), 0))
}

mapa_total_d <- unir_con_mapa_d(comunas_sf, conteo_total_d)
mapa_bici_d  <- unir_con_mapa_d(comunas_sf, conteo_bici_d)
mapa_moto_d  <- unir_con_mapa_d(comunas_sf, conteo_moto_d)
mapa_auto_d  <- unir_con_mapa_d(comunas_sf, conteo_auto_d)

cat("Resumen estadístico del total de viajes recibidos por comuna:\n")
## Resumen estadístico del total de viajes recibidos por comuna:
summary(mapa_total_d$n_viajes)
##    Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
##   190.0   457.2   595.5  1028.9  1410.8  3867.0

6. Visualización — Mapas Temáticos

6.1 Función auxiliar de mapa

# ============================================================
# Función reutilizable para generar mapas temáticos coropletas
# Parámetros:
#   datos      : objeto sf con columna n_viajes
#   titulo     : título del mapa
#   subtitulo  : subtítulo descriptivo
#   paleta     : nombre de paleta viridis ("viridis","magma",etc.)
#   lim_sup    : valor máximo de la escala (NULL = automático)
# ============================================================

mapa_tematico <- function(datos, titulo, subtitulo = "",
                          paleta = "viridis", lim_sup = NULL) {
  
  max_val <- if (is.null(lim_sup)) max(datos$n_viajes, na.rm = TRUE) else lim_sup
  
  ggplot(datos) +
    # Capa de relleno según número de viajes
    geom_sf(aes(fill = n_viajes), color = "white", linewidth = 0.4) +
    # Etiquetas con código de comuna
    geom_sf_text(aes(label = codigo_comuna_o), size = 2.8,
                 color = "white", fontface = "bold") +
    # Escala de color continua (paleta viridis)
    scale_fill_viridis_c(
      option   = paleta,
      name     = "N° de viajes",
      limits   = c(0, max_val),
      labels   = label_comma(),
      guide    = guide_colorbar(
        barwidth  = 12,
        barheight = 0.6,
        title.position = "top",
        title.hjust    = 0.5
      )
    ) +
    # Títulos y etiquetas
    labs(
      title    = titulo,
      subtitle = subtitulo,
      caption  = "Fuente: Encuesta Origen-Destino Hogares (EODH) — Metro Cali S.A."
    ) +
    # Tema limpio para cartografía
    theme_void(base_size = 12) +
    theme(
      plot.title    = element_text(face = "bold", size = 14, hjust = 0.5,
                                   margin = margin(b = 4)),
      plot.subtitle = element_text(size = 10, hjust = 0.5, color = "grey40",
                                   margin = margin(b = 8)),
      plot.caption  = element_text(size = 8, color = "grey55", hjust = 1),
      legend.position  = "bottom",
      legend.title     = element_text(size = 9, face = "bold"),
      legend.text      = element_text(size = 8),
      plot.margin      = margin(10, 10, 10, 10)
    )
}

6.2 Mapa principal — Total de viajes generados

# ------------------------------------------------------------
# Mapa principal: total de orígenes por comuna (todos los vehículos)
# ------------------------------------------------------------

p_total <- mapa_tematico(
  datos     = mapa_total,
  titulo    = "Generación de Viajes por Comuna — Cali",
  subtitulo = "Total de orígenes registrados (todos los modos de transporte)",
  paleta    = "viridis"
)

print(p_total)
Mapa coropleta del total de viajes generados por comuna en Cali

Mapa coropleta del total de viajes generados por comuna en Cali

6.3 Mapas por tipo de vehículo

# ------------------------------------------------------------
# Mapa 2: Orígenes en bicicleta (Tipo vehículo = 1)
# ------------------------------------------------------------

p_bici <- mapa_tematico(
  datos     = mapa_bici,
  titulo    = "Viajes en Bicicleta",
  subtitulo = "Origen por comuna — Tipo de vehículo: Bicicleta (código 1)",
  paleta    = "viridis"
)

print(p_bici)
Viajes generados en bicicleta por comuna

Viajes generados en bicicleta por comuna

# ------------------------------------------------------------
# Mapa 3: Orígenes en moto (Tipo vehículo = 2)
# ------------------------------------------------------------

p_moto <- mapa_tematico(
  datos     = mapa_moto,
  titulo    = "Viajes en Moto",
  subtitulo = "Origen por comuna — Tipo de vehículo: Moto (código 2)",
  paleta    = "magma"
)

print(p_moto)
Viajes generados en moto por comuna

Viajes generados en moto por comuna

# ------------------------------------------------------------
# Mapa 4: Orígenes en automóvil (Tipo vehículo = 3)
# ------------------------------------------------------------

p_auto <- mapa_tematico(
  datos     = mapa_auto,
  titulo    = "Viajes en Automóvil",
  subtitulo = "Origen por comuna — Tipo de vehículo: Automóvil (código 3)",
  paleta    = "plasma"
)

print(p_auto)
Viajes generados en automóvil por comuna

Viajes generados en automóvil por comuna

6.4 Panel comparativo — Los 3 modos juntos

# Calcular el máximo compartido para escala uniforme
max_comun <- max(
  max(mapa_bici$n_viajes, na.rm = TRUE),
  max(mapa_moto$n_viajes, na.rm = TRUE),
  max(mapa_auto$n_viajes, na.rm = TRUE)
)

# Regenerar mapas con escala común (sin ocultar leyenda, patchwork la colecta)
mapa_panel <- function(datos, titulo, paleta) {
  mapa_tematico(datos, titulo, paleta = paleta, lim_sup = max_comun) +
    theme(plot.title = element_text(size = 11))
}

p1 <- mapa_panel(mapa_bici, "Bicicleta (1)", "viridis")
p2 <- mapa_panel(mapa_moto, "Moto (2)",      "magma")
p3 <- mapa_panel(mapa_auto, "Automóvil (3)", "plasma")

# Componer el panel con patchwork
panel_final <- (p1 | p2 | p3) +
  plot_annotation(
    title    = "Generación de Viajes por Modo de Transporte — Comunas de Cali",
    subtitle = paste0("Escala de color comparable entre los 3 modos ",
                      "(máx. = ", scales::comma(max_comun), " viajes)"),
    caption  = "Fuente: Encuesta Origen-Destino Hogares (EODH) — Metro Cali S.A.",
    theme    = theme(
      plot.title    = element_text(face = "bold", size = 15, hjust = 0.5),
      plot.subtitle = element_text(size = 10, hjust = 0.5, color = "grey40"),
      plot.caption  = element_text(size = 8, color = "grey55", hjust = 1)
    )
  )

print(panel_final)
Comparación de orígenes de viaje por modo de transporte privado no motorizado y motorizado

Comparación de orígenes de viaje por modo de transporte privado no motorizado y motorizado


6.5 Tabla resumen

# ------------------------------------------------------------
# Tabla consolidada: viajes por comuna y modo de transporte
# ------------------------------------------------------------

tabla_resumen <- mapa_total %>%
  st_drop_geometry() %>%                    # Eliminar geometría para tabla plana
  select(codigo_comuna_o, n_viajes) %>%
  rename(total = n_viajes) %>%
  left_join(conteo_bici %>% rename(bicicleta = n_viajes), by = "codigo_comuna_o") %>%
  left_join(conteo_moto %>% rename(moto      = n_viajes), by = "codigo_comuna_o") %>%
  left_join(conteo_auto %>% rename(automovil = n_viajes), by = "codigo_comuna_o") %>%
  mutate(across(c(bicicleta, moto, automovil), ~replace(., is.na(.), 0))) %>%
  arrange(desc(total))

cat("Tabla de viajes por comuna y modo de transporte:\n")
## Tabla de viajes por comuna y modo de transporte:
print(tabla_resumen)
##    codigo_comuna_o total bicicleta moto automovil
## 1               02  2313       124 1096       886
## 2               19  2313       115 1036       954
## 3               17  1857       111  886       709
## 4               03  1644        87  726       687
## 5               18  1242        87  613       440
## 6               04  1219        59  588       452
## 7               10  1134        71  556       419
## 8               13  1050        64  460       421
## 9               22   994        52  433       431
## 10              15   990        56  460       385
## 11              08   897        46  441       333
## 12              16   849        67  392       322
## 13              06   814        30  389       319
## 14              09   763        42  327       307
## 15              11   738        42  354       276
## 16              21   703        36  330       276
## 17              01   642        32  307       238
## 18              20   619        36  289       237
## 19              07   600        32  281       234
## 20              14   581        34  261       237
## 21              05   535        29  270       190
## 22              12   265        10  136        93

7. Visualización — Mapas Temáticos de Destino

7.1 Mapa principal — Total de viajes recibidos

# ------------------------------------------------------------
# Mapa principal de destino: total de viajes recibidos por comuna
# ------------------------------------------------------------

p_total_d <- mapa_tematico(
  datos     = mapa_total_d,
  titulo    = "Atracción de Viajes por Comuna — Cali",
  subtitulo = "Total de destinos registrados (todos los modos de transporte)",
  paleta    = "viridis"
)

print(p_total_d)
Mapa coropleta del total de viajes recibidos por comuna en Cali

Mapa coropleta del total de viajes recibidos por comuna en Cali

7.2 Mapas de destino por tipo de vehículo

# ------------------------------------------------------------
# Mapa: Destinos en bicicleta (Tipo vehículo = 1)
# ------------------------------------------------------------

p_bici_d <- mapa_tematico(
  datos     = mapa_bici_d,
  titulo    = "Destinos en Bicicleta",
  subtitulo = "Destino por comuna — Tipo de vehículo: Bicicleta (código 1)",
  paleta    = "viridis"
)

print(p_bici_d)
Viajes recibidos en bicicleta por comuna

Viajes recibidos en bicicleta por comuna

# ------------------------------------------------------------
# Mapa: Destinos en moto (Tipo vehículo = 2)
# ------------------------------------------------------------

p_moto_d <- mapa_tematico(
  datos     = mapa_moto_d,
  titulo    = "Destinos en Moto",
  subtitulo = "Destino por comuna — Tipo de vehículo: Moto (código 2)",
  paleta    = "magma"
)

print(p_moto_d)
Viajes recibidos en moto por comuna

Viajes recibidos en moto por comuna

# ------------------------------------------------------------
# Mapa: Destinos en automóvil (Tipo vehículo = 3)
# ------------------------------------------------------------

p_auto_d <- mapa_tematico(
  datos     = mapa_auto_d,
  titulo    = "Destinos en Automóvil",
  subtitulo = "Destino por comuna — Tipo de vehículo: Automóvil (código 3)",
  paleta    = "plasma"
)

print(p_auto_d)
Viajes recibidos en automóvil por comuna

Viajes recibidos en automóvil por comuna

7.3 Panel comparativo de destino — Los 3 modos juntos

# ------------------------------------------------------------
# Panel de destino: 3 modos con escala de color compartida
# ------------------------------------------------------------

max_comun_d <- max(
  max(mapa_bici_d$n_viajes, na.rm = TRUE),
  max(mapa_moto_d$n_viajes, na.rm = TRUE),
  max(mapa_auto_d$n_viajes, na.rm = TRUE)
)

p1_d <- mapa_panel(mapa_bici_d %>% mutate(n_viajes = n_viajes),
                   "Bicicleta (1)", "viridis") %>%
  {mapa_tematico(mapa_bici_d, "Bicicleta (1)", paleta = "viridis",
                 lim_sup = max_comun_d) +
      theme(plot.title = element_text(size = 11))}

p2_d <- mapa_tematico(mapa_moto_d, "Moto (2)", paleta = "magma",
                      lim_sup = max_comun_d) +
  theme(legend.position = "none", plot.title = element_text(size = 11))

p3_d <- mapa_tematico(mapa_auto_d, "Automóvil (3)", paleta = "plasma",
                      lim_sup = max_comun_d) +
  theme(legend.position = "none", plot.title = element_text(size = 11))

panel_destino <- (p1_d | p2_d | p3_d) +
  plot_annotation(
    title    = "Atracción de Viajes por Modo de Transporte — Comunas de Cali",
    subtitle = paste0("Escala de color comparable entre los 3 modos ",
                      "(máx. = ", scales::comma(max_comun_d), " viajes)"),
    caption  = "Fuente: Encuesta Origen-Destino Hogares (EODH) — Metro Cali S.A.",
    theme    = theme(
      plot.title    = element_text(face = "bold", size = 15, hjust = 0.5),
      plot.subtitle = element_text(size = 10, hjust = 0.5, color = "grey40"),
      plot.caption  = element_text(size = 8, color = "grey55", hjust = 1)
    )
  )

print(panel_destino)
Comparación de destinos de viaje por modo de transporte

Comparación de destinos de viaje por modo de transporte


7.4 Tabla resumen

# ------------------------------------------------------------
# Tabla consolidada: viajes RECIBIDOS por comuna y modo de transporte
# ------------------------------------------------------------
tabla_resumen_d <- mapa_total_d %>%
  st_drop_geometry() %>%
  select(codigo_comuna_o, n_viajes) %>%
  rename(total = n_viajes) %>%
  left_join(conteo_bici_d %>% rename(bicicleta = n_viajes), by = c("codigo_comuna_o" = "codigo_comuna_d")) %>%
  left_join(conteo_moto_d %>% rename(moto      = n_viajes), by = c("codigo_comuna_o" = "codigo_comuna_d")) %>%
  left_join(conteo_auto_d %>% rename(automovil = n_viajes), by = c("codigo_comuna_o" = "codigo_comuna_d")) %>%
  mutate(across(c(bicicleta, moto, automovil), ~replace(., is.na(.), 0))) %>%
  arrange(desc(total))

cat("Tabla de viajes recibidos por comuna y modo de transporte:\n")
## Tabla de viajes recibidos por comuna y modo de transporte:
print(tabla_resumen_d)
##    codigo_comuna_o total bicicleta moto automovil
## 1               02  3867       201 1778      1565
## 2               03  2966       172 1364      1140
## 3               19  2497       133 1171       966
## 4               17  1695       101  764       695
## 5               22  1573        96  773       570
## 6               04  1523        80  691       612
## 7               09  1074        59  521       391
## 8               08   849        47  390       333
## 9               10   765        37  362       299
## 10              16   650        31  291       278
## 11              07   614        36  291       230
## 12              06   577        32  257       214
## 13              13   566        28  289       192
## 14              18   544        29  249       221
## 15              11   487        26  219       206
## 16              15   485        19  232       202
## 17              05   448        40  185       185
## 18              21   437        24  204       166
## 19              14   316        20  150       120
## 20              20   303        22  126       131
## 21              12   210        13  109        71
## 22              01   190        10   92        73

8. Comparación Origen vs. Destino

# ------------------------------------------------------------
# Panel comparativo: Origen vs. Destino — Total (todos los modos)
# Escala compartida entre ambos mapas
# ------------------------------------------------------------

max_total_od <- max(max(mapa_total$n_viajes), max(mapa_total_d$n_viajes))

comp_total_o <- mapa_tematico(mapa_total, "Origen — Total",
                               paleta = "viridis", lim_sup = max_total_od) +
  theme(legend.position = "none", plot.title = element_text(size = 12))

comp_total_d <- mapa_tematico(mapa_total_d, "Destino — Total",
                               paleta = "viridis", lim_sup = max_total_od) +
  theme(legend.position = "bottom", plot.title = element_text(size = 12))

(comp_total_o | comp_total_d) +
  plot_annotation(
    title    = "Generación vs. Atracción de Viajes — Total (todos los modos)",
    subtitle = paste0("Escala compartida (máx. = ", scales::comma(max_total_od), " viajes)"),
    caption  = "Fuente: EODH — Metro Cali S.A.",
    theme    = theme(
      plot.title    = element_text(face = "bold", size = 15, hjust = 0.5),
      plot.subtitle = element_text(size = 10, hjust = 0.5, color = "grey40"),
      plot.caption  = element_text(size = 8, color = "grey55", hjust = 1)
    )
  )
Comparación origen vs. destino — Total de viajes

Comparación origen vs. destino — Total de viajes

# ------------------------------------------------------------
# Panel comparativo: Origen vs. Destino — Bicicleta
# ------------------------------------------------------------

max_bici_od <- max(max(mapa_bici$n_viajes), max(mapa_bici_d$n_viajes))

comp_bici_o <- mapa_tematico(mapa_bici, "Origen — Bicicleta",
                              paleta = "viridis", lim_sup = max_bici_od) +
  theme(legend.position = "none", plot.title = element_text(size = 12))

comp_bici_d <- mapa_tematico(mapa_bici_d, "Destino — Bicicleta",
                              paleta = "viridis", lim_sup = max_bici_od) +
  theme(legend.position = "bottom", plot.title = element_text(size = 12))

(comp_bici_o | comp_bici_d) +
  plot_annotation(
    title    = "Generación vs. Atracción de Viajes — Bicicleta (código 1)",
    subtitle = paste0("Escala compartida (máx. = ", scales::comma(max_bici_od), " viajes)"),
    caption  = "Fuente: EODH — Metro Cali S.A.",
    theme    = theme(
      plot.title    = element_text(face = "bold", size = 15, hjust = 0.5),
      plot.subtitle = element_text(size = 10, hjust = 0.5, color = "grey40"),
      plot.caption  = element_text(size = 8, color = "grey55", hjust = 1)
    )
  )
Comparación origen vs. destino — Bicicleta

Comparación origen vs. destino — Bicicleta

# ------------------------------------------------------------
# Panel comparativo: Origen vs. Destino — Moto
# ------------------------------------------------------------

max_moto_od <- max(max(mapa_moto$n_viajes), max(mapa_moto_d$n_viajes))

comp_moto_o <- mapa_tematico(mapa_moto, "Origen — Moto",
                              paleta = "magma", lim_sup = max_moto_od) +
  theme(legend.position = "none", plot.title = element_text(size = 12))

comp_moto_d <- mapa_tematico(mapa_moto_d, "Destino — Moto",
                              paleta = "magma", lim_sup = max_moto_od) +
  theme(legend.position = "bottom", plot.title = element_text(size = 12))

(comp_moto_o | comp_moto_d) +
  plot_annotation(
    title    = "Generación vs. Atracción de Viajes — Moto (código 2)",
    subtitle = paste0("Escala compartida (máx. = ", scales::comma(max_moto_od), " viajes)"),
    caption  = "Fuente: EODH — Metro Cali S.A.",
    theme    = theme(
      plot.title    = element_text(face = "bold", size = 15, hjust = 0.5),
      plot.subtitle = element_text(size = 10, hjust = 0.5, color = "grey40"),
      plot.caption  = element_text(size = 8, color = "grey55", hjust = 1)
    )
  )
Comparación origen vs. destino — Moto

Comparación origen vs. destino — Moto

# ------------------------------------------------------------
# Panel comparativo: Origen vs. Destino — Automóvil
# ------------------------------------------------------------

max_auto_od <- max(max(mapa_auto$n_viajes), max(mapa_auto_d$n_viajes))

comp_auto_o <- mapa_tematico(mapa_auto, "Origen — Automóvil",
                              paleta = "plasma", lim_sup = max_auto_od) +
  theme(legend.position = "none", plot.title = element_text(size = 12))

comp_auto_d <- mapa_tematico(mapa_auto_d, "Destino — Automóvil",
                              paleta = "plasma", lim_sup = max_auto_od) +
  theme(legend.position = "bottom", plot.title = element_text(size = 12))

(comp_auto_o | comp_auto_d) +
  plot_annotation(
    title    = "Generación vs. Atracción de Viajes — Automóvil (código 3)",
    subtitle = paste0("Escala compartida (máx. = ", scales::comma(max_auto_od), " viajes)"),
    caption  = "Fuente: EODH — Metro Cali S.A.",
    theme    = theme(
      plot.title    = element_text(face = "bold", size = 15, hjust = 0.5),
      plot.subtitle = element_text(size = 10, hjust = 0.5, color = "grey40"),
      plot.caption  = element_text(size = 8, color = "grey55", hjust = 1)
    )
  )
Comparación origen vs. destino — Automóvil

Comparación origen vs. destino — Automóvil