1 Contexto

En el contexto de la movilidad urbana en Cali, se busca comprender y caracterizar los patrones de desplazamiento de las personas considerando exclusivamente aquellos viajes cuyo origen y destino se encuentran dentro de alguna de sus comunas. A partir de información proveniente de encuestas de movilidad se dispone de variables como comuna de origen, comuna de destino, tipo de vehículo utilizado (bicicleta, motocicleta, automóvil, entre otros), así como características adicionales del viaje como duración, motivo o frecuencia.

1.1 Objetivo

El objetivo es analizar de dónde provienen mayoritariamente los desplazamientos dentro de la ciudad, hacia qué comunas se dirigen y cómo se distribuyen estos flujos en términos generales. Adicionalmente, se busca desagregar este comportamiento según el tipo de vehículo, con especial énfasis en los modos bicicleta, motocicleta y automóvil, con el fin de identificar patrones diferenciados de movilidad, posibles concentraciones espaciales y relaciones entre zonas residenciales, comerciales e industriales.

Con esta información, será posible construir una visión integral de la dinámica interna de los desplazamientos urbanos, identificar corredores de alta demanda, detectar posibles desequilibrios en la oferta de infraestructura y evaluar el uso de modos de transporte sostenibles frente a los motorizados. Esto permitirá a los tomadores de decisión diseñar políticas de movilidad más eficientes, promover alternativas de transporte más limpias y seguras, y orientar inversiones en infraestructura vial y ciclorrutas que respondan de manera precisa a las necesidades reales de desplazamiento de la población.

1.2 Preguntas de investigación

En este caso se tienen 8 preguntas a resolver, teniendo en cuenta únicamente los desplazamientos que tienen como origen y destino alguna comuna de Cali:

  1. ¿De qué comuna salen la mayoría de las personas?

  2. ¿A qué comuna llegan la mayoría de las personas?

  3. ¿De qué comuna salen la mayoría de las personas que se movilizan en bicicleta?

  4. ¿De qué comuna salen la mayoría de las personas que se movilizan en moto?

  5. ¿De qué comuna salen la mayoría de las personas que se movilizan en automóvil?

  6. ¿A qué comuna llegan la mayoría de las personas que se movilizan en bicicleta?

  7. ¿A qué comuna llegan la mayoría de las personas que se movilizan en moto?

  8. ¿A qué comuna llegan la mayoría de las personas que se movilizan en automóvil?

1.3 Carga de datos shapefile de comunas de Cali

Los tipos de variable de acuerdo con su naturaleza son los siguientes:

tabla_variables <- data.frame(
  Variable = c("OBJECTID",
               "gid",
               "comuna",
               "nombre",
               "geometry"),
  
  Tipo_estadistico = c("Numérica discreta",
                       "Numérica discreta",
                       "Numérica discreta",
                       "Categórica nominal",
                       "Espacial (geométrica)"),
  
  Codificacion = c(
    "Identificador único del polígono",
    "Identificador geográfico interno (ID GIS)",
    "Número de la comuna (1–22)",
    "Nombre de la comuna",
    "Geometría tipo polígono (coordenadas proyectadas en sistema TMerc)"
  )
)

kable(tabla_variables, caption = "Descripción de las variables del shapefile de comunas de Cali")
Descripción de las variables del shapefile de comunas de Cali
Variable Tipo_estadistico Codificacion
OBJECTID Numérica discreta Identificador único del polígono
gid Numérica discreta Identificador geográfico interno (ID GIS)
comuna Numérica discreta Número de la comuna (1–22)
nombre Categórica nominal Nombre de la comuna
geometry Espacial (geométrica) Geometría tipo polígono (coordenadas proyectadas en sistema TMerc)
path_act<-"C:/Users/User/Documents/2025 PUJ R projects/Modulo 1 - Unidad 1 - AIGE/Casos/"

comunas<-st_read("C:/Users/User/Documents/2025 PUJ R projects/Modulo 1 - Unidad 1 - AIGE/Casos/cali/Comunas.shp")
## Reading layer `Comunas' from data source 
##   `C:\Users\User\Documents\2025 PUJ R projects\Modulo 1 - Unidad 1 - AIGE\Casos\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
summary(comunas)
##     OBJECTID          gid             comuna         nombre         
##  Min.   : 1.00   Min.   : 89.00   Min.   : 1.00   Length:22         
##  1st Qu.: 6.25   1st Qu.: 94.25   1st Qu.: 6.25   Class :character  
##  Median :11.50   Median : 99.50   Median :11.50   Mode  :character  
##  Mean   :11.50   Mean   : 99.50   Mean   :11.50                     
##  3rd Qu.:16.75   3rd Qu.:104.75   3rd Qu.:16.75                     
##  Max.   :22.00   Max.   :110.00   Max.   :22.00                     
##           geometry 
##  POLYGON      :22  
##  epsg:NA      : 0  
##  +proj=tmer...: 0  
##                    
##                    
## 
plot(comunas)

El objeto corresponde a un SpatialPolygonsDataFrame (.shp) que contiene la delimitación geográfica de las comunas urbanas de la ciudad.

  • Número de observaciones (registros): 22 (una por cada comuna)
  • Número de variables: 4 atributos + 1 componente espacial (geometry)
  • Variables: OBJECTID, gid, comuna, nombre y geometría
  • Valores faltantes: No se reportan valores faltantes en los atributos.

1.4 Carga de datos de encuesta de movilidad

Por su parte, la tabla corresponde a una encuesta de movilidad que recoge información detallada sobre los desplazamientos de los individuos.

  • Número de observaciones (registros): 35.054
  • Número de variables: 25
  • Tipo de datos: Mixto (numéricos, categóricos, fechas y horas)
tabla_variables_2 <- data.frame(
  Variable = c("FECHA",
               "ID_ESTACION",
               "ESTACION",
               "ACCESO",
               "MOVIMIENTO",
               "HORA_ENCUESTA",
               "MUNICIPIO",
               "UBICACION_ORIGEN",
               "CODIGO_ORIGEN_SDG",
               "ACTIVIDAD_ORIGEN",
               "UBICACION_DESTINO",
               "CODIGO_DESTINO_SDG",
               "ACTIVIDAD_DESTINO",
               "ESTRATO",
               "DISPONIBILIDAD_VEHICULO",
               "ANTES",
               "DESPUES",
               "EDAD",
               "SEXO",
               "PERSONAS_EN_VEHICULO",
               "TIPO_VEHICULO",
               "TIPO_VIAJERO",
               "COMUNA_ORIGEN",
               "COMUNA_DESTINO",
               "INTRACOMUNA"),
  
  Tipo_estadistico = c("Fecha",
                       "Numérica discreta",
                       "Categórica nominal",
                       "Categórica nominal",
                       "Categórica nominal",
                       "Hora",
                       "Categórica nominal",
                       "Categórica nominal",
                       "Categórica nominal",
                       "Ordinal",
                       "Categórica nominal",
                       "Categórica nominal",
                       "Ordinal",
                       "Ordinal",
                       "Ordinal",
                       "Ordinal",
                       "Binaria",
                       "Numérica discreta",
                       "Categórica nominal",
                       "Numérica discreta",
                       "Categórica nominal",
                       "Categórica nominal",
                       "Categórica nominal",
                       "Categórica nominal",
                       "Binaria"),
  
  Codificacion = c(
    "Fecha de realización de la encuesta",
    "Identificador de la estación de aforo",
    "Nombre de la estación",
    "Tipo de acceso (entrada/salida)",
    "Tipo de movimiento registrado",
    "Hora en que se realizó la encuesta",
    "Municipio donde se realiza la encuesta",
    "Descripción geográfica del origen (dirección, barrio, hito, etc.)",
    "Código estandarizado del origen (SDG)",
    "Actividad realizada en el origen (codificada)",
    "Descripción geográfica del destino",
    "Código estandarizado del destino (SDG)",
    "Actividad a realizar en el destino (codificada)",
    "Estrato socioeconómico (1–6)",
    "Disponibilidad de vehículo (0=No, valores mayores indican disponibilidad/tipo)",
    "Frecuencia o condición previa (escala categórica)",
    "Cambio posterior (0=No, 1=Sí)",
    "Edad del encuestado en años",
    "Sexo (1=Masculino, 2=Femenino)",
    "Número de personas en el vehículo",
    "Tipo de vehículo (codificado: bicicleta, moto, automóvil, etc.)",
    "Tipo de viajero (clasificación del encuestado)",
    "Comuna de origen",
    "Comuna de destino",
    "Indicador de viaje intracomunal (0=No, 1=Sí)"
  )
)

kable(tabla_variables_2, caption = "Descripción de las variables de la encuesta origen-destino")
Descripción de las variables de la encuesta origen-destino
Variable Tipo_estadistico Codificacion
FECHA Fecha Fecha de realización de la encuesta
ID_ESTACION Numérica discreta Identificador de la estación de aforo
ESTACION Categórica nominal Nombre de la estación
ACCESO Categórica nominal Tipo de acceso (entrada/salida)
MOVIMIENTO Categórica nominal Tipo de movimiento registrado
HORA_ENCUESTA Hora Hora en que se realizó la encuesta
MUNICIPIO Categórica nominal Municipio donde se realiza la encuesta
UBICACION_ORIGEN Categórica nominal Descripción geográfica del origen (dirección, barrio, hito, etc.)
CODIGO_ORIGEN_SDG Categórica nominal Código estandarizado del origen (SDG)
ACTIVIDAD_ORIGEN Ordinal Actividad realizada en el origen (codificada)
UBICACION_DESTINO Categórica nominal Descripción geográfica del destino
CODIGO_DESTINO_SDG Categórica nominal Código estandarizado del destino (SDG)
ACTIVIDAD_DESTINO Ordinal Actividad a realizar en el destino (codificada)
ESTRATO Ordinal Estrato socioeconómico (1–6)
DISPONIBILIDAD_VEHICULO Ordinal Disponibilidad de vehículo (0=No, valores mayores indican disponibilidad/tipo)
ANTES Ordinal Frecuencia o condición previa (escala categórica)
DESPUES Binaria Cambio posterior (0=No, 1=Sí)
EDAD Numérica discreta Edad del encuestado en años
SEXO Categórica nominal Sexo (1=Masculino, 2=Femenino)
PERSONAS_EN_VEHICULO Numérica discreta Número de personas en el vehículo
TIPO_VEHICULO Categórica nominal Tipo de vehículo (codificado: bicicleta, moto, automóvil, etc.)
TIPO_VIAJERO Categórica nominal Tipo de viajero (clasificación del encuestado)
COMUNA_ORIGEN Categórica nominal Comuna de origen
COMUNA_DESTINO Categórica nominal Comuna de destino
INTRACOMUNA Binaria Indicador de viaje intracomunal (0=No, 1=Sí)
EncuestaOrigenDestino <- read_excel("C:/Users/User/Documents/2025 PUJ R projects/Modulo 1 - Unidad 1 - AIGE/Casos/EncuestaOrigenDestino.xlsx")
skim(EncuestaOrigenDestino)
Data summary
Name EncuestaOrigenDestino
Number of rows 35054
Number of columns 28
_______________________
Column type frequency:
character 13
logical 3
numeric 10
POSIXct 2
________________________
Group variables None

Variable type: character

skim_variable n_missing complete_rate min max empty n_unique whitespace
ESTACIÓN 0 1 20 42 0 35 0
ACCESO 0 1 3 9 0 4 0
MOVIMIENTO 0 1 5 5 0 4 0
MUNICIPIO…7 38 1 4 22 0 84 0
DEPARTAMENTO / LOCALIDAD / COMUNA / DISTRITO / BARRIO / VEREDA / HITO / DIRECCIÓN…8 0 1 2 43 0 7573 0
Codigo Origen_SDG 0 1 2 7 0 547 0
MUNICIPIO…11 41 1 4 22 0 69 0
DEPARTAMENTO / LOCALIDAD / COMUNA / DISTRITO / BARRIO / VEREDA / HITO / DIRECCIÓN…12 1 1 2 39 0 7018 0
Codigo Destino_SDG 0 1 2 7 0 549 0
TIPO DE VIAJERO 129 1 1 1 0 2 0
comuna origen 0 1 1 13 0 24 0
comuna destino 0 1 1 13 0 24 0
Intracomuna 0 1 1 2 0 3 0

Variable type: logical

skim_variable n_missing complete_rate mean count
OTRO ¿CUÁL?…17 35054 0 NaN :
DESPUES 35001 0 1 TRU: 53
OTRO ¿CUÁL?…24 35054 0 NaN :

Variable type: numeric

skim_variable n_missing complete_rate mean sd p0 p25 p50 p75 p100 hist
ID ESTACIÓN 0 1.00 14.70 8.01 1 9 14 22 30 ▆▇▆▆▅
¿QUE ESTABA HACIENDO EN ESE LUGAR? 383 0.99 5.56 7.21 1 2 6 6 77 ▇▁▁▁▁
¿QUE VA HACER A ESE LUGAR? 154 1.00 4.68 10.02 1 1 2 6 77 ▇▁▁▁▁
ESTRATO EN SU VIVIENDA 1231 0.96 2.83 1.18 1 2 3 3 6 ▇▇▂▁▁
¿DISPONIA DE UN VEHÍCULO PARA REALIZAR ESTE DESPLAZAMIENTO? 18189 0.48 0.25 0.78 0 0 0 0 5 ▇▁▁▁▁
ANTES 34919 0.00 3.78 3.18 1 2 3 4 18 ▇▁▁▁▁
EDAD 479 0.99 38.02 11.42 12 29 37 45 91 ▂▇▃▁▁
SEXO 731 0.98 1.79 0.40 1 2 2 2 2 ▂▁▁▁▇
PERSONAS EN EL VEHÍCULO 118 1.00 1.68 2.32 1 1 1 2 76 ▇▁▁▁▁
TIPO DE VEHÍCULO 115 1.00 2.79 3.63 1 2 2 3 77 ▇▁▁▁▁

Variable type: POSIXct

skim_variable n_missing complete_rate min max median n_unique
FECHA 0 1 2015-05-04 2015-06-09 00:00:00 2015-05-28 00:00:00 14
Hora de Encuesta 0 1 1899-12-31 1899-12-31 12:29:00 1899-12-31 09:07:00 389

Se identifican faltantes relevantes en varias variables clave:

  • ACTIVIDAD_ORIGEN: 383
  • ACTIVIDAD_DESTINO: 154
  • ESTRATO: 1.231
  • DISPONIBILIDAD_VEHICULO: 18.189 (>50%)
  • ANTES: 34.919
  • DESPUES: 35.001
  • EDAD: 479
  • SEXO: 731
  • PERSOS_EN_VEHICULO: 118
  • -TIPO_VEHICULO: 115

Se observa que es necesario realizar algunas depuraciones previo a dar respuesta al problema planteado.

1.5 Limpieza y recodificación

La correcta clasificación de las variables permite diferenciar entre variables nominales, ordinales y numéricas, lo cual es fundamental para la especificación del modelo de datos. En particular, las variables ordinales fueron tratadas respetando su estructura jerárquica, evitando su incorrecta transformación en variables nominales, lo que podría generar pérdida de información relevante. Una vez codificadas correctamente se procede a realizar el procesamiento de datos.

# RECODIFICACIÓN COMPLETA - ENCUESTA ORIGEN DESTINO

# Copia de seguridad
encuesta2 <- EncuestaOrigenDestino


library(dplyr)

# 1. VARIABLES ESPACIALES Y DE IDENTIFICACIÓN

encuesta2 <- encuesta2 %>%
  mutate(
    FECHA = as.Date(FECHA),
    ID_ESTACION = as.numeric(`ID ESTACIÓN`),
    ESTACION = as.factor(ESTACIÓN),
    MUNICIPIO = as.factor(MUNICIPIO...7)
  )


# 2. VARIABLES DE MOVILIDAD (ORIGEN - DESTINO)

encuesta2 <- encuesta2 %>%
  mutate(
    MOVIMIENTO = factor(MOVIMIENTO,
                        levels = c(1,2,3,4),
                        labels = c("Norte-Sur",
                                   "Sur-Norte",
                                   "Occidente-Oriente",
                                   "Oriente-Occidente")),

    COMUNA_ORIGEN = as.factor(`comuna origen`),
    COMUNA_DESTINO = as.factor(`comuna destino`),

    INTRACOMUNA = factor(Intracomuna,
                         levels = c("No","Si"),
                         labels = c("Intercomunal","Intracomunal"))
  )


# 3. VARIABLES DE ACTIVIDAD (ORIGEN Y DESTINO)

encuesta2 <- encuesta2 %>%
  mutate(
    ACTIVIDAD_ORIGEN = factor(`¿QUE ESTABA HACIENDO EN ESE LUGAR?` ,
                              levels = c(1:13,77),
                              labels = c("Trabajando",
                                         "Asuntos de Trabajo",
                                         "Estudiando",
                                         "Salud",
                                         "Visita",
                                         "Casa",
                                         "Acompañar",
                                         "Encargos",
                                         "Comer",
                                         "Compras",
                                         "Trámites",
                                         "Recreación",
                                         "Buscar trabajo",
                                         "Otro")),

    ACTIVIDAD_DESTINO = factor(`¿QUE VA HACER A ESE LUGAR?`,
                               levels = c(1:13,77),
                               labels = c("Trabajar",
                                          "Asuntos de Trabajo",
                                          "Estudiar",
                                          "Salud",
                                          "Visita",
                                          "Casa",
                                          "Acompañar",
                                          "Encargos",
                                          "Comer",
                                          "Compras",
                                          "Trámites",
                                          "Recreación",
                                          "Buscar trabajo",
                                          "Otro"))
  )


# 4. VARIABLES SOCIOECONÓMICAS

encuesta2 <- encuesta2 %>%
  mutate(
    ESTRATO = factor(`ESTRATO EN SU VIVIENDA`,
                     levels = 1:6,
                     labels = c("Bajo bajo","Bajo","Medio bajo",
                                "Medio","Medio alto","Alto"),
                     ordered = TRUE),

    EDAD = as.numeric(EDAD),

    SEXO = factor(SEXO,
                  levels = c(1,2),
                  labels = c("Femenino","Masculino"))
  )


# 5. DISPONIBILIDAD Y USO DE VEHÍCULO

encuesta2 <- encuesta2 %>%
  mutate(
    DISPONIBILIDAD_VEHICULO = factor(`¿DISPONIA DE UN VEHÍCULO PARA REALIZAR ESTE DESPLAZAMIENTO?`,
                                     levels = c(0,1,2,3,4,5),
                                     labels = c("No motorizado",
                                                "Moto",
                                                "Vehículo privado",
                                                "Campero",
                                                "Taxi",
                                                "Otro")),

    PERSONAS_EN_VEHICULO = as.numeric(`PERSONAS EN EL VEHÍCULO`),

    TIPO_VEHICULO = factor(`TIPO DE VEHÍCULO`,
                           levels = c(1:9,77),
                           labels = c("Bicicleta",
                                      "Moto",
                                      "Automóvil",
                                      "Campero",
                                      "Taxi",
                                      "Intermunicipal bus",
                                      "Buseta",
                                      "Van",
                                      "Taxi blanco",
                                      "Otro"))
  )


# 6. VARIABLES DE VIAJE Y VIAJERO

encuesta2 <- encuesta2 %>%
  mutate(
    TIPO_VIAJERO = factor(`TIPO DE VIAJERO`,
                          levels = c(1,2),
                          labels = c("Conductor","Pasajero"))
  )

2 Procesamiento de Datos

2.1 Construcción del dataset analítico (OD Cali)

En este paso se filtran únicamente los registros correspondientes a viajes que tienen como origen y destino una comuna de Cali.

od_cali  <- encuesta2 %>%
  filter(
    !is.na(COMUNA_ORIGEN),
    !is.na(COMUNA_DESTINO),
   COMUNA_ORIGEN!="Fuera de Cali",
   COMUNA_DESTINO!="Fuera de Cali") 

2.2 Enfoque metodológico para la construcción de flujos agregados

El análisis se fundamenta en un enfoque de agregación espacial de tipo origen-destino (OD), en el cual cada registro individual de la encuesta es interpretado como una realización de un flujo entre dos unidades geográficas discretas (comunas).

A diferencia de un conteo simple de viajes, en este estudio se incorpora la variable PERSONAS_EN_VEHICULO, con el fin de aproximar el número efectivo de individuos que realizan cada desplazamiento. De esta forma, la unidad de análisis corresponde a personas movilizadas y no únicamente a viajes observados.

Formalmente, sea \(i\) la comuna de origen y \(j\) la comuna de destino. El flujo total de personas entre ambas comunas se define como:

\[ T_{ij} = \sum_{k=1}^{N} P_k \cdot \mathbf{1}(O_k = i, D_k = j) \]

donde:

  • \(P_k\) corresponde al número de personas en el vehículo en el viaje \(k\)
  • \(\mathbf{1}(\cdot)\) es una función indicadora que toma valor 1 cuando el viaje \(k\) ocurre entre \(i\) y \(j\)
  • \(N\) es el total de registros de la encuesta

A partir de esta estructura se derivan dos métricas clave:

Producción de viajes (outflows):

\[ T_i^{out} = \sum_j T_{ij} \]

Atracción de viajes (inflows):

\[ T_j^{in} = \sum_i T_{ij} \]

Este enfoque permite identificar el rol funcional de cada comuna dentro del sistema urbano —como generadora, receptora o equilibrada— considerando no solo la frecuencia de desplazamientos, sino también la intensidad poblacional de los mismos.

od_modes <- od_cali %>%
  filter(TIPO_VEHICULO %in% c("Bicicleta", "Moto", "Automóvil"))

2.2.1 Flujos de salida

salida_modos <- od_cali %>%
  filter(TIPO_VEHICULO %in% c("Bicicleta","Moto","Automóvil")) %>%
  group_by(COMUNA_ORIGEN, TIPO_VEHICULO) %>%
  summarise(viajes = sum(PERSONAS_EN_VEHICULO,na.rm=T), .groups = "drop") %>%
  pivot_wider(
    names_from = TIPO_VEHICULO,
    values_from = viajes,
    values_fill = 0
  ) %>%
  rename(comuna = COMUNA_ORIGEN,
    viajes_bici = Bicicleta,
    viajes_moto = Moto,
    viajes_auto = Automóvil
  )
top_comuna_salida <- flujos_salida %>%
  slice(1)
ranking_salida <- flujos_salida %>%
  mutate(
    porcentaje = viajes_salida / sum(viajes_salida) * 100
  )
#ranking_salida
ggplot(ranking_salida,
       aes(x = reorder(COMUNA_ORIGEN, viajes_salida),
           y = viajes_salida)) +
  
  geom_col(fill = "salmon") +

  
  geom_text(aes(label = paste0(viajes_salida, "  viajes - (", round(porcentaje, 1), "%)")),
          position = position_stack(vjust = 0.5),
          color = "black",
          size = 3)+
  
  coord_flip() +
  
  labs(
    title = "Flujos de salida por comuna (Cali)",
    x = "Comuna de origen",
    y = "Número de viajes"
  ) +
  
  theme_minimal()

2.2.2 Flujos modales – ORIGEN (salida o producción)

flujos_modales_origen <- od_modes %>%
  group_by(COMUNA_ORIGEN, TIPO_VEHICULO) %>%
  summarise(viajes = sum(PERSONAS_EN_VEHICULO,na.rm=T), .groups = "drop") %>%
  group_by(TIPO_VEHICULO) %>%
  mutate(porcentaje = viajes / sum(viajes) * 100) %>%
  ungroup()
ggplot(flujos_modales_origen,
       aes(x = reorder(COMUNA_ORIGEN, viajes),
           y = viajes,
           fill = TIPO_VEHICULO)) +
  geom_col(position = "dodge") +
  coord_flip() +
  labs(
    title = "Producción de viajes por comuna y modo (Cali)",
    x = "Comuna de origen",
    y = "Número de viajes",
    fill = "Modo"
  ) +
  theme_minimal()

2.2.3 Flujos de llegada

llegada_modos <- od_cali %>%
  filter(TIPO_VEHICULO %in% c("Bicicleta","Moto","Automóvil")) %>%
  group_by(COMUNA_DESTINO, TIPO_VEHICULO) %>%
  summarise(viajes = sum(PERSONAS_EN_VEHICULO,na.rm=T), .groups = "drop") %>%
  tidyr::pivot_wider(
    names_from = TIPO_VEHICULO,
    values_from = viajes,
    values_fill = 0
  ) %>%
  rename(comuna = COMUNA_DESTINO,
         llegadas_bici = Bicicleta,
         llegadas_moto = Moto,
         llegadas_auto = Automóvil)
flujos_llegada <- od_cali %>%
  group_by(COMUNA_DESTINO) %>%
  summarise(
    viajes_llegada = sum(PERSONAS_EN_VEHICULO,na.rm=T),
    .groups = "drop"
  ) %>%
  arrange(desc(viajes_llegada))
ranking_llegada <- flujos_llegada %>%
  mutate(
    porcentaje = viajes_llegada / sum(viajes_llegada) * 100
  ) %>%
  arrange(desc(viajes_llegada))
#ranking_llegada
ggplot(ranking_llegada,
       aes(x = reorder(COMUNA_DESTINO, viajes_llegada),
           y = viajes_llegada)) +
  
  geom_col(fill = "lightblue") +
  
  geom_text(aes(label = paste0(viajes_llegada, "  viajes - (", round(porcentaje, 1), "%)")),
          position = position_stack(vjust = 0.5),
          color = "black",
          size = 3)+
  
  coord_flip() +
  
  labs(
    title = "Flujos de llegada por comuna (Cali)",
    x = "Comuna de destino",
    y = "Número de viajes"
  ) +
  
  theme_minimal()

2.2.4 Flujos modales – DESTINO (llegada o atracción)

flujos_modales_destino <- od_modes %>%
  group_by(COMUNA_DESTINO, TIPO_VEHICULO) %>%
  summarise(viajes = sum(PERSONAS_EN_VEHICULO), .groups = "drop") %>%
  group_by(TIPO_VEHICULO) %>%
  mutate(porcentaje = viajes / sum(viajes) * 100) %>%
  ungroup()

ggplot(flujos_modales_destino,
       aes(x = reorder(COMUNA_DESTINO, viajes),
           y = viajes,
           fill = TIPO_VEHICULO)) +
  geom_col(position = "dodge") +
  coord_flip() +
  labs(
    title = "Atracción de viajes por comuna y modo (Cali)",
    x = "Comuna de destino",
    y = "Número de viajes",
    fill = "Modo"
  ) +
  theme_minimal()

2.2.5 Construcción del objeto espacial enriquecido (sf) con métricas OD completas

Con el siguiente bloque de código se realiza la integración espacial de indicadores de movilidad.

Con esto, se pasa de datos individuales (encuesta) a métricas agregadas por unidad territorial integradas en una estructura geográfica.

comunas_map <- comunas %>%
  mutate(comuna = str_pad(as.character(comuna), width = 2, pad = "0")) %>%
  left_join(flujos_salida, by = c("comuna"="COMUNA_ORIGEN")) %>%
  left_join(salida_modos, by = "comuna") %>%
  left_join(flujos_llegada, by = c("comuna"="COMUNA_DESTINO")) %>%
  left_join(llegada_modos, by = "comuna")%>%
  mutate(
    saldo = viajes_salida - viajes_llegada
  )


comunas_map <- comunas_map %>%
  mutate(
    # Totales
    prop_salida = viajes_salida / sum(viajes_salida) * 100,
    prop_llegada = viajes_llegada / sum(viajes_llegada) * 100,

    # Modos salida
    prop_bici = viajes_bici / sum(viajes_bici) * 100,
    prop_moto = viajes_moto / sum(viajes_moto) * 100,
    prop_auto = viajes_auto / sum(viajes_auto) * 100,

    # Modos llegada
    prop_lleg_bici = llegadas_bici / sum(llegadas_bici) * 100,
    prop_lleg_moto = llegadas_moto / sum(llegadas_moto) * 100,
    prop_lleg_auto = llegadas_auto / sum(llegadas_auto) * 100
  )
head(comunas_map)
## Simple feature collection with 6 features and 21 fields
## Geometry type: POLYGON
## Dimension:     XY
## Bounding box:  xmin: 1053868 ymin: 863572.5 xmax: 1066087 ymax: 878628.1
## Projected CRS: MAGNA_Colombia_Cali
##   OBJECTID gid comuna    nombre viajes_salida viajes_bici viajes_moto
## 1        1 107     02  Comuna 2          3730         124        1289
## 2        2 108     01  Comuna 1          1103          32         360
## 3        3 109     03  Comuna 3          2638          87         851
## 4        4 110     19 Comuna 19          3829         115        1235
## 5        5 103     15 Comuna 15          1635          56         552
## 6        6 104     17 Comuna 17          2999         109        1051
##   viajes_auto viajes_llegada llegadas_bici llegadas_moto llegadas_auto
## 1        1406           6059           201          2099          2611
## 2         363            336            10           114           127
## 3        1133           4982           172          1624          1868
## 4        1518           4000           132          1403          1576
## 5         621            805            19           276           324
## 6        1143           2856           101           913          1133
##                         geometry saldo prop_salida prop_llegada prop_bici
## 1 POLYGON ((1059648 874236.3,... -2329   10.038215   16.4409953  9.841270
## 2 POLYGON ((1054094 875172.8,...   767    2.968405    0.9117304  2.539683
## 3 POLYGON ((1061757 874615.5,... -2344    7.099413   13.5185738  6.904762
## 4 POLYGON ((1057817 873269.4,...  -171   10.304645   10.8539332  9.126984
## 5 POLYGON ((1065485 869864.1,...   830    4.400129    2.1843541  4.444444
## 6 POLYGON ((1061675 868320.9,...   143    8.070940    7.7497083  8.650794
##   prop_moto prop_auto prop_lleg_bici prop_lleg_moto prop_lleg_auto
## 1 10.222046  9.757113     16.0287081     16.8270002     18.1105639
## 2  2.854877  2.519084      0.7974482      0.9139009      0.8809045
## 3  6.748612  7.862595     13.7161085     13.0190797     12.9569259
## 4  9.793814 10.534351     10.5263158     11.2473946     10.9315392
## 5  4.377478  4.309507      1.5151515      2.2126022      2.2473469
## 6  8.334655  7.931992      8.0542265      7.3192240      7.8587778

Con esta base de datos enriquedica se procede a realizar la representación gráfica de los flujos de las comunas para dar respuesta a las preguntas de investigación.

tema_mapa <- theme_minimal() +
  theme(
    plot.title = element_text(face = "bold", size = 12),
    legend.position = "right"
  )
mapa_etiquetado <- function(data, fill_var, prop_var, titulo, escala_low, escala_high) {
  
  ggplot(data) +
    geom_sf(aes(fill = {{fill_var}}), color = "gray85") +
    
    geom_sf_label(
      aes(label = paste0(
        "Comuna: ", comuna,
        "\n #:", scales::comma({{fill_var}}),
        "\n prop: (", round({{prop_var}}, 1), "%)"
      )),
      size = 2.5,
      label.size = 0.3,
      fill = "white",
      alpha = 0.8
    ) +
    
    scale_fill_gradient(low = escala_low, high = escala_high) +
    
    labs(title = titulo, fill = "Viajes") +
    tema_mapa
}

3 Representación espacial de los flujos

Con el fin de capturar la heterogeneidad espacial de los patrones de movilidad, se emplea cartografía temática basada en polígonos (choropleth maps), donde la intensidad del color representa la magnitud de los flujos agregados.

Adicionalmente, se incorporan etiquetas que combinan:

  • Valores absolutos de viajes
  • Participación relativa (%)

Esto permite una lectura simultánea de escala y peso relativo, evitando sesgos derivados del tamaño poblacional de las comunas.

3.1 Pregunta 1. ¿De qué comuna salen la mayoría de las personas?

La producción de viajes presenta una alta concentración en pocas comunas, destacándose las comunas 02 y 19 como principales emisoras, cada una con cerca del 10% del total. Les siguen las comunas 17 y 03, que mantienen participaciones relevantes pero ya en un segundo nivel. A partir de ahí, la distribución muestra una caída progresiva, evidenciando una estructura jerárquica en la generación de viajes. Este patrón sugiere la existencia de zonas residenciales densas que funcionan como principales focos emisores dentro del sistema de movilidad urbana.

mapa_etiquetado(
  comunas_map,
  viajes_salida,
  prop_salida,
  "Producción total de viajes por comuna",
  "#fde0dd", "#f768a1"
)

3.2 Pregunta 2. ¿A qué comuna llegan la mayoría de las personas?

La atracción de viajes está aún más concentrada que la producción, con la comuna 02 captando más del 16% del total, lo que la posiciona como principal nodo de centralidad urbana. Le siguen las comunas 03 y 19, consolidando un eje de alta recepción asociado a actividades económicas y de servicios. A partir de estas, la participación disminuye de forma marcada, evidenciando una estructura jerárquica de destinos. Este patrón es consistente con la presencia de polos funcionales que concentran empleo, comercio y servicios dentro de la ciudad.

mapa_etiquetado(
  comunas_map,
  viajes_llegada,
  prop_llegada,
  "Atracción total de viajes por comuna",
  "#deebf7", "#4292c6"
)

3.3 🚲 Pregunta 3. ¿De qué comuna salen la mayoría de las personas que se movilizan en bicicleta?

La producción de viajes en bicicleta se concentra en un grupo reducido de comunas, destacándose las comunas 02 y 19 como principales emisoras. Les siguen las comunas 17, 03 y 18 con niveles relativamente cercanos, lo que sugiere un patrón de distribución menos disperso que otros modos. Este comportamiento es consistente con la naturaleza de la bicicleta como modo de corta distancia, asociado a entornos urbanos con condiciones favorables de conectividad local.

flujos_bici <- od_modes %>%
  filter(TIPO_VEHICULO == "Bicicleta") %>%
  group_by(COMUNA_ORIGEN) %>%
  summarise(viajes = sum(PERSONAS_EN_VEHICULO,na.rm=T), .groups = "drop") %>%
  arrange(desc(viajes))
head(flujos_bici)
## # A tibble: 6 × 2
##   COMUNA_ORIGEN viajes
##   <fct>          <dbl>
## 1 02               124
## 2 19               115
## 3 17               109
## 4 03                87
## 5 18                87
## 6 10                71
mapa_etiquetado(
  comunas_map,
  viajes_bici,
  prop_bici,
  "Producción de viajes - Bicicleta",
  "#e5f5e0", "#66c2a4"
)

3.4 🏍 Pregunta 4. ¿De qué comuna salen la mayoría de las personas que se movilizan en moto?

La producción de viajes en motocicleta muestra una alta concentración en las comunas 02 y 19, seguidas por la 17 y la 03, lo que refleja una estructura jerárquica similar a la observada en el total de viajes. A diferencia de la bicicleta, la moto presenta mayor volumen y dispersión, evidenciando su capacidad para cubrir distancias más largas. Este patrón sugiere un uso intensivo en zonas con alta demanda de movilidad y posibles limitaciones en la oferta de transporte público.

flujos_moto <- od_modes %>%
  filter(TIPO_VEHICULO == "Moto") %>%
  group_by(COMUNA_ORIGEN) %>%
  summarise(viajes = sum(PERSONAS_EN_VEHICULO,na.rm=T), .groups = "drop") %>%
  arrange(desc(viajes))

head(flujos_moto)
## # A tibble: 6 × 2
##   COMUNA_ORIGEN viajes
##   <fct>          <dbl>
## 1 02              1289
## 2 19              1235
## 3 17              1051
## 4 03               851
## 5 18               715
## 6 04               694
mapa_etiquetado(
  comunas_map,
  viajes_moto,
  prop_moto,
  "Producción de viajes - Moto",
  "#ede7f6", "#9e9ac8"
)

3.5 🚗 Pregunta 5. ¿De qué comuna salen la mayoría de las personas que se movilizan en automóvil?

La producción de viajes en automóvil está liderada por la comuna 19, seguida de la 02 y la 17, manteniendo una estructura jerárquica similar a la observada en otros modos motorizados. Sin embargo, en términos agregados, la motocicleta continúa siendo el modo más frecuente en las salidas, superando al automóvil en volumen total. Esto sugiere que, aunque el automóvil tiene una presencia relevante en ciertas comunas, la moto domina como principal medio de desplazamiento motorizado en la ciudad.

flujos_auto <- od_modes %>%
  filter(TIPO_VEHICULO == "Automóvil") %>%
  group_by(COMUNA_ORIGEN) %>%
  summarise(viajes = sum(PERSONAS_EN_VEHICULO,na.rm=T), .groups = "drop") %>%
  arrange(desc(viajes))

head(flujos_auto)
## # A tibble: 6 × 2
##   COMUNA_ORIGEN viajes
##   <fct>          <dbl>
## 1 19              1518
## 2 02              1406
## 3 17              1143
## 4 03              1133
## 5 18               759
## 6 04               739
mapa_etiquetado(
  comunas_map,
  viajes_auto,
  prop_auto,
  "Producción de viajes - Automóvil",
  "#fff7bc", "#fdb863"
)

3.6 🚲 Pregunta 6. ¿A qué comuna llegan la mayoría de las personas que se movilizan en bicicleta?

La atracción de viajes en bicicleta se concentra principalmente en la comuna 02, seguida por las comunas 03 y 19, lo que evidencia la existencia de polos de proximidad con alta actividad local. La distribución presenta menor dispersión en comparación con modos motorizados, reforzando el carácter territorialmente acotado de este modo.

flujos_bici <- od_modes %>%
  filter(TIPO_VEHICULO == "Bicicleta") %>%
  group_by(COMUNA_DESTINO) %>%
  summarise(viajes = sum(PERSONAS_EN_VEHICULO,na.rm=T), .groups = "drop") %>%
  arrange(desc(viajes))
head(flujos_bici)
## # A tibble: 6 × 2
##   COMUNA_DESTINO viajes
##   <fct>           <dbl>
## 1 02                201
## 2 03                172
## 3 19                132
## 4 17                101
## 5 22                 95
## 6 04                 80
mapa_etiquetado(
  comunas_map,
  llegadas_bici,
  prop_lleg_bici,
  "Llegadas - Bicicleta",
  "#edf8e9", "#66c2a4"
)

3.7 🏍 Pregunta 7. ¿A qué comuna llegan la mayoría de las personas que se movilizan en moto?

La atracción de viajes en motocicleta está fuertemente concentrada en las comunas 02, 03 y 19, consolidando estos territorios como principales polos receptores de este modo. A diferencia de la bicicleta, la moto muestra una mayor capacidad de cobertura espacial, alcanzando también comunas como la 22 y la 17. Este patrón sugiere que la motocicleta cumple un rol clave en la conexión hacia centralidades urbanas, especialmente en contextos donde la accesibilidad al transporte público puede ser limitada.

flujos_moto <- od_modes %>%
  filter(TIPO_VEHICULO == "Moto") %>%
  group_by(COMUNA_DESTINO) %>%
  summarise(viajes = sum(PERSONAS_EN_VEHICULO,na.rm=T), .groups = "drop") %>%
  arrange(desc(viajes))

head(flujos_moto)
## # A tibble: 6 × 2
##   COMUNA_DESTINO viajes
##   <fct>           <dbl>
## 1 02               2099
## 2 03               1624
## 3 19               1403
## 4 17                913
## 5 22                901
## 6 04                811
mapa_etiquetado(
  comunas_map,
  llegadas_moto,
  prop_lleg_moto,
  "Llegadas - Moto",
  "#fff5eb", "#9e9ac8"
)

3.8 🚗 Pregunta 8. ¿A qué comuna llegan la mayoría de las personas que se movilizan en automóvil?

La atracción de viajes en automóvil está altamente concentrada en las comunas 02, 03 y 19, que actúan como principales centralidades urbanas. A diferencia de la motocicleta, el automóvil muestra una mayor presencia en comunas con alta actividad económica y mejor infraestructura vial, como la 04 y la 17.

flujos_auto <- od_modes %>%
  filter(TIPO_VEHICULO == "Automóvil") %>%
  group_by(COMUNA_DESTINO) %>%
  summarise(viajes = sum(PERSONAS_EN_VEHICULO,na.rm=T), .groups = "drop") %>%
  arrange(desc(viajes))

head(flujos_auto)
## # A tibble: 6 × 2
##   COMUNA_DESTINO viajes
##   <fct>           <dbl>
## 1 02               2611
## 2 03               1868
## 3 19               1576
## 4 17               1133
## 5 04                977
## 6 22                916
mapa_etiquetado(
  comunas_map,
  llegadas_auto,
  prop_lleg_auto,
  "Llegadas - Automóvil",
  "#fff5eb", "#fdb863"
)

3.9 Saldo neto de viajes por comuna

ggplot(comunas_map) +
  geom_sf(aes(fill = saldo), color = "white") +
  geom_sf_text(aes(label = comuna), size = 3) +
  scale_fill_gradient2(low = "lightblue", mid = "white", high = "red") +
  labs(title = "Saldo neto de viajes por comuna",
       fill = "Saldo") 

4 Conclusiones

Los resultados evidencian que la estructura de movilidad intraurbana en Cali responde a un patrón espacial altamente jerarquizado, consistente con modelos clásicos de economía urbana y estructura monocéntrica parcialmente descentralizada.

4.1 Producción vs atracción de viajes

Se observa una clara separación funcional entre comunas:

  • Comunas productoras (emisoras netas): caracterizadas por altos niveles de salida y menor atracción relativa. Estas zonas corresponden típicamente a áreas residenciales, donde se origina la demanda de movilidad.

  • Comunas atractoras (receptoras netas): concentran actividades económicas, institucionales y comerciales, actuando como polos de empleo y servicios.

Este patrón es consistente con la existencia de gradientes de centralidad urbana, donde la movilidad responde a la localización de oportunidades económicas.

4.2 Diferenciación modal

El análisis por tipo de vehículo revela estructuras de movilidad segmentadas. Los resultados evidencian una estructura de movilidad intraurbana altamente concentrada y jerárquica en Cali, donde un conjunto reducido de comunas —principalmente la 02, 03 y 19— actúan simultáneamente como principales nodos emisores y receptores de viajes, consolidándose como centralidades funcionales de la ciudad. Desde el punto de vista modal, la motocicleta domina la producción de viajes, reflejando su papel como alternativa flexible y de amplio alcance territorial, especialmente en contextos de restricciones del transporte público. En contraste, la bicicleta presenta una lógica espacial más localizada, asociada a desplazamientos de corta distancia, mientras que el automóvil se vincula a viajes hacia zonas de mayor actividad económica y mayor nivel de ingreso.

4.2.1 🚲 Bicicleta

Presenta alta concentración espacial, lo que indica:

  • Dependencia de distancias cortas
  • Sensibilidad a infraestructura local
  • Predominio en viajes intracomunales o intercomunales cercanos

Esto sugiere que su expansión depende críticamente de la continuidad de la red ciclista.

4.2.2 🏍 Motocicleta

Exhibe mayor cobertura territorial, especialmente en periferias:

  • Funciona como sustituto del transporte público
  • Reduce costos de acceso en zonas con baja conectividad
  • Indica posibles fallas en la provisión de transporte masivo

4.2.3 🚗 Automóvil

Muestra mayor dispersión espacial:

  • Asociado a viajes de mayor longitud
  • Mayor presencia en comunas de ingreso medio-alto
  • Refleja menor restricción de costos de transporte

4.3 Implicaciones de política pública

Los resultados sugieren:

  • Necesidad de fortalecer infraestructura en corredores de alta atracción (Comunas 2, 3 19 y 17)
  • Expansión focalizada de ciclorrutas en zonas con potencial de uso
  • Intervenciones en transporte público en periferias donde domina la motocicleta

El análisis confirma que la movilidad intraurbana en Cali no es aleatoria, sino que responde a una estructura espacial definida por la localización de actividades económicas y características socioeconómicas de la población.

La evidencia empírica muestra que:

  • Existen comunas claramente especializadas en producción o atracción de viajes
  • Los modos de transporte no se distribuyen homogéneamente en el territorio
  • La motocicleta juega un rol clave en zonas con menor accesibilidad

Estos hallazgos permiten orientar políticas de movilidad basadas en evidencia, priorizando intervenciones diferenciadas según el rol funcional de cada comuna dentro del sistema urbano.