require(sf)
require(dplyr)
require(leaflet)
require(htmltools)
Se usa la encuesta de origen y destino de Cali, una encuesta de interceptación de vehículos realizada en 35 estaciones entre mayo y junio de 2015, junto con el shapefile de las 22 comunas.
Los conteos son viajes encuestados, no el total de viajes de la ciudad, así que también reflejan dónde estaban ubicadas las estaciones.
comunas=read_sf("Casos/cali/Comunas.shp") %>%
st_transform(4326)
encuesta=readxl::read_xlsx("Casos/EncuestaOrigenDestino.xlsx")
viajes=encuesta[,c(7,9,11,13,26,27)]
names(viajes)=c("mun_origen","sdg_origen","mun_destino","sdg_destino",
"comuna_origen","comuna_destino")
La columna de comuna no se puede usar directamente, porque tiene dos categorías que mezclan casos distintos.
Comuna 0. Cali no tiene comuna 0. El código SDG de cada lugar empieza por el número de su comuna, y casi todos los registros con 0 empiezan por 26: son corregimientos como Pance, La Buitrera y Montebello. Estos se agrupan como Zona rural. Los pocos que empiezan por el número de una comuna se devuelven a esa comuna.
Fuera de Cali. Esta categoría incluye lugares dentro
de la ciudad cuyo código se perdió (código SDG Perdida,
municipio CALI), como la Avenida Roosevelt o La 14. Estos se separan
como Sin ubicar, y el resto se mantiene como Fuera de
Cali.
También se eliminan los registros marcados como
ANULADO.
clasificar=function(comuna, sdg, municipio) {
prefijo=substr(sdg, 1, nchar(sdg) - 2)
municipio=toupper(trimws(municipio))
case_when(
comuna %in% sprintf("%02d", 1:22) ~ sub("^0+", "", comuna),
prefijo == "26" ~ "Zona rural",
comuna == "0" & prefijo %in% as.character(1:22) ~ prefijo,
sdg == "Perdida" & (is.na(municipio) | municipio %in% c("CALI", "SIN DATOS")) ~ "Sin ubicar",
TRUE ~ "Fuera de Cali"
)
}
viajes=viajes %>%
filter(!(mun_origen %in% "ANULADO" | mun_destino %in% "ANULADO")) %>%
mutate(
zona_origen=clasificar(comuna_origen, sdg_origen, mun_origen),
zona_destino=clasificar(comuna_destino, sdg_destino, mun_destino)
)
# Count trips by comuna, and the ones that connect it with other municipalities
conteo_origen=viajes %>%
count(zona_origen, name = "viajes_origen")
conteo_destino=viajes %>%
count(zona_destino, name = "viajes_destino")
hacia_fuera=viajes %>%
filter(zona_destino == "Fuera de Cali") %>%
count(zona_origen, name = "hacia_fuera")
desde_fuera=viajes %>%
filter(zona_origen == "Fuera de Cali") %>%
count(zona_destino, name = "desde_fuera")
comunas_final=comunas %>%
mutate(zona=as.character(comuna)) %>%
left_join(conteo_origen, by = c("zona" = "zona_origen")) %>%
left_join(conteo_destino, by = c("zona" = "zona_destino")) %>%
left_join(hacia_fuera, by = c("zona" = "zona_origen")) %>%
left_join(desde_fuera, by = c("zona" = "zona_destino")) %>%
mutate(
across(c(viajes_origen, viajes_destino, hacia_fuera, desde_fuera), ~coalesce(.x, 0L)),
pct_fuera=100 * (hacia_fuera + desde_fuera) / (viajes_origen + viajes_destino)
) %>%
arrange(comuna)
El número sobre cada comuna es la cantidad de viajes. Use el selector de la esquina superior derecha para cambiar entre origen y destino: ambos usan la misma escala de color, así que se pueden comparar. Pase el cursor sobre una comuna para ver sus dos valores, o haga clic para ver el detalle.
miles=function(x) format(x, big.mark = ".", decimal.mark = ",", trim = TRUE)
porcentaje=function(x) sub(".", ",", sprintf("%.1f%%", x), fixed = TRUE)
centros=st_coordinates(st_point_on_surface(st_geometry(comunas_final)))
etiqueta_numero=labelOptions(
noHide = TRUE, textOnly = TRUE, direction = "center",
style = list(
"color" = "#0b0b0b", "font-weight" = "600", "font-size" = "12px",
"background" = "rgba(255,255,255,0.8)", "border-radius" = "3px", "padding" = "0 3px"
)
)
hover=with(comunas_final, lapply(sprintf(
"<b>%s</b><br>Origen: %s<br>Destino: %s",
nombre, miles(viajes_origen), miles(viajes_destino)
), HTML))
popup=with(comunas_final, sprintf(
"<b>%s</b><br>Viajes con origen aquí: %s<br>Viajes con destino aquí: %s<br>
Hacia fuera de Cali: %s<br>Desde fuera de Cali: %s<br>Conexión con otros municipios: %s",
nombre, miles(viajes_origen), miles(viajes_destino),
miles(hacia_fuera), miles(desde_fuera), porcentaje(pct_fuera)
))
valores=c(comunas_final$viajes_origen, comunas_final$viajes_destino)
azules=c("#cde2fb", "#9ec5f4", "#6da7ec", "#3987e5", "#256abf", "#184f95", "#0d366b")
paleta=colorBin(azules, domain = valores, bins = pretty(valores, n = 6))
capa=function(mapa, columna, grupo) {
mapa %>%
addPolygons(
fillColor = paleta(comunas_final[[columna]]), fillOpacity = 0.85,
color = "#ffffff", weight = 1.5, group = grupo,
label = hover, popup = popup,
highlightOptions = highlightOptions(weight = 3, color = "#0b0b0b", bringToFront = TRUE)
) %>%
addLabelOnlyMarkers(
lng = centros[,1], lat = centros[,2], group = grupo,
label = miles(comunas_final[[columna]]), labelOptions = etiqueta_numero
)
}
leaflet(comunas_final, width = "100%", height = 680) %>%
addProviderTiles(providers$Esri.WorldGrayCanvas) %>%
capa("viajes_origen", "Origen") %>%
capa("viajes_destino", "Destino") %>%
addLayersControl(
baseGroups = c("Origen", "Destino"),
options = layersControlOptions(collapsed = FALSE)
) %>%
addLegend(
position = "bottomright", pal = paleta, values = valores,
title = "Viajes encuestados", opacity = 0.85,
labFormat = labelFormat(big.mark = ".")
)
El shapefile cubre el perímetro urbano, así que estos viajes no tienen polígono. Se reportan aquí para que no se pierdan.
zonas_otras=c("Zona rural", "Fuera de Cali", "Sin ubicar")
tibble(Zona = zonas_otras) %>%
left_join(conteo_origen, by = c("Zona" = "zona_origen")) %>%
left_join(conteo_destino, by = c("Zona" = "zona_destino")) %>%
mutate(across(c(viajes_origen, viajes_destino), miles)) %>%
rename(Origen = viajes_origen, Destino = viajes_destino) %>%
knitr::kable(align = "lrr")
| Zona | Origen | Destino |
|---|---|---|
| Zona rural | 695 | 786 |
| Fuera de Cali | 5.430 | 5.263 |
| Sin ubicar | 803 | 1.094 |
Los viajes fuera de Cali no caben en el mapa de comunas, pero sí muestran qué tan conectada está cada comuna con la región. Este mapa muestra el porcentaje de los viajes de cada comuna que salen hacia otro municipio o llegan desde otro.
valores_fuera=comunas_final$pct_fuera
naranjas=c("#fde3d8", "#f7b89e", "#f08f68", "#eb6834", "#bd4c1f", "#8f3410")
paleta_fuera=colorBin(naranjas, domain = valores_fuera, bins = pretty(valores_fuera, n = 5))
leaflet(comunas_final, width = "100%", height = 680) %>%
addProviderTiles(providers$Esri.WorldGrayCanvas) %>%
addPolygons(
fillColor = ~paleta_fuera(pct_fuera), fillOpacity = 0.85,
color = "#ffffff", weight = 1.5,
label = hover, popup = popup,
highlightOptions = highlightOptions(weight = 3, color = "#0b0b0b", bringToFront = TRUE)
) %>%
addLabelOnlyMarkers(
lng = centros[,1], lat = centros[,2],
label = sprintf("%.0f%%", valores_fuera), labelOptions = etiqueta_numero
) %>%
addLegend(
position = "bottomright", pal = paleta_fuera, values = valores_fuera,
title = "% de viajes con<br>otros municipios", opacity = 0.85,
labFormat = labelFormat(suffix = "%")
)
La tabla cuenta los viajes con un extremo en Cali, incluida su zona rural.
en_cali=function(zona) !zona %in% c("Fuera de Cali", "Sin ubicar")
sin_municipio=c("CALI", "SIN DATOS")
hacia_cali=viajes %>%
filter(zona_origen == "Fuera de Cali", en_cali(zona_destino)) %>%
count(municipio = toupper(trimws(mun_origen)), name = "Hacia Cali")
desde_cali=viajes %>%
filter(zona_destino == "Fuera de Cali", en_cali(zona_origen)) %>%
count(municipio = toupper(trimws(mun_destino)), name = "Desde Cali")
full_join(hacia_cali, desde_cali, by = "municipio") %>%
filter(!is.na(municipio), !municipio %in% sin_municipio) %>%
mutate(
across(c(`Hacia Cali`, `Desde Cali`), ~coalesce(.x, 0L)),
Total = `Hacia Cali` + `Desde Cali`,
Municipio = tools::toTitleCase(tolower(municipio))
) %>%
arrange(desc(Total)) %>%
slice_head(n = 8) %>%
transmute(Municipio, `Hacia Cali` = miles(`Hacia Cali`),
`Desde Cali` = miles(`Desde Cali`), Total = miles(Total)) %>%
knitr::kable(align = "lrrr")
| Municipio | Hacia Cali | Desde Cali | Total |
|---|---|---|---|
| Yumbo | 1.354 | 1.642 | 2.996 |
| Jamundi | 1.072 | 667 | 1.739 |
| Palmira | 827 | 871 | 1.698 |
| Candelaria | 255 | 278 | 533 |
| Puerto Tejada | 54 | 155 | 209 |
| La Union | 112 | 82 | 194 |
| Santander De Quilichao | 80 | 70 | 150 |
| Guadalajara De Buga | 73 | 65 | 138 |
de_paso=sum(viajes$zona_origen == "Fuera de Cali" & viajes$zona_destino == "Fuera de Cali")
Además, 636 viajes tienen ambos extremos fuera de Cali. Pasan por la ciudad sin empezar ni terminar en ella, y por eso no se cuentan en ninguna comuna.
comunas_final %>%
st_drop_geometry() %>%
transmute(
Comuna = comuna, Origen = miles(viajes_origen), Destino = miles(viajes_destino),
`Hacia fuera` = miles(hacia_fuera), `Desde fuera` = miles(desde_fuera),
`% otros municipios` = porcentaje(pct_fuera)
) %>%
knitr::kable(align = "lrrrrr")
| Comuna | Origen | Destino | Hacia fuera | Desde fuera | % otros municipios |
|---|---|---|---|---|---|
| 1 | 794 | 230 | 128 | 38 | 16,2% |
| 2 | 2.968 | 4.810 | 568 | 855 | 18,3% |
| 3 | 2.121 | 3.859 | 398 | 804 | 20,1% |
| 4 | 1.493 | 1.856 | 229 | 302 | 15,9% |
| 5 | 664 | 522 | 109 | 67 | 14,8% |
| 6 | 998 | 716 | 159 | 124 | 16,5% |
| 7 | 734 | 748 | 115 | 113 | 15,4% |
| 8 | 1.124 | 1.025 | 187 | 157 | 16,0% |
| 9 | 952 | 1.279 | 150 | 168 | 14,3% |
| 10 | 1.401 | 927 | 212 | 143 | 15,2% |
| 11 | 925 | 564 | 156 | 62 | 14,6% |
| 12 | 348 | 246 | 70 | 27 | 16,3% |
| 13 | 1.238 | 673 | 147 | 84 | 12,1% |
| 14 | 685 | 379 | 82 | 55 | 12,9% |
| 15 | 1.171 | 579 | 151 | 82 | 13,3% |
| 16 | 993 | 743 | 119 | 66 | 10,7% |
| 17 | 2.382 | 2.166 | 442 | 416 | 18,9% |
| 18 | 1.536 | 662 | 235 | 108 | 15,6% |
| 19 | 2.850 | 3.159 | 444 | 573 | 16,9% |
| 20 | 745 | 360 | 94 | 36 | 11,8% |
| 21 | 818 | 515 | 85 | 59 | 10,8% |
| 22 | 1.153 | 1.860 | 127 | 217 | 11,4% |