VISUALIZACIÓN DE DATOS
Inseguridad y territorio en Bogotá:
¿qué nos cuentan las UPZ?
Docente: Carlos Amortegui
Para realizar la exploración de los datos se utilizarán paquetes de R que permiten importar archivos, organizar la información y realizar cálculos estadísticos.
El siguiente código instala los paquetes necesarios para trabajar con archivos Excel y CSV, manipular datos y elaborar gráficos.
# Instalación de paquetes necesarios para el proyecto
install.packages("tidyverse") # Manipulación, transformación y exploración de datos. Incluye dplyr, tidyr, ggplot2 y readr.
install.packages("sf") # Lectura y manejo de información geográfica. Permite trabajar con los polígonos de las UPZ y localidades.
install.packages("leaflet") # Creación de mapas interactivos con zoom, etiquetas y resaltado de territorios.
install.packages("scales") # Formato de números, porcentajes, tasas y escalas en gráficos.
install.packages("knitr") # Organización y presentación de tablas y resultados dentro del informe R Markdown.
Una vez instalados, los paquetes se cargan para poder utilizar sus funciones durante el análisis.
# Cargar las librerías necesarias
library(tidyverse)
library(sf)
library(leaflet)
library(scales)
library(knitr)
Configuración del comportamiento general del documento
# Definir la paleta de colores del proyecto
morado <- "#351A4F"
magenta <- "#D9006C"
turquesa <- "#168C86"
gris <- "#D9D6DD"
# Configuración general de los gráficos
tema_clase <- theme_minimal(base_size = 12) +
theme(
plot.title.position = "plot",
plot.title = element_text(
face = "bold", size = 15, color = morado
),
plot.subtitle = element_text(
size = 10.5, color = "grey35"
),
panel.grid.minor = element_blank(),
plot.caption = element_text(
hjust = 0, color = "grey45", size = 8.5
),
plot.margin = margin(10, 20, 10, 10)
)
# Opciones generales de presentación del informe
knitr::opts_chunk$set(
echo = TRUE,
warning = FALSE,
message = FALSE,
fig.align = "center",
fig.width = 8,
fig.height = 5,
dpi = 120
)
La seguridad ciudadana es una de las dimensiones que influye en la calidad de vida y en las condiciones de convivencia de una ciudad. Sin embargo, su comportamiento no necesariamente es igual en todos los territorios, ya que cada zona presenta características particulares relacionadas con su población, infraestructura, condiciones socioeconómicas y entorno urbano.
En Bogotá, las Unidades de Planeamiento Zonal (UPZ) permiten observar estas diferencias desde una perspectiva territorial. A través de ellas es posible comparar las condiciones de distintos sectores de la ciudad y explorar cómo se relacionan con los registros de delitos y la percepción de inseguridad de sus habitantes.
Este trabajo desarrolla un análisis exploratorio de datos (EDA) sobre las 112 UPZ urbanas de Bogotá, utilizando información relacionada con delitos denunciados, población, vivienda, alumbrado público y condiciones socioeconómicas.
El propósito es identificar patrones, diferencias y posibles relaciones entre las características de cada territorio y los indicadores de seguridad disponibles. Para ello, se utilizarán herramientas estadísticas y visualizaciones que faciliten la interpretación de los resultados, incluyendo representaciones geográficas que permitan reconocer las diferencias entre las zonas de la ciudad.
El análisis no busca establecer relaciones de causalidad ni afirmar que una característica territorial sea la causa directa de determinados comportamientos delictivos. Su alcance es exploratorio y pretende comprender mejor la información disponible, reconocer patrones y generar preguntas que puedan orientar investigaciones posteriores.
Explorar las condiciones de seguridad y las características territoriales, demográficas y socioeconómicas de las UPZ urbanas de Bogotá, mediante técnicas de análisis exploratorio de datos y visualización, con el propósito de identificar patrones, diferencias y posibles relaciones que permitan comprender el comportamiento de los indicadores de inseguridad en la ciudad.
Describir la estructura y las características de la información disponible para las 112 UPZ de Bogotá.
Explorar la distribución de los indicadores de delitos, población, vivienda, infraestructura y condiciones socioeconómicas.
Identificar diferencias territoriales mediante el uso de estadísticas descriptivas, comparaciones y mapas.
Examinar posibles relaciones entre los indicadores de seguridad y las características de cada UPZ.
Comunicar los principales hallazgos mediante visualizaciones y una narrativa basada en los datos.
Para desarrollar el análisis se utiliza una base de datos consolidada que contiene información de 112 Unidades de Planeamiento Zonal de Bogotá. Cada registro representa una UPZ e incluye variables relacionadas con su territorio, población, condiciones de vivienda, infraestructura, delitos denunciados y características socioeconómicas.
La información se encuentra organizada en cinco grandes bloques:
Territorio: identificación de la UPZ, localidad y extensión geográfica.
Demografía: población, densidad poblacional y composición por grupos de edad.
Vivienda e infraestructura: características de las viviendas y disponibilidad de alumbrado público.
Delitos: registros de denuncias y tasas por cada 10.000 habitantes para diez categorías de delitos.
Encuesta Multipropósito: información relacionada con pobreza, ingresos, estrato, educación, percepción de inseguridad y condiciones del entorno.
Adicionalmente, se dispone de archivos geográficos que representan los límites de las UPZ y las localidades urbanas de Bogotá. Estos archivos permitirán integrar la información estadística con su ubicación territorial.
Vamos a conectar nuestro informe con los archivos.
Se cargaran tres fuentes: 1. La base estadística de las UPZ. 2. El mapa de las UPZ. 3. El mapa de las localidades.
# 3.1. Importación de la base estadística
upz <- read_csv(
"input/upz_variables.csv",
show_col_types = FALSE
)
# 3.2. Importación de los archivos geográficos
upz_shp <- st_read(
"input/shp/upz_bogota.shp",
quiet = TRUE
)
localidades_shp <- st_read(
"input/shp/localidades_bogota.shp",
quiet = TRUE
)
Notas:
read_csv() permite importar la información estadística.
st_read() permite leer los archivos geográficos.
Los objetos terminados en **_shp** contienen geometrías que representan los límites territoriales.
Antes de realizar los análisis estadísticos y las visualizaciones, es necesario conocer la estructura de la información disponible y verificar sus características generales.
Esta primera exploración permite identificar la cantidad de registros y variables, los tipos de datos utilizados y las condiciones generales de la base. De esta manera, se busca establecer un punto de partida que facilite el desarrollo de las siguientes etapas del análisis.
La base de datos contiene información de diferentes características de las UPZ de Bogotá. Para comenzar, se revisa su dimensión general, identificando cuántos registros y variables están disponibles.
Cada registro representa una UPZ, mientras que las columnas corresponden a las diferentes características e indicadores recopilados para el análisis.
# Consultar las dimensiones generales de la base
dim(upz)
## [1] 112 67
# Identificar la cantidad de registros
nrow(upz)
## [1] 112
# Identificar la cantidad de variables
ncol(upz)
## [1] 67
# Consultar los primeros registros
head(upz)
| upz_cod | upz_nombre | localidad_cod | localidad | area_km2 | poblacion | densidad_hab_km2 | pct_mujeres | pct_0_14 | pct_15_29 | pct_60_mas | viviendas_totales | viviendas_ocupadas | pct_viviendas_desocupadas | personas_por_vivienda | luminarias | luminarias_km2 | luminarias_1000hab | pct_luminarias_led | casos_homicidios | casos_lesiones | casos_hurto_personas | casos_hurto_residencias | casos_hurto_automotor | casos_hurto_bicicletas | casos_hurto_comercio | casos_hurto_celulares | casos_hurto_motos | casos_violencia_intrafamiliar | casos_total | tasa_homicidios | tasa_lesiones | tasa_hurto_personas | tasa_hurto_residencias | tasa_hurto_automotor | tasa_hurto_bicicletas | tasa_hurto_comercio | tasa_hurto_celulares | tasa_hurto_motos | tasa_violencia_intrafamiliar | tasa_total | em_agrupada | pct_pobreza | edad_promedio | salario_promedio | pct_estrato_1_2 | pct_estrato_3_4 | pct_estrato_5_6 | pct_vivienda_propia | pct_arriendo | anios_educacion_15mas | pct_padre_universitario | pct_madre_universitaria | pct_percibe_inseguridad | pct_cerca_ollas | pct_cerca_bares | pct_cerca_lotes_oscuros | pct_cerca_basureros | pct_cerca_terminales | pct_cerca_fabricas | min_transmilenio | min_sitp | min_parque | min_cai_policia | min_centro_medico | min_cultura | min_ciclorruta |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 1 | Paseo De Los Libertadores | 1 | Usaquén | 6.33 | 2690 | 424.81 | 51.26 | 18.85 | 26.13 | 12.94 | 1087 | 1022 | 5.98 | 2.63 | 524 | 82.75 | 194.80 | 28.44 | 0 | 8 | 44 | 1 | 0 | 1 | 3 | 17 | 0 | 0 | 74 | 0.00 | 29.74 | 163.57 | 3.72 | 0.00 | 3.72 | 11.15 | 63.20 | 0.00 | 0.00 | 275.09 | TRUE | 1.37 | 36.54 | 3937004 | 13.92 | 83.87 | 2.21 | 54.45 | 38.00 | 12.16 | 24.14 | 17.37 | 36.18 | 17.53 | 15.68 | 24.15 | 6.13 | 20.93 | 11.55 | 13.01 | 9.99 | 7.00 | 21.66 | 29.82 | 33.90 | 9.00 |
| 2 | La Academia | 11 | Suba | 6.74 | 5260 | 779.85 | 51.35 | 24.11 | 18.46 | 9.26 | 1554 | 1515 | 2.51 | 3.47 | 534 | 79.17 | 101.52 | 0.37 | 1 | 3 | 75 | 0 | 3 | 1 | 9 | 26 | 0 | 5 | 123 | 1.90 | 5.70 | 142.59 | 0.00 | 5.70 | 1.90 | 17.11 | 49.43 | 0.00 | 9.51 | 233.84 | TRUE | 0.86 | 38.71 | 4280663 | 0.63 | 87.06 | 12.31 | 57.98 | 36.81 | 13.57 | 24.16 | 14.82 | 40.88 | 7.43 | 17.03 | 16.71 | 1.35 | 26.66 | 1.70 | 10.78 | 9.56 | 5.44 | 24.50 | 34.17 | 29.61 | 13.45 |
| 3 | Guaymaral | 11 | Suba | 4.55 | 2692 | 591.30 | 51.63 | 18.31 | 20.88 | 14.04 | 789 | 698 | 11.53 | 3.86 | 184 | 40.42 | 68.35 | 0.00 | 0 | 1 | 29 | 0 | 0 | 2 | 2 | 9 | 0 | 2 | 45 | 0.00 | 3.71 | 107.73 | 0.00 | 0.00 | 7.43 | 7.43 | 33.43 | 0.00 | 7.43 | 167.16 | TRUE | 0.86 | 38.71 | 4280663 | 0.63 | 87.06 | 12.31 | 57.98 | 36.81 | 13.57 | 24.16 | 14.82 | 40.88 | 7.43 | 17.03 | 16.71 | 1.35 | 26.66 | 1.70 | 10.78 | 9.56 | 5.44 | 24.50 | 34.17 | 29.61 | 13.45 |
| 9 | Verbenal | 1 | Usaquén | 3.57 | 131999 | 36967.66 | 52.77 | 20.15 | 25.15 | 11.61 | 46809 | 45055 | 3.75 | 2.93 | 3555 | 995.61 | 26.93 | 65.77 | 3 | 104 | 386 | 29 | 19 | 17 | 26 | 125 | 30 | 205 | 944 | 0.23 | 7.88 | 29.24 | 2.20 | 1.44 | 1.29 | 1.97 | 9.47 | 2.27 | 15.53 | 71.52 | FALSE | 3.12 | 33.28 | 1933709 | 31.32 | 66.05 | 2.63 | 36.78 | 55.53 | 12.16 | 8.36 | 6.13 | 65.43 | 17.53 | 15.68 | 24.15 | 6.13 | 20.93 | 11.55 | 6.96 | 5.96 | 8.60 | 18.39 | 34.18 | 42.77 | 14.45 |
| 10 | La Uribe | 1 | Usaquén | 3.47 | 37014 | 10682.12 | 54.34 | 17.24 | 20.18 | 15.62 | 14399 | 13763 | 4.42 | 2.69 | 1328 | 383.26 | 35.88 | 49.25 | 1 | 26 | 328 | 31 | 4 | 14 | 47 | 129 | 1 | 40 | 621 | 0.27 | 7.02 | 88.62 | 8.38 | 1.08 | 3.78 | 12.70 | 34.85 | 0.27 | 10.81 | 167.77 | TRUE | 1.37 | 36.54 | 3937004 | 13.92 | 83.87 | 2.21 | 54.45 | 38.00 | 12.16 | 24.14 | 17.37 | 36.18 | 17.53 | 15.68 | 24.15 | 6.13 | 20.93 | 11.55 | 13.01 | 9.99 | 7.00 | 21.66 | 29.82 | 33.90 | 9.00 |
| 11 | San Cristobal Norte | 1 | Usaquén | 2.76 | 72939 | 26401.70 | 52.65 | 19.59 | 24.65 | 14.38 | 24886 | 24401 | 1.95 | 2.99 | 2578 | 933.16 | 35.34 | 49.34 | 4 | 73 | 351 | 27 | 5 | 11 | 39 | 117 | 9 | 157 | 793 | 0.55 | 10.01 | 48.12 | 3.70 | 0.69 | 1.51 | 5.35 | 16.04 | 1.23 | 21.52 | 108.72 | FALSE | 5.19 | 34.50 | 1368739 | 29.48 | 68.87 | 1.65 | 28.86 | 58.05 | 10.95 | 4.76 | 3.31 | 49.84 | 25.91 | 15.41 | 19.15 | 8.30 | 3.38 | 5.99 | 17.76 | 11.43 | 10.39 | 25.32 | 29.71 | 28.10 | 18.27 |
Además de conocer el tamaño de la base, es importante identificar el tipo de información que contiene cada variable.
Esta revisión permite diferenciar los campos que representan cantidades, porcentajes, tasas, categorías territoriales y otras características.
La identificación de estos tipos de datos es importante porque no todas las variables pueden analizarse de la misma manera. Por ejemplo, una variable de población permite realizar cálculos estadísticos, mientras que una variable como el nombre de la localidad se utiliza principalmente para clasificar y agrupar la información.
# Consultar la estructura y los tipos de variables
glimpse(upz)
## Rows: 112
## Columns: 67
## $ upz_cod <dbl> 1, 2, 3, 9, 10, 11, 12, 13, 14, 15, 16, …
## $ upz_nombre <chr> "Paseo De Los Libertadores", "La Academi…
## $ localidad_cod <dbl> 1, 11, 11, 1, 1, 1, 1, 1, 1, 1, 1, 11, 1…
## $ localidad <chr> "Usaquén", "Suba", "Suba", "Usaquén", "U…
## $ area_km2 <dbl> 6.33, 6.74, 4.55, 3.57, 3.47, 2.76, 2.92…
## $ poblacion <dbl> 2690, 5260, 2692, 131999, 37014, 72939, …
## $ densidad_hab_km2 <dbl> 424.81, 779.85, 591.30, 36967.66, 10682.…
## $ pct_mujeres <dbl> 51.26, 51.35, 51.63, 52.77, 54.34, 52.65…
## $ pct_0_14 <dbl> 18.85, 24.11, 18.31, 20.15, 17.24, 19.59…
## $ pct_15_29 <dbl> 26.13, 18.46, 20.88, 25.15, 20.18, 24.65…
## $ pct_60_mas <dbl> 12.94, 9.26, 14.04, 11.61, 15.62, 14.38,…
## $ viviendas_totales <dbl> 1087, 1554, 789, 46809, 14399, 24886, 24…
## $ viviendas_ocupadas <dbl> 1022, 1515, 698, 45055, 13763, 24401, 23…
## $ pct_viviendas_desocupadas <dbl> 5.98, 2.51, 11.53, 3.75, 4.42, 1.95, 3.6…
## $ personas_por_vivienda <dbl> 2.63, 3.47, 3.86, 2.93, 2.69, 2.99, 2.68…
## $ luminarias <dbl> 524, 534, 184, 3555, 1328, 2578, 2734, 5…
## $ luminarias_km2 <dbl> 82.75, 79.17, 40.42, 995.61, 383.26, 933…
## $ luminarias_1000hab <dbl> 194.80, 101.52, 68.35, 26.93, 35.88, 35.…
## $ pct_luminarias_led <dbl> 28.44, 0.37, 0.00, 65.77, 49.25, 49.34, …
## $ casos_homicidios <dbl> 0, 1, 0, 3, 1, 4, 1, 0, 0, 0, 3, 1, 2, 0…
## $ casos_lesiones <dbl> 8, 3, 1, 104, 26, 73, 52, 75, 36, 14, 49…
## $ casos_hurto_personas <dbl> 44, 75, 29, 386, 328, 351, 500, 1189, 78…
## $ casos_hurto_residencias <dbl> 1, 0, 0, 29, 31, 27, 19, 87, 35, 24, 76,…
## $ casos_hurto_automotor <dbl> 0, 3, 0, 19, 4, 5, 7, 11, 3, 1, 8, 14, 1…
## $ casos_hurto_bicicletas <dbl> 1, 1, 2, 17, 14, 11, 38, 71, 26, 12, 32,…
## $ casos_hurto_comercio <dbl> 3, 9, 2, 26, 47, 39, 58, 95, 72, 28, 125…
## $ casos_hurto_celulares <dbl> 17, 26, 9, 125, 129, 117, 170, 368, 262,…
## $ casos_hurto_motos <dbl> 0, 0, 0, 30, 1, 9, 6, 3, 3, 0, 5, 8, 8, …
## $ casos_violencia_intrafamiliar <dbl> 0, 5, 2, 205, 40, 157, 92, 92, 73, 14, 4…
## $ casos_total <dbl> 74, 123, 45, 944, 621, 793, 943, 1991, 1…
## $ tasa_homicidios <dbl> 0.00, 1.90, 0.00, 0.23, 0.27, 0.55, 0.16…
## $ tasa_lesiones <dbl> 29.74, 5.70, 3.71, 7.88, 7.02, 10.01, 8.…
## $ tasa_hurto_personas <dbl> 163.57, 142.59, 107.73, 29.24, 88.62, 48…
## $ tasa_hurto_residencias <dbl> 3.72, 0.00, 0.00, 2.20, 8.38, 3.70, 3.01…
## $ tasa_hurto_automotor <dbl> 0.00, 5.70, 0.00, 1.44, 1.08, 0.69, 1.11…
## $ tasa_hurto_bicicletas <dbl> 3.72, 1.90, 7.43, 1.29, 3.78, 1.51, 6.03…
## $ tasa_hurto_comercio <dbl> 11.15, 17.11, 7.43, 1.97, 12.70, 5.35, 9…
## $ tasa_hurto_celulares <dbl> 63.20, 49.43, 33.43, 9.47, 34.85, 16.04,…
## $ tasa_hurto_motos <dbl> 0.00, 0.00, 0.00, 2.27, 0.27, 1.23, 0.95…
## $ tasa_violencia_intrafamiliar <dbl> 0.00, 9.51, 7.43, 15.53, 10.81, 21.52, 1…
## $ tasa_total <dbl> 275.09, 233.84, 167.16, 71.52, 167.77, 1…
## $ em_agrupada <lgl> TRUE, TRUE, TRUE, FALSE, TRUE, FALSE, FA…
## $ pct_pobreza <dbl> 1.37, 0.86, 0.86, 3.12, 1.37, 5.19, 0.84…
## $ edad_promedio <dbl> 36.54, 38.71, 38.71, 33.28, 36.54, 34.50…
## $ salario_promedio <dbl> 3937004, 4280663, 4280663, 1933709, 3937…
## $ pct_estrato_1_2 <dbl> 13.92, 0.63, 0.63, 31.32, 13.92, 29.48, …
## $ pct_estrato_3_4 <dbl> 83.87, 87.06, 87.06, 66.05, 83.87, 68.87…
## $ pct_estrato_5_6 <dbl> 2.21, 12.31, 12.31, 2.63, 2.21, 1.65, 0.…
## $ pct_vivienda_propia <dbl> 54.45, 57.98, 57.98, 36.78, 54.45, 28.86…
## $ pct_arriendo <dbl> 38.00, 36.81, 36.81, 55.53, 38.00, 58.05…
## $ anios_educacion_15mas <dbl> 12.16, 13.57, 13.57, 12.16, 12.16, 10.95…
## $ pct_padre_universitario <dbl> 24.14, 24.16, 24.16, 8.36, 24.14, 4.76, …
## $ pct_madre_universitaria <dbl> 17.37, 14.82, 14.82, 6.13, 17.37, 3.31, …
## $ pct_percibe_inseguridad <dbl> 36.18, 40.88, 40.88, 65.43, 36.18, 49.84…
## $ pct_cerca_ollas <dbl> 17.53, 7.43, 7.43, 17.53, 17.53, 25.91, …
## $ pct_cerca_bares <dbl> 15.68, 17.03, 17.03, 15.68, 15.68, 15.41…
## $ pct_cerca_lotes_oscuros <dbl> 24.15, 16.71, 16.71, 24.15, 24.15, 19.15…
## $ pct_cerca_basureros <dbl> 6.13, 1.35, 1.35, 6.13, 6.13, 8.30, 11.7…
## $ pct_cerca_terminales <dbl> 20.93, 26.66, 26.66, 20.93, 20.93, 3.38,…
## $ pct_cerca_fabricas <dbl> 11.55, 1.70, 1.70, 11.55, 11.55, 5.99, 2…
## $ min_transmilenio <dbl> 13.01, 10.78, 10.78, 6.96, 13.01, 17.76,…
## $ min_sitp <dbl> 9.99, 9.56, 9.56, 5.96, 9.99, 11.43, 6.8…
## $ min_parque <dbl> 7.00, 5.44, 5.44, 8.60, 7.00, 10.39, 5.1…
## $ min_cai_policia <dbl> 21.66, 24.50, 24.50, 18.39, 21.66, 25.32…
## $ min_centro_medico <dbl> 29.82, 34.17, 34.17, 34.18, 29.82, 29.71…
## $ min_cultura <dbl> 33.90, 29.61, 29.61, 42.77, 33.90, 28.10…
## $ min_ciclorruta <dbl> 9.00, 13.45, 13.45, 14.45, 9.00, 18.27, …
Los valores faltantes representan información que no se encuentra disponible para una o varias variables. Su identificación es importante porque pueden afectar los cálculos estadísticos, las comparaciones y las relaciones entre variables.
En esta etapa se revisa la cantidad de datos faltantes en cada columna, con el propósito de determinar si existen limitaciones en la información disponible.
# Calcular la cantidad de valores faltantes por variable
faltantes <- upz %>%
summarise(
across(
everything(),
~ sum(is.na(.))
)
) %>%
pivot_longer(
cols = everything(),
names_to = "Variable",
values_to = "Cantidad_faltantes"
) %>%
filter(Cantidad_faltantes > 0) %>%
arrange(desc(Cantidad_faltantes))
# Presentar los resultados
if (nrow(faltantes) == 0) {
cat("No se encontraron valores faltantes en la base de datos.")
} else {
knitr::kable(
faltantes,
caption = "Variables con valores faltantes"
)
}
## No se encontraron valores faltantes en la base de datos.
Debido a que cada registro representa una UPZ, el código de identificación territorial debe ser único dentro de la base de datos.
Por esta razón, se revisa si existen códigos repetidos que puedan generar duplicidad de información o afectar las comparaciones posteriores.
# Identificar códigos UPZ repetidos
duplicados_upz <- upz %>%
count(upz_cod, name = "Frecuencia") %>%
filter(Frecuencia > 1)
# Presentar el resultado
if (nrow(duplicados_upz) == 0) {
cat("No se encontraron códigos UPZ duplicados.")
} else {
knitr::kable(
duplicados_upz,
caption = "Códigos UPZ duplicados"
)
}
## No se encontraron códigos UPZ duplicados.
Una vez realizadas las verificaciones iniciales, se consolida un resumen de las principales características de la base de datos.
Este resultado permite establecer las condiciones generales de la información con la que se desarrollará el análisis exploratorio.
resumen_base <- tibble(
Indicador = c(
"Cantidad de registros",
"Cantidad de variables",
"Códigos UPZ únicos",
"Valores faltantes",
"Códigos UPZ duplicados"
),
Resultado = c(
nrow(upz),
ncol(upz),
n_distinct(upz$upz_cod),
sum(is.na(upz)),
nrow(duplicados_upz)
)
)
knitr::kable(
resumen_base,
col.names = c("Indicador", "Resultado"),
caption = "Resumen de la exploración inicial"
)
| Indicador | Resultado |
|---|---|
| Cantidad de registros | 112 |
| Cantidad de variables | 67 |
| Códigos UPZ únicos | 112 |
| Valores faltantes | 0 |
| Códigos UPZ duplicados | 0 |
Los resultados muestran que la base de datos está conformada por 112 registros y 67 variables, con una correspondencia de un registro por cada código UPZ.
En la revisión realizada no se identificaron valores faltantes ni códigos territoriales duplicados. Esto representa una condición favorable para continuar con el análisis exploratorio.
Sin embargo, la ausencia de valores faltantes y duplicados no garantiza por sí sola la calidad de toda la información. Todavía es necesario revisar la distribución de las variables, identificar posibles valores extremos y evaluar la coherencia de los indicadores calculados.
Por lo tanto, esta primera revisión constituye un punto de partida para profundizar en el comportamiento estadístico de las variables.
Una vez revisada la estructura general de la información, se inicia el análisis exploratorio de las variables con el propósito de comprender su comportamiento, identificar diferencias entre los territorios y reconocer posibles patrones que puedan orientar la investigación.
En esta etapa se utilizarán estadísticas descriptivas y representaciones gráficas para examinar las principales características de las UPZ de Bogotá.
La población constituye una de las variables fundamentales para comprender las diferencias entre las UPZ, ya que permite dimensionar el tamaño de cada territorio en términos de habitantes.
Su análisis es especialmente importante para este trabajo, porque los indicadores de delitos se expresan tanto en cantidades absolutas como en tasas por cada 10.000 habitantes. Por lo tanto, conocer cómo se distribuye la población permitirá interpretar posteriormente las diferencias en los indicadores de seguridad.
Inicialmente se analiza la cantidad de habitantes registrados en cada UPZ, con el propósito de identificar las diferencias existentes entre los territorios y reconocer cuáles concentran una mayor o menor población.
Primero vamos a calcular las principales medidas estadísticas.
# Calcular las principales medidas descriptivas
# de la población de las UPZ
estadisticas_poblacion <- upz %>%
summarise(
Total_UPZ = n(),
Poblacion_total = sum(poblacion),
Media = mean(poblacion),
Mediana = median(poblacion),
Desviacion_estandar = sd(poblacion),
Minimo = min(poblacion),
Q1 = quantile(poblacion, 0.25),
Q3 = quantile(poblacion, 0.75),
Maximo = max(poblacion)
)
# Presentar resultados
estadisticas_poblacion %>%
tidyr::pivot_longer(
cols = everything(),
names_to = "Estadística",
values_to = "Valor"
) %>%
knitr::kable(
col.names = c("Estadística", "Resultado"),
caption = "Estadísticas descriptivas de población por UPZ"
)
| Estadística | Resultado |
|---|---|
| Total_UPZ | 112.00 |
| Poblacion_total | 7936532.00 |
| Media | 70861.89 |
| Mediana | 54102.50 |
| Desviacion_estandar | 58406.41 |
| Minimo | 30.00 |
| Q1 | 30081.75 |
| Q3 | 100972.25 |
| Maximo | 305907.00 |
| Medida | Qué nos permite conocer |
|---|---|
| Media | Población promedio por UPZ. |
| Mediana | Valor que divide las UPZ en dos grupos iguales. |
| Desviación estándar | Qué tan dispersa está la población respecto a la media. |
| Mínimo y máximo | Los extremos de población. |
| Q1 | El 25 % de las UPZ tiene una población igual o inferior a este valor. |
| Q3 | El 75 % de las UPZ tiene una población igual o inferior a este valor. |
Una comparación especialmente importante será la media frente a la mediana. Si la primera es considerablemente mayor, puede indicar que algunas UPZ con poblaciones muy elevadas están influyendo en el promedio.
Ahora vamos a visualizar cómo se distribuye la población entre las 112 UPZ
# Histograma de la población por UPZ
ggplot(upz, aes(x = poblacion)) +
geom_histogram(
bins = 20,
fill = magenta,
color = "white",
alpha = 0.85
) +
labs(
title = "Distribución de la población por UPZ",
subtitle = "Población proyectada para el año 2023",
x = "Cantidad de habitantes",
y = "Número de UPZ",
caption = "Fuente: Base de datos del taller."
) +
scale_x_continuous(
labels = scales::label_number(
big.mark = ".",
decimal.mark = ","
)
) +
tema_clase
El histograma nos permite observar dónde se concentra la mayor cantidad de UPZ según su población.
También nos ayuda a identificar si la distribución es simétrica o si presenta una concentración de territorios con poblaciones pequeñas y unos pocos territorios con poblaciones considerablemente mayores.
No debemos asumir que la población se distribuye de manera uniforme entre las UPZ.
Y como el histograma nos muestra el comportamiento general, pero ahora necesitamos identificar los territorios que se encuentran en los extremos.
Vamos a construir dos rankings: las 10 UPZ más pobladas y las 10 menos pobladas.
# 10 UPZ con mayor población
upz_mayor_poblacion <- upz %>%
arrange(desc(poblacion)) %>%
select(
upz_nombre,
localidad,
poblacion
) %>%
slice_head(n = 10)
# 10 UPZ con menor población
upz_menor_poblacion <- upz %>%
arrange(poblacion) %>%
select(
upz_nombre,
localidad,
poblacion
) %>%
slice_head(n = 10)
# Presentar las UPZ más pobladas
knitr::kable(
upz_mayor_poblacion,
col.names = c("UPZ", "Localidad", "Habitantes"),
caption = "Las 10 UPZ con mayor población",
digits = 0
)
| UPZ | Localidad | Habitantes |
|---|---|---|
| Tibabuyes | Suba | 305907 |
| El Rincon | Suba | 295322 |
| Bosa Central | Bosa | 237111 |
| Bosa Occidental | Bosa | 199365 |
| Suba | Suba | 186728 |
| Garces Navas | Engativá | 168657 |
| Ismael Perdomo | Ciudad Bolívar | 166602 |
| Lucero | Ciudad Bolívar | 163588 |
| El Porvenir | Bosa | 143758 |
| Engativa | Engativá | 142612 |
# Presentar las UPZ menos pobladas
knitr::kable(
upz_menor_poblacion,
col.names = c("UPZ", "Localidad", "Habitantes"),
caption = "Las 10 UPZ con menor población",
digits = 0
)
| UPZ | Localidad | Habitantes |
|---|---|---|
| El Mochuelo | Ciudad Bolívar | 30 |
| Aeropuerto El Dorado | Fontibón | 883 |
| Parque Entrenubes | Usme | 1169 |
| Parque Salitre | Barrios Unidos | 1442 |
| Paseo De Los Libertadores | Usaquén | 2690 |
| Guaymaral | Suba | 2692 |
| Jardin Botanico | Engativá | 2900 |
| Parque Simon Bolivar - Can | Teusaquillo | 3323 |
| La Academia | Suba | 5260 |
| Monte Blanco | Ciudad Bolívar | 6575 |
Ahora vamos a representar visualmente estos resultados.
# Preparar los datos de las 10 UPZ más pobladas
ggplot(
upz_mayor_poblacion,
aes(
x = reorder(upz_nombre, poblacion),
y = poblacion
)
) +
geom_col(
fill = morado,
width = 0.7
) +
coord_flip() +
labs(
title = "Las UPZ con mayor concentración de población",
subtitle = "Ranking de las 10 UPZ más pobladas de Bogotá",
x = NULL,
y = "Cantidad de habitantes",
caption = "Fuente: Base de datos del taller."
) +
scale_y_continuous(
labels = scales::label_number(
big.mark = ".",
decimal.mark = ","
)
) +
tema_clase
La cantidad de habitantes no es el único elemento que permite caracterizar un territorio. También es importante considerar su extensión geográfica para comprender qué tan concentrada se encuentra la población.
Para ello se utiliza la densidad poblacional, medida en habitantes por kilómetro cuadrado (hab/km²). Este indicador relaciona la población de cada UPZ con el área que ocupa.
Su análisis permite diferenciar territorios con grandes poblaciones y extensiones amplias de aquellos que presentan una mayor concentración de habitantes en superficies más reducidas.
# Estadísticas descriptivas de densidad poblacional
estadisticas_densidad <- upz %>%
summarise(
Media = mean(densidad_hab_km2),
Mediana = median(densidad_hab_km2),
Desviacion_estandar = sd(densidad_hab_km2),
Minimo = min(densidad_hab_km2),
Q1 = quantile(densidad_hab_km2, 0.25),
Q3 = quantile(densidad_hab_km2, 0.75),
Maximo = max(densidad_hab_km2)
)
knitr::kable(
estadisticas_densidad,
digits = 2,
caption = "Estadísticas descriptivas de la densidad poblacional"
)
| Media | Mediana | Desviacion_estandar | Minimo | Q1 | Q3 | Maximo |
|---|---|---|---|---|---|---|
| 19119.36 | 20180.22 | 10801.85 | 9.44 | 11160.41 | 25826.54 | 46156.87 |
# Identificar las UPZ con mayor densidad poblacional
ranking_densidad <- upz %>%
arrange(desc(densidad_hab_km2)) %>%
select(
upz_nombre,
localidad,
poblacion,
area_km2,
densidad_hab_km2
)
# Presentar las 10 UPZ con mayor densidad
knitr::kable(
ranking_densidad %>% slice_head(n = 10),
col.names = c(
"UPZ",
"Localidad",
"Habitantes",
"Área (km²)",
"Densidad (hab/km²)"
),
digits = 2,
caption = "Las 10 UPZ con mayor densidad poblacional"
)
| UPZ | Localidad | Habitantes | Área (km²) | Densidad (hab/km²) |
|---|---|---|---|---|
| Bosa Occidental | Bosa | 199365 | 4.32 | 46156.87 |
| Patio Bonito | Kennedy | 137776 | 3.18 | 43262.66 |
| Calandaima | Kennedy | 134340 | 3.20 | 41970.43 |
| Tibabuyes | Suba | 305907 | 7.29 | 41963.01 |
| El Rincon | Suba | 295322 | 7.13 | 41440.43 |
| San Francisco | Ciudad Bolívar | 72057 | 1.79 | 40199.86 |
| Verbenal | Usaquén | 131999 | 3.57 | 36967.66 |
| Diana Turbay | Rafael Uribe Uribe | 76093 | 2.12 | 35859.94 |
| Gran Britalia | Kennedy | 62139 | 1.81 | 34416.53 |
| Marruecos | Rafael Uribe Uribe | 123085 | 3.64 | 33796.36 |
# Presentar las 10 UPZ con menor densidad
knitr::kable(
ranking_densidad %>% arrange(densidad_hab_km2) %>% slice_head(n = 10),
col.names = c(
"UPZ",
"Localidad",
"Habitantes",
"Área (km²)",
"Densidad (hab/km²)"
),
digits = 2,
caption = "Las 10 UPZ con menor densidad poblacional"
)
| UPZ | Localidad | Habitantes | Área (km²) | Densidad (hab/km²) |
|---|---|---|---|---|
| El Mochuelo | Ciudad Bolívar | 30 | 3.18 | 9.44 |
| Aeropuerto El Dorado | Fontibón | 883 | 7.46 | 118.40 |
| Parque Entrenubes | Usme | 1169 | 4.21 | 277.97 |
| Paseo De Los Libertadores | Usaquén | 2690 | 6.33 | 424.81 |
| Guaymaral | Suba | 2692 | 4.55 | 591.30 |
| La Academia | Suba | 5260 | 6.74 | 779.85 |
| Parque Simon Bolivar - Can | Teusaquillo | 3323 | 4.00 | 830.50 |
| Parque Salitre | Barrios Unidos | 1442 | 1.66 | 869.50 |
| Monte Blanco | Ciudad Bolívar | 6575 | 6.98 | 941.73 |
| Jardin Botanico | Engativá | 2900 | 1.62 | 1786.96 |
# Visualizar las 10 UPZ con mayor densidad poblacional
ggplot(
ranking_densidad %>% slice_head(n = 10),
aes(
x = reorder(upz_nombre, densidad_hab_km2),
y = densidad_hab_km2
)
) +
geom_col(
fill = turquesa,
width = 0.7
) +
coord_flip() +
labs(
title = "Concentración de población en las UPZ",
subtitle = "Territorios con mayor densidad poblacional",
x = NULL,
y = "Habitantes por km²",
caption = "Fuente: Base de datos del taller."
) +
scale_y_continuous(
labels = scales::label_number(
big.mark = ".",
decimal.mark = ","
)
) +
tema_clase
Para complementar el análisis anterior, se examina la relación entre la población y el área geográfica de cada UPZ.
Esta comparación permite observar si los territorios con mayor extensión también concentran una mayor cantidad de habitantes o si existen diferencias importantes en la ocupación del espacio.
La visualización se realiza mediante un diagrama de dispersión, en el que cada punto representa una UPZ.
# Relación entre población y área territorial
ggplot(
upz,
aes(
x = area_km2,
y = poblacion
)
) +
geom_point(
color = magenta,
size = 2.8,
alpha = 0.75
) +
geom_smooth(
method = "lm",
se = FALSE,
color = morado,
linewidth = 0.9
) +
labs(
title = "Relación entre población y área de las UPZ",
subtitle = "Cada punto representa una unidad territorial",
x = "Área de la UPZ (km²)",
y = "Cantidad de habitantes",
caption = "Fuente: Base de datos del taller."
) +
scale_y_continuous(
labels = scales::label_number(
big.mark = ".",
decimal.mark = ","
)
) +
tema_clase
Si existe una tendencia positiva entre el área y la población.
Si las UPZ de mayor extensión concentran necesariamente más habitantes.
Si existen territorios que se apartan del comportamiento general.
La línea representa una tendencia lineal de referencia. No significa que el área territorial explique por sí sola la cantidad de habitantes.
Durante el análisis de la población es importante identificar territorios que presenten valores considerablemente diferentes al comportamiento general de las UPZ.
Para ello se utiliza el rango intercuartílico (IQR), que corresponde a la diferencia entre el tercer y el primer cuartil de la distribución.
Mediante este procedimiento se identifican posibles valores atípicos, entendidos como observaciones que se encuentran por fuera de los límites estadísticos establecidos.
La identificación de estos valores no significa que deban eliminarse de la información. Por el contrario, permite reconocer territorios con características particulares que deben considerarse en las comparaciones posteriores.
# Calcular los límites para identificar posibles valores atípicos
q1_poblacion <- quantile(upz$poblacion, 0.25)
q3_poblacion <- quantile(upz$poblacion, 0.75)
iqr_poblacion <- IQR(upz$poblacion)
limite_inferior <- q1_poblacion - 1.5 * iqr_poblacion
limite_superior <- q3_poblacion + 1.5 * iqr_poblacion
# Identificar las UPZ que se encuentran fuera de los límites
valores_extremos <- upz %>%
filter(
poblacion < limite_inferior |
poblacion > limite_superior
) %>%
select(
upz_nombre,
localidad,
poblacion,
area_km2,
densidad_hab_km2
) %>%
arrange(desc(poblacion))
# Presentar resultados
knitr::kable(
valores_extremos,
col.names = c(
"UPZ",
"Localidad",
"Habitantes",
"Área (km²)",
"Densidad (hab/km²)"
),
digits = 2,
caption = "UPZ identificadas como posibles valores atípicos en población"
)
| UPZ | Localidad | Habitantes | Área (km²) | Densidad (hab/km²) |
|---|---|---|---|---|
| Tibabuyes | Suba | 305907 | 7.29 | 41963.01 |
| El Rincon | Suba | 295322 | 7.13 | 41440.43 |
| Bosa Central | Bosa | 237111 | 7.17 | 33059.28 |
# Mostrar los límites estadísticos
cat("Límite inferior:", round(limite_inferior, 2), "\n")
## Límite inferior: -76254
cat("Límite superior:", round(limite_superior, 2), "\n")
## Límite superior: 207308
cat("Cantidad de posibles valores atípicos:", nrow(valores_extremos))
## Cantidad de posibles valores atípicos: 3
El análisis demográfico permite reconocer que las UPZ presentan características diferentes en cuanto a su población, extensión y densidad.
Estas diferencias son relevantes para el desarrollo de la investigación, debido a que los indicadores de seguridad pueden presentar comportamientos distintos dependiendo del tamaño y las características de cada territorio.
La identificación de posibles valores extremos también permite reconocer que algunas UPZ pueden tener condiciones particulares que requieren un tratamiento diferenciado al momento de realizar comparaciones estadísticas.
A partir de estos resultados será posible establecer una base más sólida para analizar los indicadores de delitos, diferenciando las cantidades absolutas de las tasas calculadas por habitante.