En la presente actividad se trabaja con la Encuesta Origen Destino de Cali de 2015 y con la cartografía de las comunas de la ciudad. El proposito es contar cuántos viajes salen y cuántos llegan a cada una de las 22 comunas, primero con todos los viajes y luego solo con los que se hacen en bicicleta, moto y automóvil, y representar los resultados a traves de mapas. Esta información puede servir para tomar decisiones de movilidad, como saber en qué zonas hace falta infraestructura para la bicicleta.
Para el desarrollo de la actividad 1, se van a utilizar dos fuentes de información: la Encuesta Origen Destino de Cali de 2015, que registra los viajes con su origen, destino, motivo y tipo de vehículo, y la cartografía de las 22 comunas de la ciudad.
library(here)
library(readxl)
library(dplyr)
library(sf)
library(knitr)
library(kableExtra)
library(tidyr)
library(ggplot2)
library(ggspatial)
# estilo común para todas las tablas del documento
tabla <- function(datos, columnas, titulo) {
kable(datos, col.names = columnas, caption = titulo,
format.args = list(big.mark = ".")) |>
kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE, position = "center") |>
row_spec(0, bold = TRUE, background = "#2C3E50", color = "white") |>
column_spec(1, bold = TRUE)
}
ruta_encuesta <- here("Casos", "EncuestaOrigenDestino.xlsx")
ruta_comunas <- here("Casos", "cali", "Comunas.shp")
stopifnot(file.exists(ruta_encuesta), file.exists(ruta_comunas))
La encuesta fue realizada por Metro Cali en 2015 a personas que se movilizaban en vehículo particular. Se aplicó entre el 25 de mayo y el 9 de junio en 35 puntos de la ciudad, y en cada caso se preguntó de dónde venía la persona, hacia dónde iba, qué iba a hacer y en qué vehículo viajaba. Cada registro de la base corresponde a un viaje.
# renombran automáticamente los municipios
encuesta <- suppressWarnings(
read_excel(ruta_encuesta, sheet = "Hoja1", .name_repair = "unique_quiet")
)
dim(encuesta)
## [1] 35054 28
La base tiene 28 variables sobre el lugar y la hora de la encuesta, el origen y el destino del viaje, su motivo y algunas características de la persona, como el estrato, la edad y el sexo. Para el caso se usan cuatro: la comuna de origen y la de destino, que permiten ubicar los viajes en el mapa; el tipo de vehículo, para separar bicicleta, moto y automóvil; y el motivo del viaje, que ayuda a interpretar los resultados.
vars <- c("comuna origen", "comuna destino",
"TIPO DE VEHÍCULO", "¿QUE VA HACER A ESE LUGAR?")
variables <- data.frame(
Variable = c("Comuna de origen", "Comuna de destino",
"Tipo de vehículo", "Motivo del viaje"),
Descripcion = c("Comuna donde empieza el viaje",
"Comuna donde termina el viaje",
"Vehículo en que se realiza el viaje",
"Actividad que se va a realizar en el destino"),
Valores = c("01 a 22 · 0 zona rural · Fuera de Cali",
"01 a 22 · 0 zona rural · Fuera de Cali",
"1 bicicleta · 2 moto · 3 automóvil · otros",
"1 trabajar · 3 estudiar · 6 volver a casa · otros"),
# el tipo de dato y los faltantes se calculan desde la base
Tipo = ifelse(sapply(encuesta[vars], is.character), "Texto", "Numérica"),
Faltantes = sapply(encuesta[vars], function(x) sum(is.na(x))),
row.names = NULL
)
kable(variables,
col.names = c("Variable", "Descripción", "Valores", "Tipo", "Faltantes"),
caption = "Variables de la encuesta utilizadas en el análisis") |>
kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE, position = "center") |>
row_spec(0, bold = TRUE, background = "#2C3E50", color = "white") |>
column_spec(1, bold = TRUE)
| Variable | Descripción | Valores | Tipo | Faltantes |
|---|---|---|---|---|
| Comuna de origen | Comuna donde empieza el viaje | 01 a 22 · 0 zona rural · Fuera de Cali | Texto | 0 |
| Comuna de destino | Comuna donde termina el viaje | 01 a 22 · 0 zona rural · Fuera de Cali | Texto | 0 |
| Tipo de vehículo | Vehículo en que se realiza el viaje | 1 bicicleta · 2 moto · 3 automóvil · otros | Numérica | 115 |
| Motivo del viaje | Actividad que se va a realizar en el destino | 1 trabajar · 3 estudiar · 6 volver a casa · otros | Numérica | 154 |
En total hay 35.054 viajes. Las comunas de origen y destino están completas, pero se almacenan como texto e incluyen, además de las 22 comunas, viajes de la zona rural y de otros municipios que no tienen un polígono en el mapa. El tipo de vehículo tiene 115 registros sin información, que quedan por fuera al filtrar bicicleta, moto y automóvil. Estos ajustes se hacen en la siguiente sección.
La cartografía corresponde a los límites de las 22 comunas del área urbana de Cali en formato shapefile. Esta capa es la base sobre la cual se representan los viajes de la encuesta.
comunas <- st_read(ruta_comunas, quiet = TRUE)
| Característica | Valor |
|---|---|
| Número de polígonos | 22 |
| Tipo de geometría | POLYGON |
| Sistema de referencia | MAGNA_Colombia_Cali |
| Unidades | m |
| Geometrías válidas | Sí |
| Campos | OBJECTID, gid, comuna, nombre |
| Códigos de comuna | 1 a 22 |
# mapa base con el número de cada comuna
par(mar = c(0, 0, 2, 0))
plot(st_geometry(comunas), col = "#EAF2F8", border = "#2C3E50",
main = "Comunas de Cali")
text(st_coordinates(st_point_on_surface(st_geometry(comunas))),
labels = comunas$comuna, cex = 0.7)
La capa tiene 22 polígonos válidos, uno por comuna, en el sistema
MAGNA Colombia Cali con unidades en metros. El campo comuna
identifica cada polígono con un número de 1 a 22, mientras que en la
encuesta las comunas están como texto (“01”, “02”…). Por eso, antes de
unir las dos fuentes, se debe llevar el código de la encuesta al mismo
formato numérico.
Antes de construir los mapas es necesario dejar la información de la encuesta en un formato que se pueda relacionar con la cartografía. Para esto se ajustan los códigos de comuna, se recodifican los tipos de vehículo y se seleccionan los viajes que se van a analizar.
Las comunas de origen y destino se convierten a número para que
coincidan con el campo comuna de la cartografía. Los
valores que no corresponden a una comuna, como “Fuera de Cali”, quedan
sin dato. El tipo de vehículo se recodifica con el nombre de cada
categoría según las convenciones de la encuesta.
# convierte a número solo los valores que son códigos ("02" pasa a 2);
# "Fuera de Cali" queda como NA
a_numero <- function(x) as.integer(ifelse(grepl("^[0-9]+$", x), x, NA))
encuesta_limpia <- encuesta |>
transmute(
comuna_origen = a_numero(`comuna origen`),
comuna_destino = a_numero(`comuna destino`),
vehiculo = case_when(
`TIPO DE VEHÍCULO` == 1 ~ "Bicicleta",
`TIPO DE VEHÍCULO` == 2 ~ "Moto",
`TIPO DE VEHÍCULO` == 3 ~ "Automóvil",
`TIPO DE VEHÍCULO` %in% c(5, 9) ~ "Taxi",
`TIPO DE VEHÍCULO` == 4 ~ "Campero",
`TIPO DE VEHÍCULO` %in% 6:8 ~ "Transporte intermunicipal",
`TIPO DE VEHÍCULO` == 77 ~ "Otro",
.default = "Sin dato"
),
motivo = `¿QUE VA HACER A ESE LUGAR?`
)
encuesta_limpia |>
count(vehiculo, name = "viajes") |>
arrange(desc(viajes)) |>
mutate(porcentaje = round(viajes / sum(viajes) * 100, 1)) |>
tabla(c("Vehículo", "Viajes", "%"),
"Viajes por tipo de vehículo en la base completa")
| Vehículo | Viajes | % |
|---|---|---|
| Moto | 16.077 | 45.9 |
| Automóvil | 14.100 | 40.2 |
| Taxi | 2.029 | 5.8 |
| Bicicleta | 1.731 | 4.9 |
| Transporte intermunicipal | 466 | 1.3 |
| Campero | 459 | 1.3 |
| Sin dato | 115 | 0.3 |
| Otro | 77 | 0.2 |
En la base completa, la moto y el automóvil concentran la mayoría de los viajes, seguidos por el taxi, mientras que la bicicleta representa una proporción pequeña. Para los mapas por modo se toman solo bicicleta, moto y automóvil, que son los tres vehículos definidos en el caso; los demás se mantienen en los mapas generales de origen y destino.
El análisis se enfoca en los viajes internos de la ciudad, es decir, los que inician y terminan en alguna de las 22 comunas urbanas. Se excluyen los viajes con origen o destino en otros municipios y en la zona rural, porque no tienen un polígono en la cartografía. Al usar el mismo grupo de viajes para los mapas de origen y de destino, los resultados se pueden comparar entre sí.
viajes_cali <- encuesta_limpia |>
filter(comuna_origen %in% 1:22, comuna_destino %in% 1:22)
# cuántos viajes quedan en cada paso del filtro
seleccion <- data.frame(
criterio = c("Base completa",
"Origen en una de las 22 comunas",
"Origen y destino en una de las 22 comunas"),
viajes = c(nrow(encuesta_limpia),
sum(encuesta_limpia$comuna_origen %in% 1:22),
nrow(viajes_cali))
)
seleccion$porcentaje <- round(seleccion$viajes / nrow(encuesta_limpia) * 100, 1)
tabla(seleccion, c("Criterio", "Viajes", "% de la base"),
"Viajes seleccionados para el análisis")
| Criterio | Viajes | % de la base |
|---|---|---|
| Base completa | 35.054 | 100.0 |
| Origen en una de las 22 comunas | 28.076 | 80.1 |
| Origen y destino en una de las 22 comunas | 22.151 | 63.2 |
viajes_cali |>
filter(vehiculo %in% c("Bicicleta", "Moto", "Automóvil")) |>
count(vehiculo, name = "viajes") |>
arrange(desc(viajes)) |>
mutate(porcentaje = round(viajes / nrow(viajes_cali) * 100, 1)) |>
tabla(c("Vehículo", "Viajes", "% de los viajes en Cali"),
"Viajes dentro de Cali en los tres modos del caso")
| Vehículo | Viajes | % de los viajes en Cali |
|---|---|---|
| Moto | 10.307 | 46.5 |
| Automóvil | 8.605 | 38.8 |
| Bicicleta | 1.223 | 5.5 |
De los 35.054 viajes de la encuesta, 22.151 (63,2 %) inician y terminan dentro de las comunas de Cali, y este es el grupo con el que se construyen los mapas. La mayor parte de lo que se excluye corresponde a viajes desde o hacia otros municipios del área metropolitana. Dentro de Cali, la moto reúne 10.307 viajes, el automóvil 8.605 y la bicicleta 1.223. Además, 1.484 viajes empiezan y terminan en la misma comuna; estos se mantienen en el análisis porque también hacen parte de la movilidad de cada comuna.
La cartografía de comunas viene en MAGNA Colombia Cali, un sistema de coordenadas local de la ciudad. Para los mapas se reproyecta a MAGNA-SIRGAS / Origen Nacional (EPSG:9377), que es el sistema oficial de proyección para Colombia (IGAC, 2020).
comunas <- st_transform(comunas, crs = 9377)
st_crs(comunas)$Name
## [1] "MAGNA-SIRGAS 2018 / Origen-Nacional"
Para representar los viajes en el mapa se cuenta cuántos salen de cada comuna, en total y en cada uno de los tres modos del caso. Además del número de viajes, se calcula el porcentaje que aporta cada comuna dentro de cada modo, lo que permite comparar la bicicleta con la moto y el automóvil aunque el volumen de viajes sea muy diferente.
# cuenta los viajes por comuna (de origen o de destino) y por modo,
# y calcula el porcentaje que aporta cada comuna dentro de cada columna
resumir_comunas <- function(datos, campo) {
datos |>
group_by(comuna = {{ campo }}) |>
summarise(total = n(),
bicicleta = sum(vehiculo == "Bicicleta"),
moto = sum(vehiculo == "Moto"),
automovil = sum(vehiculo == "Automóvil"),
.groups = "drop") |>
mutate(across(total:automovil, ~ round(.x / sum(.x) * 100, 1),
.names = "pct_{.col}"))
}
# tabla de calor: comunas en filas, modos en columnas y el porcentaje en cada
# celda; las comunas se ordenan de mayor a menor según el total de viajes
grafico_calor <- function(resumen, titulo, subtitulo) {
orden <- paste("Comuna", resumen$comuna[order(resumen$total)])
datos <- resumen |>
select(comuna, pct_total, pct_bicicleta, pct_moto, pct_automovil) |>
pivot_longer(-comuna, names_to = "modo", values_to = "porcentaje") |>
mutate(
modo = factor(modo,
levels = c("pct_total", "pct_bicicleta", "pct_moto", "pct_automovil"),
labels = c("Total", "Bicicleta", "Moto", "Automóvil")),
comuna = factor(paste("Comuna", comuna), levels = orden)
)
ggplot(datos, aes(x = modo, y = comuna, fill = porcentaje)) +
geom_tile(color = "white", linewidth = 1.2) +
geom_text(aes(label = format(porcentaje, decimal.mark = ","),
color = porcentaje > 6.5), size = 3.4) +
scale_fill_gradient(low = "#eef5fd", high = "#184f95", limits = c(0, 18)) +
scale_color_manual(values = c(`FALSE` = "#1f2d3d", `TRUE` = "white")) +
scale_x_discrete(position = "top") +
labs(title = titulo, subtitle = subtitulo, x = NULL, y = NULL,
caption = "Fuente: elaboración propia con base en la Encuesta Origen Destino (Metro Cali, 2015).") +
theme_minimal(base_size = 11) +
theme(panel.grid = element_blank(),
axis.text.x = element_text(face = "bold", size = 11),
plot.title = element_text(face = "bold"),
plot.caption = element_text(color = "grey40", hjust = 0),
legend.position = "none")
}
origen <- resumir_comunas(viajes_cali, comuna_origen)
grafico_calor(origen,
titulo = "Viajes según la comuna de origen",
subtitulo = "Porcentaje de los viajes de cada modo que sale de cada comuna")
Los viajes que salen de las comunas se concentran en pocas zonas: las
comunas 2, 19, 17 y 3 reúnen el 35,6 % de los orígenes, mientras que la
comuna 12 es la que menos viajes genera, con el 1,2 %. Al comparar por
modo, la bicicleta tiene un peso mayor que el total en las comunas 18,
10 y 16; en la comuna 16, por ejemplo, sale el 5,3 % de los viajes en
bicicleta frente al 3,8 % del total. En el automóvil, la comuna 19
supera a la 2 como principal origen, con el 10,7 % de los viajes. Estos
patrones se revisan sobre el mapa en las siguientes secciones.
Con el mismo grupo de viajes se cuenta ahora cuántos llegan a cada comuna. De esta forma se puede ver hacia dónde se dirigen las personas que salen de las comunas de Cali y compararlo con los orígenes.
destino <- resumir_comunas(viajes_cali, comuna_destino)
grafico_calor(destino,
titulo = "Viajes según la comuna de destino",
subtitulo = "Porcentaje de los viajes de cada modo que llega a cada comuna")
Los destinos están más concentrados que los orígenes. Las comunas 2, 3 y 19 reciben el 41 % de los viajes, y solo la comuna 2 recibe el 17 %, mientras que ninguna comuna supera el 10,2 % de los orígenes. Este patrón se repite en los tres modos, con la comuna 2 como principal destino en bicicleta (15,9 %), moto (16,8 %) y automóvil (17,6 %). La comuna 22 también gana peso como destino, con el 7 % de las llegadas frente al 4,4 % de las salidas. En el otro extremo, las comunas 1, 12, 14 y 20 reciben menos del 1,5 % de los viajes cada una.
Para apoyar la interpretación de los destinos se revisa el motivo declarado por las personas encuestadas, es decir, la actividad que iban a realizar en el lugar de llegada.
viajes_cali |>
filter(vehiculo %in% c("Bicicleta", "Moto", "Automóvil")) |>
mutate(motivo = case_when(
motivo == 1 ~ "Ir a trabajar",
motivo == 2 ~ "Asuntos de trabajo",
motivo == 6 ~ "Volver a casa",
motivo == 3 ~ "Estudiar",
.default = "Otros motivos"
)) |>
count(vehiculo, motivo) |>
group_by(vehiculo) |>
mutate(porcentaje = round(n / sum(n) * 100, 1)) |>
select(-n) |>
pivot_wider(names_from = vehiculo, values_from = porcentaje) |>
arrange(desc(Bicicleta)) |>
tabla(c("Motivo", "Automóvil", "Bicicleta", "Moto"),
"Motivo del viaje según el modo (% de los viajes de cada modo)")
| Motivo | Automóvil | Bicicleta | Moto |
|---|---|---|---|
| Ir a trabajar | 42.2 | 55.5 | 51.0 |
| Otros motivos | 26.4 | 17.8 | 16.7 |
| Volver a casa | 14.0 | 14.3 | 13.2 |
| Asuntos de trabajo | 14.9 | 10.2 | 16.7 |
| Estudiar | 2.5 | 2.1 | 2.5 |
Ir a trabajar es el motivo principal en los tres modos, pero pesa más en la bicicleta (55,5 %) y en la moto (51 %) que en el automóvil (42,2 %). En el automóvil tienen mayor participación otros motivos, como trámites, compras o recoger a alguien.
Los conteos de origen y de destino se unen a la capa de comunas
mediante el campo comuna, que después del ajuste de la
sección de depuración tiene el mismo formato numérico en ambas fuentes.
Se construye además una capa de balance, que resta las salidas a las
llegadas de cada comuna: un valor positivo indica que la comuna recibe
más viajes de los que genera, y uno negativo, lo contrario.
mapa_origen <- left_join(comunas, origen, by = "comuna")
mapa_destino <- left_join(comunas, destino, by = "comuna")
mapa_balance <- comunas |>
left_join(select(origen, comuna, salidas = total), by = "comuna") |>
left_join(select(destino, comuna, llegadas = total), by = "comuna") |>
mutate(balance = llegadas - salidas)
# cada capa debe tener 22 polígonos, ninguno sin dato, y conservar
# el total de viajes; el balance de toda la ciudad debe ser cero
data.frame(
capa = c("Origen", "Destino", "Balance"),
poligonos = c(nrow(mapa_origen), nrow(mapa_destino), nrow(mapa_balance)),
sin_dato = c(sum(is.na(mapa_origen$total)), sum(is.na(mapa_destino$total)),
sum(is.na(mapa_balance$balance))),
viajes = c(sum(mapa_origen$total), sum(mapa_destino$total),
sum(mapa_balance$balance))
) |>
tabla(c("Capa", "Polígonos", "Comunas sin dato", "Suma de viajes"),
"Verificación de la unión")
| Capa | Polígonos | Comunas sin dato | Suma de viajes |
|---|---|---|---|
| Origen | 22 | 0 | 22.151 |
| Destino | 22 | 0 | 22.151 |
| Balance | 22 | 0 | 0 |
Los mapas muestran el número de viajes que sale de cada comuna (origen) y que llega a cada comuna (destino). Para cada modo, los dos mapas se presentan juntos y comparten la misma escala, con el fin de comparar las zonas que generan viajes con las que los reciben. Como el volumen de viajes es muy distinto entre modos, cada figura tiene su propia escala; la comparación entre modos se apoya en los porcentajes de las secciones anteriores.
# une origen y destino en una sola capa para dibujarlos lado a lado
mapas <- bind_rows(
mutate(mapa_origen, tipo = "Origen"),
mutate(mapa_destino, tipo = "Destino")
) |>
mutate(tipo = factor(tipo, levels = c("Origen", "Destino")))
# mapa coroplético del número de viajes para la columna indicada;
# origen y destino comparten la misma escala dentro de cada figura
mapa_viajes <- function(columna, titulo) {
ggplot(mapas) +
geom_sf(aes(fill = .data[[columna]]), color = "white", linewidth = 0.4) +
# etiqueta: número de la comuna y cantidad de viajes
geom_sf_text(aes(label = paste0("C", comuna, "\n",
format(.data[[columna]], big.mark = ".")),
color = .data[[columna]] > 0.45 * max(.data[[columna]])),
size = 2.7, lineheight = 0.85, fontface = "bold") +
facet_wrap(~ tipo) +
scale_fill_stepsn(colors = c("#eef5fd", "#9ec5f4", "#5598e7",
"#2a78d6", "#184f95", "#0d366b"),
n.breaks = 6,
labels = function(x) format(x, big.mark = ".", scientific = FALSE),
name = "Número de viajes") +
scale_color_manual(values = c(`FALSE` = "#1f2d3d", `TRUE` = "white"),
guide = "none") +
annotation_scale(location = "bl", width_hint = 0.3, style = "ticks") +
annotation_north_arrow(location = "tr", height = unit(1, "cm"),
width = unit(0.8, "cm"),
style = north_arrow_orienteering(text_size = 7)) +
labs(title = titulo, x = NULL, y = NULL,
caption = paste0(
"Sistema de referencia: MAGNA-SIRGAS / Origen Nacional (EPSG:9377)\n",
"Fuente: elaboración propia con base en la Encuesta Origen Destino ",
"(Metro Cali, 2015) y cartografía de comunas de Cali.\n",
"Autora: Nicoll")) +
theme_void(base_size = 11) +
theme(strip.text = element_text(face = "bold", size = 12,
margin = margin(b = 5)),
plot.title = element_text(face = "bold", size = 13,
margin = margin(b = 8)),
plot.caption = element_text(color = "grey40", hjust = 0, size = 8),
legend.key.height = unit(1.4, "cm"),
legend.title = element_text(size = 9))
}
mapa_viajes("total", "Mapas 1 y 2. Origen y destino de los viajes en Cali")
Los orígenes se distribuyen en buena parte de la ciudad, aunque con mayor intensidad en el norte y el occidente: de las comunas 2 y 19 salen cerca de 2.250 viajes cada una, seguidas por la 17 (1.762) y la 3 (1.610). Los destinos, en cambio, se concentran mucho más. La comuna 2 recibe 3.773 viajes y la 3, que incluye el centro de la ciudad, 2.887; junto con la 19 (2.441) forman el eje hacia el que se dirige gran parte de la movilidad en vehículo particular. Hacia el oriente y en las comunas del occidente los destinos son poco frecuentes: la comuna 1 recibe 187 viajes, la 12 recibe 207 y la 20, 303.
mapa_viajes("bicicleta", "Mapas 3 y 4. Origen y destino de los viajes en bicicleta")
Los viajes en bicicleta salen principalmente de las comunas 2 (122 viajes), 19 (113) y 17 (103), pero a diferencia del total, las comunas del sur y el oriente tienen un peso importante como origen: la comuna 18 genera 85 viajes en bicicleta y la 10, 71, cifras cercanas a las de la comuna 3. Estas comunas, en cambio, reciben pocos viajes en este modo; la comuna 18, por ejemplo, solo recibe 28. Los destinos se concentran en las comunas 2 (194 viajes), 3 (169) y 19 (131), que reúnen el 40 % de las llegadas en bicicleta.
Esto sugiere un patrón de desplazamiento desde el sur y el oriente hacia el centro y el norte de la ciudad. De los 338 viajes en bicicleta que salen de las comunas 10, 13, 15, 16 y 18, el 43 % termina en las comunas 2, 3 o 19. Además, el 55,5 % de los viajes en bicicleta se hace para ir a trabajar, la proporción más alta entre los tres modos, lo que indica que la bicicleta se usa principalmente para desplazamientos laborales.
mapa_viajes("moto", "Mapas 5 y 6. Origen y destino de los viajes en moto")
La moto es el modo con más viajes dentro de la ciudad, por lo que su distribución es muy similar a la del total. Los orígenes se concentran en las comunas 2 (1.063 viajes), 19 (995) y 17 (853), y la comuna 12 es la que menos viajes genera (133). Como destino, sobresalen otra vez las comunas 2 (1.734), 3 (1.333) y 19 (1.152), que reciben el 41 % de los viajes en moto, seguidas por la 22 (766) y la 17 (744).
La diferencia entre salidas y llegadas permite distinguir dos tipos de comunas. Las comunas 2 y 3 reciben cerca de 650 viajes más de los que generan, y la 22 recibe 336 más, por lo que funcionan como zonas de atracción. En cambio, la comuna 18 genera 593 viajes en moto y solo recibe 240, y en la 15 las salidas también duplican a las llegadas, lo que las ubica como zonas de donde salen las personas hacia otros sectores de la ciudad.
mapa_viajes("automovil", "Mapas 7 y 8. Origen y destino de los viajes en automóvil")
En el automóvil, la comuna 19 es el principal origen, con 923 viajes, por encima de la comuna 2 (860); es el único de los tres modos en que esto ocurre. Le siguen las comunas 3 (679) y 17 (662), mientras que la 12 genera apenas 88 viajes. Los destinos mantienen el patrón de los otros modos: las comunas 2 (1.518 viajes), 3 (1.098) y 19 (926) reciben el 41 % de las llegadas en automóvil.
La comuna 19 presenta casi el mismo número de salidas (923) que de llegadas (926), lo que muestra que cumple al mismo tiempo un papel de origen y de destino. Las comunas 2 y 3 vuelven a ser las principales zonas de atracción, con 658 y 419 llegadas más que salidas. En el otro extremo, las comunas 13 y 18 generan más del doble de los viajes que reciben: de la 13 salen 412 viajes en automóvil y llegan 189, y de la 18 salen 433 y llegan 216.
Como complemento, se calcula para cada comuna la diferencia entre los viajes que llegan y los que salen. Un valor positivo indica que la comuna atrae más viajes de los que genera, y uno negativo, que es principalmente una zona de salida.
# clases simétricas alrededor de cero para la escala divergente
mapa_balance <- mapa_balance |>
mutate(clase = cut(balance,
breaks = c(-Inf, -500, -250, -100, 100, 250, 500, 1000, Inf),
labels = c("Menos de -500", "-500 a -250", "-250 a -100",
"-100 a 100", "100 a 250", "250 a 500",
"500 a 1.000", "Más de 1.000")))
ggplot(mapa_balance) +
geom_sf(aes(fill = clase), color = "white", linewidth = 0.4) +
geom_sf_text(aes(label = paste0("C", comuna, "\n", ifelse(balance > 0, "+", ""),
format(balance, big.mark = ".", trim = TRUE)),
color = abs(balance) > 500),
size = 2.7, lineheight = 0.85, fontface = "bold") +
scale_fill_manual(values = c("#a8431a", "#e07b4f", "#f3b99b", "#f1f1ee",
"#c6dbf3", "#86b6ef", "#2a78d6", "#104281"),
drop = FALSE, name = "Llegadas menos salidas") +
scale_color_manual(values = c(`FALSE` = "#1f2d3d", `TRUE` = "white"),
guide = "none") +
annotation_scale(location = "bl", width_hint = 0.3, style = "ticks") +
annotation_north_arrow(location = "tr", height = unit(1, "cm"),
width = unit(0.8, "cm"),
style = north_arrow_orienteering(text_size = 7)) +
labs(title = "Mapa 9. Balance entre llegadas y salidas de viajes por comuna",
subtitle = "Azul: la comuna recibe más viajes de los que genera. Naranja: genera más de los que recibe.",
caption = paste0(
"Sistema de referencia: MAGNA-SIRGAS / Origen Nacional (EPSG:9377)\n",
"Fuente: elaboración propia con base en la Encuesta Origen Destino ",
"(Metro Cali, 2015) y cartografía de comunas de Cali.\n",
"Autora: Nicoll")) +
theme_void(base_size = 11) +
theme(plot.title = element_text(face = "bold", size = 13),
plot.subtitle = element_text(size = 9, margin = margin(b = 8)),
plot.caption = element_text(color = "grey40", hjust = 0, size = 8))
El balance muestra una clara división de la ciudad. Las comunas que atraen viajes forman un eje en el norte y el centro: la comuna 2 recibe 1.523 viajes más de los que genera y la 3, 1.277, seguidas por la 9 (+318) y la 4 (+304). En el sur, la comuna 22 también es una zona de atracción (+576). En el otro extremo, la mayoría de las comunas del oriente y de la ladera generan más viajes de los que reciben; los casos más marcados son la 18 (-682), la 15 (-493), la 13 (-471) y la 1 (-439). Las comunas 5, 7, 8 y 12 están cerca del equilibrio, mientras que la 19, con un balance de +200, cumple al mismo tiempo un papel importante como origen y como destino.
Los viajes salen de muchas zonas de la ciudad, pero se dirigen a pocas: ninguna comuna genera más del 10,2 % de los viajes, mientras que las comunas 2, 3 y 19 reciben el 41 %.
Las comunas 2 y 3 son las principales zonas de atracción, con más de 1.200 llegadas adicionales a sus salidas cada una. Las comunas del oriente y de la ladera, en especial la 18, la 15 y la 13, funcionan sobre todo como zonas de salida.
El patrón se repite en los tres modos. La moto es el modo con más viajes; en el automóvil, la comuna 19 es el principal origen, y en la bicicleta las comunas del sur y del oriente tienen mayor peso como origen.
La bicicleta se usa principalmente para ir a trabajar (55,5 % de sus viajes), y el 43 % de los viajes que salen en bicicleta de las comunas 10, 13, 15, 16 y 18 termina en las comunas 2, 3 o 19. Las conexiones ciclistas entre estos sectores serían las que más usuarios beneficiarían, aunque esto debe contrastarse con la red de ciclorrutas existente.
Los resultados corresponden solo a viajes en vehículo particular en 2015, sin transporte público ni viajes a pie, y dependen en parte de la ubicación de los puntos de encuesta. Por esto deben leerse como patrones de movilidad y no como el total de viajes de la ciudad.