library(tidyverse)   # dplyr, ggplot2, readr, tidyr, forcats
library(sf)          # datos espaciales (shapefiles)
library(scales)      # formatos de números en ejes y tablas
library(ggrepel)     # etiquetas que no se pisan
library(patchwork)   # combinar gráficos
library(knitr)       # tablas con kable()
library(leaflet)     # mapas interactivos (hover y datos por UPZ)
library(htmltools)   # para armar el diseño de los mapas en el HTML

# Paleta y tema del curso: un color para lo importante (magenta), otro para el
# contexto (morado / gris) y uno para las líneas de tendencia (turquesa).
morado   <- "#351A4F"
magenta  <- "#D9006C"
turquesa <- "#168C86"
gris     <- "#D9D6DD"

tema_clase <- theme_minimal(base_size = 12) +
  theme(
    plot.title.position = "plot",
    plot.title    = element_text(face = "bold", size = 14, hjust = 0),
    plot.subtitle = element_text(size = 10.5, color = "grey35", hjust = 0),
    panel.grid.minor = element_blank(),
    plot.caption  = element_text(hjust = 0, color = "grey45", size = 8.5),
    plot.margin   = margin(10, 20, 10, 10)
  )
theme_set(tema_clase)

# Funciones auxiliares de formato (separador de miles "." y decimal ",")
f2   <- function(x, d = 2) formatC(x, format = "f", digits = d, decimal.mark = ",")
mil  <- function(x) number(x, accuracy = 1, big.mark = ".", decimal.mark = ",")
fmt  <- function(x) ifelse(abs(x) >= 1000,
                           number(x, accuracy = 1,    big.mark = ".", decimal.mark = ","),
                           number(x, accuracy = 0.01, big.mark = ".", decimal.mark = ","))
pval <- function(p) ifelse(p < 0.001, "p < 0,001", paste0("p = ", f2(p, 3)))

1. Introducción y preguntas

Bogotá se organiza en 112 UPZ (Unidades de Planeamiento Zonal) urbanas. Para cada una tenemos cuántos delitos denunciaron entre enero y julio de 2023, y además quién vive allí, cuánto gana, qué tan cerca queda un CAI y qué tan insegura se siente la zona.El analisis del taller está enfocado en los datos de inseguridad y la relación con el territorio y las condiciones de vida de cada sector demostrando que según el delito que miremos (hurto o violencia), el mapa de Bogotá cambia por completo.

Las preguntas

# Pregunta Variables principales
P1 ¿Las UPZ con más denuncias son las que tienen más delitos por habitante, o solo las más grandes? casos_total, poblacion, tasa_total
P2 ¿Hay relación entre la distancia al CAI y la tasa de inseguridad? min_cai_policia
P3 ¿Cambia el tipo de delito predominante según el estrato o el salario de la zona? pct_estrato_*, salario_promedio
P4 ¿La percepción de inseguridad coincide con lo que dicen las denuncias? pct_percibe_inseguridad, tasas
P5 ¿Vivir cerca de “ollas” o bares se asocia con más delitos? pct_cerca_ollas, pct_cerca_bares, tasas
P6 ¿La pobreza y el hacinamiento se asocian con algún tipo de delito? pct_pobreza, personas_por_vivienda, tasas
P7 ¿Dónde se concentran las denuncias y qué tan lejos queda el CAI de esos lugares? mapa de tasa_total y min_cai_policia

Las variables que elegimos

Trabajamos con 16 variables de los 3 bloques (más las llaves upz_cod y upz_nombre). Elegimos tasas por 10.000 habitantes y no conteos, porque a través de las tasas podemos tener una visión clara de inseguridad (Pregunta 1) y no tuvimos en cuenta delitos que consideramos no aportaban claridad como: bicicletas, automotores, motos, residencias, lesiones) y las variables de servicios que no influyen con las preguntas (parques, centros médicos, etc.).

vars <- tribble(
  ~variable,                      ~bloque,                ~etiqueta,                          ~por_que,
  "personas_por_vivienda",        "Vivienda",             "Personas por vivienda",            "Aproximación al hacinamiento (P6)",
  "tasa_homicidios",              "Delitos",              "Homicidios",                       "El delito más grave (P3-P6)",
  "tasa_hurto_personas",          "Delitos",              "Hurto a personas",                 "El delito más frecuente (P2-P6)",
  "tasa_hurto_comercio",          "Delitos",              "Hurto a comercio",                 "Hurto ligado a zonas de actividad comercial (P2-P3)",
  "tasa_hurto_celulares",         "Delitos",              "Hurto de celulares",               "Oportunidad en espacio público (P2-P3)",
  "tasa_violencia_intrafamiliar", "Delitos",              "Violencia intrafamiliar",          "Violencia en el hogar",
  "tasa_total",                   "Delitos",              "Tasa total",                       "Resumen de denuncias (P1, P2, P4, P7)",
  "pct_pobreza",                  "Encuesta Multipropósito", "% en pobreza",                  "Condición de vida (P6)",
  "salario_promedio",             "Encuesta Multipropósito", "Salario promedio",              "Capacidad económica de la zona (P3)",
  "pct_estrato_1_2",              "Encuesta Multipropósito", "% viviendas estrato 1-2",       "Composición socioeconómica (P3)",
  "pct_estrato_3_4",              "Encuesta Multipropósito", "% viviendas estrato 3-4",       "Composición socioeconómica (P3)",
  "pct_estrato_5_6",              "Encuesta Multipropósito", "% viviendas estrato 5-6",       "Composición socioeconómica (P3)",
  "pct_percibe_inseguridad",      "Encuesta Multipropósito", "% percibe inseguridad",         "Percepción vs. realidad denunciada (P4)",
  "pct_cerca_ollas",              "Encuesta Multipropósito", "% cerca de ollas",              "Entorno (P5)",
  "pct_cerca_bares",              "Encuesta Multipropósito", "% cerca de bares",              "Entorno (P5)",
  "min_cai_policia",              "Encuesta Multipropósito", "Minutos caminando al CAI",      "Presencia policial cercana (P2, P7)"
)
etq      <- setNames(vars$etiqueta, vars$variable)
vars_num <- vars$variable
vars %>%
  transmute(Variable = paste0("`", variable, "`"), Bloque = bloque, `Para qué la usamos` = por_que) %>%
  kable()
Variable Bloque Para qué la usamos
personas_por_vivienda Vivienda Aproximación al hacinamiento (P6)
tasa_homicidios Delitos El delito más grave (P3-P6)
tasa_hurto_personas Delitos El delito más frecuente (P2-P6)
tasa_hurto_comercio Delitos Hurto ligado a zonas de actividad comercial (P2-P3)
tasa_hurto_celulares Delitos Oportunidad en espacio público (P2-P3)
tasa_violencia_intrafamiliar Delitos Violencia en el hogar
tasa_total Delitos Resumen de denuncias (P1, P2, P4, P7)
pct_pobreza Encuesta Multipropósito Condición de vida (P6)
salario_promedio Encuesta Multipropósito Capacidad económica de la zona (P3)
pct_estrato_1_2 Encuesta Multipropósito Composición socioeconómica (P3)
pct_estrato_3_4 Encuesta Multipropósito Composición socioeconómica (P3)
pct_estrato_5_6 Encuesta Multipropósito Composición socioeconómica (P3)
pct_percibe_inseguridad Encuesta Multipropósito Percepción vs. realidad denunciada (P4)
pct_cerca_ollas Encuesta Multipropósito Entorno (P5)
pct_cerca_bares Encuesta Multipropósito Entorno (P5)
min_cai_policia Encuesta Multipropósito Presencia policial cercana (P2, P7)

2. Exploración de datos

2.1 Cargue y estructura

# Rutas relativas: el .Rmd debe estar en la misma carpeta que input/
upz     <- read_csv("input/upz_variables.csv", show_col_types = FALSE)
upz_shp <- st_read("input/shp/upz_bogota.shp",       quiet = TRUE)
loc_shp <- st_read("input/shp/localidades_bogota.shp", quiet = TRUE)

c(filas = nrow(upz), columnas = ncol(upz),
  upz_cod_unicos = n_distinct(upz$upz_cod))
##          filas       columnas upz_cod_unicos 
##            112             67            112
# Estructura, faltantes, ceros y rangos de las variables elegidas
calidad <- upz %>%
  select(all_of(vars_num)) %>%
  pivot_longer(everything(), names_to = "variable", values_to = "v") %>%
  group_by(variable) %>%
  summarise(Tipo = "numérica", Faltantes = sum(is.na(v)), Ceros = sum(v == 0, na.rm = TRUE),
            Mínimo = min(v), Máximo = max(v), .groups = "drop") %>%
  mutate(variable = factor(variable, levels = vars_num)) %>%
  arrange(variable) %>%
  mutate(across(c(Mínimo, Máximo), fmt))
kable(calidad, caption = "Estructura y calidad de las 16 variables elegidas (112 UPZ)")
Estructura y calidad de las 16 variables elegidas (112 UPZ)
variable Tipo Faltantes Ceros Mínimo Máximo
personas_por_vivienda numérica 0 0 1,70 5,80
tasa_homicidios numérica 0 23 0,00 6,93
tasa_hurto_personas numérica 0 0 15,70 6.333
tasa_hurto_comercio numérica 0 0 0,94 1.333
tasa_hurto_celulares numérica 0 0 7,29 2.667
tasa_violencia_intrafamiliar numérica 0 2 0,00 232,06
tasa_total numérica 0 0 64,47 11.333
pct_pobreza numérica 0 0 0,07 16,56
salario_promedio numérica 0 0 845.688 7.977.532
pct_estrato_1_2 numérica 0 8 0,00 100,00
pct_estrato_3_4 numérica 0 6 0,00 100,00
pct_estrato_5_6 numérica 0 78 0,00 98,94
pct_percibe_inseguridad numérica 0 0 17,45 92,11
pct_cerca_ollas numérica 0 0 0,31 75,60
pct_cerca_bares numérica 0 0 0,64 53,91
min_cai_policia numérica 0 0 10,06 35,11

Encontramos que: no hay valores faltantes, hay ceros solo donde corresponde (UPZ sin homicidios.

2.2 Validamos la población para poder confiar en las tasas

Dentro de la rubrica del taller se menciona que hay UPZ con muy pocos habitantes donde la tasa puede llegar a dispararse. Hicimos la siguiente revisión:

upz %>%
  arrange(poblacion) %>%
  transmute(UPZ = upz_nombre, Localidad = localidad, Población = mil(poblacion),
            `Casos (ene-jul 2023)` = mil(casos_total), `Tasa total` = fmt(tasa_total)) %>%
  head(12) %>%
  kable(caption = "Las 12 UPZ menos pobladas")
Las 12 UPZ menos pobladas
UPZ Localidad Población Casos (ene-jul 2023) Tasa total
El Mochuelo Ciudad Bolívar 30 34 11.333
Aeropuerto El Dorado Fontibón 883 545 6.172
Parque Entrenubes Usme 1.169 16 136,87
Parque Salitre Barrios Unidos 1.442 233 1.616
Paseo De Los Libertadores Usaquén 2.690 74 275,09
Guaymaral Suba 2.692 45 167,16
Jardin Botanico Engativá 2.900 266 917,24
Parque Simon Bolivar - Can Teusaquillo 3.323 958 2.883
La Academia Suba 5.260 123 233,84
Monte Blanco Ciudad Bolívar 6.575 80 121,67
Zona Industrial Puente Aranda 6.666 1.573 2.360
Sagrado Corazon Santa Fe 11.247 1.707 1.518

Pudimos observar que UPZ como El Mochuelo y Aeropuerto El Dorado tienen un número bajo de habitantes, sin embargo las tasas son altas lo que permite evidenciar que seguramente no representa la población real ejm: pasajeros, trabajadores, visitantes y zonas industriales.

Decidimos excluir del análisis de tasas las UPZ con menos de 10.000 habitantes. Con ese corte quedan 101 UPZ. Las 11 excluidas seguiran apareciendo en gris en los mapas.

UMBRAL <- 10000

upz <- upz %>%
  mutate(
    poblacion_baja = poblacion < UMBRAL,
    # Estrato dominante: la franja (1-2, 3-4 o 5-6) con mayor % de viviendas
    estrato_dom = case_when(
      pct_estrato_1_2 >= pct_estrato_3_4 & pct_estrato_1_2 >= pct_estrato_5_6 ~ "Estratos 1-2",
      pct_estrato_3_4 >= pct_estrato_5_6 ~ "Estratos 3-4",
      TRUE ~ "Estratos 5-6"),
    # "Centro ampliado": localidades de alta actividad comercial, de oficinas y de tránsito
    # (definición operativa nuestra, para probar la robustez de los resultados)
    centro_ampliado = localidad %in% c("Santa Fe", "La Candelaria", "Los Mártires",
                                       "Chapinero", "Teusaquillo", "Puente Aranda")
  )

a <- upz %>% filter(!poblacion_baja)   # base de análisis: 101 UPZ
excluidas <- upz %>% filter(poblacion_baja) %>% pull(upz_nombre)
mapa_upz <- upz_shp %>% left_join(upz %>% select(-upz_nombre), by = "upz_cod")

nrow(a); excluidas
## [1] 101
##  [1] "Paseo De Los Libertadores"  "La Academia"               
##  [3] "Guaymaral"                  "Parque Entrenubes"         
##  [5] "El Mochuelo"                "Monte Blanco"              
##  [7] "Parque Salitre"             "Parque Simon Bolivar - Can"
##  [9] "Jardin Botanico"            "Zona Industrial"           
## [11] "Aeropuerto El Dorado"

2.3 Distribuciones

g_pob <- ggplot(upz, aes(poblacion, fill = poblacion_baja)) +
  geom_histogram(bins = 30, color = "white") +
  geom_vline(xintercept = UMBRAL, color = magenta, linetype = "dashed") +
  scale_x_log10(labels = label_comma(big.mark = ".")) +
  scale_fill_manual(values = c(`FALSE` = morado, `TRUE` = magenta), guide = "none") +
  labs(title = "11 UPZ tienen menos de 10.000 habitantes",
       subtitle = "Población por UPZ (escala logarítmica). En magenta, las UPZ excluidas del análisis de tasas",
       x = "Población", y = "Número de UPZ")

g_tasa <- ggplot(upz, aes(tasa_total, fill = poblacion_baja)) +
  geom_histogram(bins = 30, color = "white") +
  scale_x_log10(labels = label_comma(big.mark = ".")) +
  scale_fill_manual(values = c(`FALSE` = morado, `TRUE` = magenta), guide = "none") +
  labs(title = "La tasa total está muy sesgada a la derecha",
       subtitle = "Denuncias por 10.000 hab. (escala log.). Las UPZ excluidas son los valores extremos",
       x = "Tasa total (ene-jul 2023)", y = "Número de UPZ")

g_pob + g_tasa

c(media_todas = mean(upz$tasa_total), mediana_todas = median(upz$tasa_total),
  media_101 = mean(a$tasa_total), mediana_101 = median(a$tasa_total)) %>% round(1)
##   media_todas mediana_todas     media_101   mediana_101 
##         503.6         192.5         298.9         186.6

La media de la tasa total con las 112 UPZ es 503,64, pero la mediana es solo 192,52; sin las UPZ de población baja la media baja a 298,93. Hay unas pocas UPZ muy altas que arrastran el promedio. Por eso, decidimos que para el analisis usaremos la mediana para resumir, correlacionar y establecer las escalas para graficar tasas.

2.4 Estadística descriptiva

tabla_resumen <- a %>%
  select(all_of(vars_num)) %>%
  pivot_longer(everything(), names_to = "variable", values_to = "v") %>%
  group_by(variable) %>%
  summarise(Media = mean(v), Mediana = median(v), `Desv. est.` = sd(v),
            Mín = min(v), Q1 = quantile(v, .25), Q3 = quantile(v, .75), Máx = max(v),
            .groups = "drop") %>%
  mutate(variable = factor(variable, levels = vars_num)) %>%
  arrange(variable) %>%
  mutate(Variable = etq[as.character(variable)], .before = 1) %>%
  select(-variable) %>%
  mutate(across(where(is.numeric), fmt))

kable(tabla_resumen, align = "lrrrrrrr",
      caption = "Tabla resumen: estadística descriptiva de las 16 variables (101 UPZ con 10.000 hab. o más)")
Tabla resumen: estadística descriptiva de las 16 variables (101 UPZ con 10.000 hab. o más)
Variable Media Mediana Desv. est. Mín Q1 Q3 Máx
Personas por vivienda 2,78 2,81 0,49 1,70 2,59 3,01 5,80
Homicidios 0,90 0,56 1,13 0,00 0,24 1,14 6,25
Hurto a personas 167,74 96,03 223,88 15,70 54,33 159,66 1.488
Hurto a comercio 11,80 6,93 14,97 0,94 3,75 11,83 92,43
Hurto de celulares 60,98 34,12 85,82 7,29 19,08 59,33 619,66
Violencia intrafamiliar 21,72 17,65 24,08 5,36 12,46 23,33 232,06
Tasa total 298,93 186,56 353,67 64,47 126,39 273,23 2.344
% en pobreza 3,99 2,70 3,83 0,07 0,99 5,79 16,56
Salario promedio 2.553.007 1.826.624 1.768.638 845.688 1.229.038 3.574.567 7.977.532
% viviendas estrato 1-2 41,63 23,69 42,85 0,00 0,57 96,85 100,00
% viviendas estrato 3-4 50,16 66,05 41,45 0,00 2,23 92,70 100,00
% viviendas estrato 5-6 8,10 0,00 22,95 0,00 0,00 0,22 98,94
% percibe inseguridad 61,29 65,97 18,67 17,45 48,52 74,30 92,11
% cerca de ollas 21,45 20,92 15,37 0,31 10,14 30,54 75,60
% cerca de bares 14,54 13,00 10,71 0,64 5,82 19,48 53,91
Minutos caminando al CAI 18,09 17,49 4,40 10,06 15,06 20,54 35,11

Análisis: Entre los delitos la mediana de la tasa de hurto a personas (96,03) es una de las más altas, sine embargo la dispersión es enorme. La percepción de inseguridad es alta en la ciudad (mediana 66,0 %), y el salario promedio de las UPZ va de $845.688 a $7.977.532 mensuales.

2.5 Correlaciones entre las variables elegidas

# Correlación de Spearman entre dos conjuntos de variables, en formato largo
cor_larga <- function(filas, cols, d = a) {
  m <- cor(d[filas], d[cols], method = "spearman")
  as_tibble(m, rownames = "fila") %>%
    pivot_longer(-fila, names_to = "col", values_to = "rho") %>%
    mutate(fila = factor(fila, levels = rev(filas)), col = factor(col, levels = cols))
}

mapa_calor <- function(df, titulo, subtitulo, size = 3) {
  ggplot(df, aes(col, fila, fill = rho)) +
    geom_tile(color = "white") +
    geom_text(aes(label = f2(rho, 2), color = abs(rho) > 0.55), size = size) +
    scale_color_manual(values = c(`TRUE` = "white", `FALSE` = "grey20"), guide = "none") +
    scale_fill_gradient2(low = turquesa, mid = "white", high = magenta, limits = c(-1, 1),
                         name = "Spearman") +
    scale_x_discrete(labels = etq, position = "top") +
    scale_y_discrete(labels = etq) +
    labs(title = str_wrap(titulo, 75), subtitle = str_wrap(subtitulo, 95), x = NULL, y = NULL) +
    theme(axis.text.x = element_text(angle = 40, hjust = 0), panel.grid = element_blank())
}
mapa_calor(cor_larga(vars_num, vars_num),
           "Hurtos e ingreso se mueven juntos; violencia, pobreza y percepción de inseguridad, en el bloque opuesto",
           "Correlación de Spearman entre las 16 variables (101 UPZ). Magenta = positiva, turquesa = negativa",
           size = 2.5)

Lectura de la matriz: aparecen dos bloques opuestos. Por un lado, los hurtos (personas, comercio, celulares) y la tasa total se mueven con el salario y el estrato 3-4. Por el otro, homicidios y violencia intrafamiliar se mueven con la pobreza, el estrato 1-2, la percepción de inseguridad y la cercanía a ollas (ρ de 0,6 a 0,8 en varios casos).

3. Análisis por pregunta

P1. ¿Más denuncias o más delitos por habitante?

top_casos <- a %>% slice_max(casos_total, n = 10)
top_tasa  <- a %>% slice_max(tasa_total,  n = 10)
comunes   <- intersect(top_casos$upz_cod, top_tasa$upz_cod)
solo_casos <- setdiff(top_casos$upz_nombre, top_tasa$upz_nombre)
rho_pob_casos <- cor(a$poblacion, a$casos_total, method = "spearman")
barras_top <- function(d, y, titulo, subt, xlab) {
  d %>%
    mutate(destacada = upz_cod %in% comunes, upz_nombre = fct_reorder(upz_nombre, .data[[y]])) %>%
    ggplot(aes(.data[[y]], upz_nombre, fill = destacada)) +
    geom_col() +
    scale_fill_manual(values = c(`TRUE` = magenta, `FALSE` = gris), guide = "none") +
    scale_x_continuous(labels = label_comma(big.mark = "."), expand = expansion(mult = c(0, .08))) +
    labs(title = titulo, subtitle = subt, x = xlab, y = NULL)
}

p1a <- barras_top(top_casos, "casos_total", "Por número de denuncias",
                  "Top 10 UPZ en casos totales", "Denuncias (ene-jul 2023)")
p1b <- barras_top(top_tasa, "tasa_total", "Por denuncias por habitante",
                  "Top 10 UPZ en tasa total", "Denuncias por 10.000 hab.")
(p1a + p1b) +
  plot_annotation(
    title = paste0(length(comunes), " de las 10 UPZ con más denuncias también lideran por habitante"),
    subtitle = "En magenta, las UPZ que aparecen en ambos rankings",
    theme = theme(plot.title = element_text(face = "bold", size = 14),
                  plot.subtitle = element_text(size = 10.5, color = "grey35")))

a %>%
  slice_max(tasa_total, n = 10) %>%
  transmute(`#` = row_number(), UPZ = upz_nombre, Localidad = localidad,
            Población = mil(poblacion), Casos = mil(casos_total),
            `Tasa total` = fmt(tasa_total), `Hurto a personas` = fmt(tasa_hurto_personas),
            `Min. al CAI` = f2(min_cai_policia, 1), `% percibe insegur.` = f2(pct_percibe_inseguridad, 1),
            `Salario prom. ($)` = mil(salario_promedio)) %>%
  kable(align = "rllrrrrrrr",
        caption = "Ranking: las 10 UPZ con mayor tasa total de denuncias (101 UPZ con 10.000 hab. o más)")
Ranking: las 10 UPZ con mayor tasa total de denuncias (101 UPZ con 10.000 hab. o más)
# UPZ Localidad Población Casos Tasa total Hurto a personas Min. al CAI % percibe insegur. Salario prom. ($)
1 Las Nieves Santa Fe 17.203 4.033 2.344 1.488 10,1 59,9 4.390.281
2 Sagrado Corazon Santa Fe 11.247 1.707 1.518 850,89 10,1 59,9 4.390.281
3 La Sabana Los Mártires 38.856 5.441 1.400 852,12 16,0 83,5 1.914.420
4 Chico Lago Chapinero 38.608 4.985 1.291 841,79 13,1 21,5 7.977.532
5 Puente Aranda Puente Aranda 12.482 1.561 1.251 723,44 17,2 66,3 1.612.726
6 Chapinero Chapinero 26.491 2.901 1.095 699,86 15,6 50,3 4.981.378
7 Teusaquillo Teusaquillo 28.881 2.976 1.030 648,18 10,4 62,9 3.675.044
8 Galerias Teusaquillo 38.425 3.067 798,18 496,55 12,8 48,5 3.574.567
9 Los Alcazares Barrios Unidos 44.678 3.495 782,26 466,90 12,8 69,8 2.188.284
10 La Candelaria Candelaria 18.409 1.371 744,74 448,15 12,7 64,7 2.530.327

Hallazgo Pegunta 1. El conteo y la tasa cuentan casi la misma historia porque las UPZ más denunciadas no son las más pobladas: la correlación entre población y denuncias es solo moderada (ρ = 0,44). Las que aparecen únicamente en el ranking de casos (El Rincon, Bosa Central, Las Ferias) son muy grandes pero con tasas bajas, es decir, tienen muchas denuncias solo porque tienen mucha gente. En cambio, el top de tasas lo dominan UPZ del centro (Las Nieves, Sagrado Corazón, La Sabana, Chico Lago, Chapinero, Teusaquillo…), con poblaciones mediana.

P2. ¿Hay relación entre la distancia al CAI y la tasa de inseguridad?

Esta es la pregunta central de nuestro equipo. Medimos la distancia como min_cai_policia: minutos promedio caminando desde la vivienda hasta el CAI más cercano

rho_total <- cor.test(a$min_cai_policia, a$tasa_total, method = "spearman", exact = FALSE)

tasas6 <- c("tasa_homicidios", "tasa_hurto_personas", "tasa_hurto_comercio",
            "tasa_hurto_celulares", "tasa_violencia_intrafamiliar", "tasa_total")

rho_cai <- map_dfr(tasas6, function(t) {
  r <- cor.test(a$min_cai_policia, a[[t]], method = "spearman", exact = FALSE)
  tibble(variable = t, rho = unname(r$estimate), p = r$p.value)
}) %>%
  mutate(delito = etq[variable])
rho_cai %>% mutate(rho = f2(rho), p = pval(p)) %>% select(Delito = delito, `ρ de Spearman` = rho, `p-valor` = p) %>%
  kable(caption = "Correlación entre minutos al CAI y cada tasa de delito (101 UPZ)")
Correlación entre minutos al CAI y cada tasa de delito (101 UPZ)
Delito ρ de Spearman p-valor
Homicidios -0,11 p = 0,268
Hurto a personas -0,43 p < 0,001
Hurto a comercio -0,30 p = 0,003
Hurto de celulares -0,41 p < 0,001
Violencia intrafamiliar -0,08 p = 0,398
Tasa total -0,43 p < 0,001
a <- a %>% mutate(top10_tasa = upz_cod %in% top_tasa$upz_cod)

ggplot(a, aes(min_cai_policia, tasa_total)) +
  geom_point(aes(color = top10_tasa, alpha = top10_tasa), size = 2.6) +
  geom_smooth(method = "lm", se = FALSE, color = turquesa, linewidth = 1) +
  geom_text_repel(data = filter(a, top10_tasa, tasa_total > 1200), aes(label = upz_nombre),
                  size = 3, color = magenta, min.segment.length = 0, seed = 1) +
  scale_y_log10(labels = label_comma(big.mark = ".")) +
  scale_color_manual(values = c(`TRUE` = magenta, `FALSE` = morado), guide = "none") +
  scale_alpha_manual(values = c(`TRUE` = 1, `FALSE` = .55), guide = "none") +
  labs(title = "Donde el CAI queda más lejos, las denuncias por habitante son menores",
       subtitle = paste0("Spearman ρ = ", f2(rho_total$estimate), " (", pval(rho_total$p.value),
                         ") · 101 UPZ · magenta = 10 UPZ con mayor tasa total"),
       x = "Minutos caminando hasta el CAI más cercano", y = "Denuncias por 10.000 hab. (escala log.)",
       caption = "Fuentes: SDSCJ (delitos ene-jul 2023), DANE (Encuesta Multipropósito 2021). La línea turquesa es un ajuste lineal sobre la escala log.")

rho_cai %>%
  mutate(sig = p < 0.05, delito = fct_reorder(delito, rho, .desc = TRUE)) %>%
  ggplot(aes(rho, delito, fill = sig)) +
  geom_col() +
  geom_text(aes(label = f2(rho), hjust = if_else(rho < 0, 1.15, -0.15)), size = 3.5) +
  geom_vline(xintercept = 0) +
  scale_fill_manual(values = c(`TRUE` = magenta, `FALSE` = gris), guide = "none") +
  scale_x_continuous(limits = c(-.6, .15)) +
  labs(title = "La distancia al CAI solo se asocia con los hurtos, no con la violencia",
       subtitle = "Correlación de Spearman entre minutos al CAI y cada tasa. Magenta = estadísticamente distinta de 0 (p < 0,05)",
       x = "Correlación (ρ)", y = NULL)

Hallazgo Pregunta 2. La correlación entre minutos al CAI y tasa total es negativa y moderada (ρ = -0,43, p < 0,001): donde el CAI queda más cerca, se denuncian más delitos por habitante.

Dos conclusiones de esta correlación:

  1. Es un fenómeno de hurtos. Con hurto a personas (ρ = -0,43) y celulares (ρ = -0,41) es clara; con homicidios (ρ = -0,11) y violencia intrafamiliar (ρ = -0,08) no hay relación distinguible de cero.
  2. Una lectura, que estos datos no pueden confirmar, es que los CAI y las denuncias se ubican donde hay más actividad, más comercio y más cultura de denuncia; en las UPZ periféricas, más lejos del CAI, hay probablemente más subregistro (menos hurtos denunciados, no necesariamente menos hurtos). Tampoco podemos decir que poner un CAI reduzca o aumente el delito.

P3. ¿Cambia el delito predominante según el estrato o el salario?

tasas5 <- c("tasa_homicidios", "tasa_hurto_personas", "tasa_hurto_celulares",
            "tasa_hurto_comercio", "tasa_violencia_intrafamiliar")

por_estrato <- a %>%
  group_by(estrato_dom) %>%
  summarise(n = n(), across(all_of(tasas5), median), .groups = "drop")

por_estrato %>%
  mutate(across(all_of(tasas5), fmt)) %>%
  rename(`Estrato dominante` = estrato_dom, UPZ = n,
         Homicidios = tasa_homicidios, `Hurto personas` = tasa_hurto_personas,
         `Hurto celulares` = tasa_hurto_celulares, `Hurto comercio` = tasa_hurto_comercio,
         `Viol. intrafamiliar` = tasa_violencia_intrafamiliar) %>%
  kable(align = "lrrrrrr", caption = "Tasa mediana por 10.000 hab., según el estrato dominante de la UPZ")
Tasa mediana por 10.000 hab., según el estrato dominante de la UPZ
Estrato dominante UPZ Homicidios Hurto personas Hurto celulares Hurto comercio Viol. intrafamiliar
Estratos 1-2 41 1,00 51,67 17,69 3,47 22,55
Estratos 3-4 53 0,39 147,09 54,16 9,98 15,53
Estratos 5-6 7 0,24 154,49 60,70 10,72 9,39
por_estrato %>%
  pivot_longer(all_of(tasas5), names_to = "variable", values_to = "mediana") %>%
  mutate(delito = factor(etq[variable], levels = etq[tasas5]),
         estrato_lab = str_remove(estrato_dom, "Estratos ")) %>%
  group_by(delito) %>% mutate(es_max = mediana == max(mediana)) %>% ungroup() %>%
  ggplot(aes(estrato_lab, mediana, fill = es_max)) +
  geom_col(width = .7) +
  geom_text(aes(label = fmt(mediana)), vjust = -0.4, size = 3.2) +
  facet_wrap(~ delito, scales = "free_y", nrow = 1) +
  scale_fill_manual(values = c(`TRUE` = magenta, `FALSE` = gris), guide = "none") +
  scale_y_continuous(expand = expansion(mult = c(0, .18))) +
  labs(title = "Homicidios y violencia intrafamiliar bajan con el estrato; los hurtos suben",
       subtitle = "Tasa mediana por 10.000 hab. según el estrato dominante de la UPZ (magenta = grupo con la tasa más alta de ese delito)",
       x = "Estrato dominante de la UPZ", y = "Mediana de la tasa",
       caption = paste0("Número de UPZ: estratos 1-2 = ", por_estrato$n[1], ", 3-4 = ", por_estrato$n[2], ", 5-6 = ", por_estrato$n[3], " (pocas para sacar conclusiones firmes en 5-6). Cada panel tiene su propia escala vertical."))

mapa_calor(cor_larga(c("salario_promedio", "pct_estrato_1_2", "pct_estrato_3_4", "pct_estrato_5_6"),
                     c("tasa_homicidios", "tasa_violencia_intrafamiliar", "tasa_hurto_personas",
                       "tasa_hurto_celulares", "tasa_hurto_comercio")),
           "El salario y el estrato separan los delitos en dos grupos opuestos",
           "Correlación de Spearman entre nivel socioeconómico y tasas de delito (101 UPZ)", size = 3.4)

Hallazgo Pregunta 3. Sí cambia el tipo de delito. En las UPZ de estratos 1-2 el delito que más pesa es la violencia: su tasa mediana de homicidios es 1,0 frente a 0,2 en estratos 5-6, y la violencia intrafamiliar es 2,4 veces mayor. En estratos 3-6 domina el hurto (a personas, celulares, comercio), con tasas de unas 3 veces las de las UPZ de estratos 1-2. El salario promedio confirma el patrón (ρ positiva con los hurtos, negativa con homicidios y violencia intrafamiliar). Esto no significa que los hogares de estrato alto sean “más delincuentes” ni los de estrato bajo “más violentos”: significa que el tipo de delito que se denuncia varía con el territorio, y que el hurto se denuncia más donde hay más cosas que robar y más hábito de denunciar.

P4. ¿La percepción de inseguridad coincide con las denuncias?

rho_perc <- map_dfr(c("tasa_total", "tasa_hurto_personas", "tasa_homicidios", "tasa_violencia_intrafamiliar"), function(t) {
  r <- cor.test(a$pct_percibe_inseguridad, a[[t]], method = "spearman", exact = FALSE)
  tibble(variable = t, rho = unname(r$estimate), p = r$p.value)
})
rho_perc %>% mutate(Delito = etq[variable], `ρ de Spearman` = f2(rho), `p-valor` = pval(p)) %>%
  select(Delito, `ρ de Spearman`, `p-valor`) %>%
  kable(caption = "Correlación entre % que percibe inseguridad en su entorno y cada tasa")
Correlación entre % que percibe inseguridad en su entorno y cada tasa
Delito ρ de Spearman p-valor
Tasa total -0,31 p = 0,002
Hurto a personas -0,39 p < 0,001
Homicidios 0,58 p < 0,001
Violencia intrafamiliar 0,67 p < 0,001
base_p4 <- ggplot(a, aes(pct_percibe_inseguridad)) +
  scale_x_continuous(labels = function(x) paste0(x, " %"))

p4a <- base_p4 +
  geom_point(aes(y = tasa_hurto_personas, shape = em_agrupada), color = morado, alpha = .6, size = 2.4) +
  geom_smooth(aes(y = tasa_hurto_personas), method = "lm", se = FALSE, color = turquesa) +
  scale_y_log10(labels = label_comma(big.mark = ".")) +
  scale_shape_manual(values = c(`FALSE` = 16, `TRUE` = 1), guide = "none") +
  labs(title = str_wrap("Hurto a personas: la percepción baja donde más se denuncia", 40),
       subtitle = paste0("ρ = ", f2(rho_perc$rho[rho_perc$variable == "tasa_hurto_personas"])),
       x = "% que percibe inseguridad en su entorno", y = "Hurto a personas por 10.000 hab. (log)")

p4b <- base_p4 +
  geom_point(aes(y = tasa_homicidios, shape = em_agrupada), color = magenta, alpha = .65, size = 2.4) +
  geom_smooth(aes(y = tasa_homicidios), method = "lm", se = FALSE, color = turquesa) +
  scale_shape_manual(values = c(`FALSE` = 16, `TRUE` = 1), guide = "none") +
  coord_cartesian(ylim = c(0, NA)) +
  labs(title = str_wrap("Homicidios: la percepción sube donde más hay", 40),
       subtitle = paste0("ρ = ", f2(rho_perc$rho[rho_perc$variable == "tasa_homicidios"])),
       x = "% que percibe inseguridad en su entorno", y = "Homicidios por 10.000 hab.")

p4a + p4b +
  plot_annotation(caption = "Círculo vacío = UPZ con valor de encuesta de grupo (em_agrupada). Línea turquesa = ajuste lineal.",
                  theme = theme(plot.caption = element_text(hjust = 0, color = "grey45", size = 8.5)))

Hallazgo Pregunta 4. La percepción de inseguridad sigue a la violencia, no a los hurtos. Se correlaciona positivamente con homicidios (ρ = 0,58) y violencia intrafamiliar (ρ = 0,67), y negativamente con la tasa total y el hurto a personas. Dicho de otro modo: donde más se denuncian hurtos, la gente dice sentirse menos insegura en su entorno inmediato.

P5 y P6. Entorno (ollas, bares), pobreza y hacinamiento

mapa_calor(
  cor_larga(c("pct_cerca_ollas", "pct_cerca_bares", "pct_pobreza", "personas_por_vivienda",
              "pct_percibe_inseguridad", "min_cai_policia"),
            c("tasa_homicidios", "tasa_violencia_intrafamiliar", "tasa_hurto_personas",
              "tasa_hurto_celulares", "tasa_hurto_comercio", "tasa_total")),
  "Ollas, pobreza y hacinamiento se asocian con violencia; los bares, menos",
  "Correlación de Spearman entre condiciones del entorno y tasas de delito (101 UPZ)", size = 3.4)

ggplot(a, aes(pct_pobreza, tasa_homicidios)) +
  geom_point(aes(size = poblacion), color = magenta, alpha = .55) +
  geom_smooth(method = "lm", se = FALSE, color = turquesa) +
  scale_size_area(max_size = 7, labels = label_comma(big.mark = "."), name = "Población") +
  scale_x_continuous(labels = function(x) paste0(x, " %")) +
  labs(title = "Más pobreza, más homicidios por habitante",
       subtitle = paste0("Spearman ρ = ", f2(cor(a$pct_pobreza, a$tasa_homicidios, method = "spearman")),
                         " · 101 UPZ · el tamaño del punto es la población"),
       x = "% de personas en pobreza (Encuesta Multipropósito 2021)", y = "Homicidios por 10.000 hab. (ene-jul 2023)",
       caption = "Los homicidios son pocos casos por UPZ: las tasas son ruidosas. Valores de encuesta compartidos en 32 UPZ.")

r_olla_hom  <- cor(a$pct_cerca_ollas, a$tasa_homicidios, method = "spearman")
r_olla_vif  <- cor(a$pct_cerca_ollas, a$tasa_violencia_intrafamiliar, method = "spearman")
r_olla_hp   <- cor(a$pct_cerca_ollas, a$tasa_hurto_personas, method = "spearman")
r_bar_hom   <- cor(a$pct_cerca_bares, a$tasa_homicidios, method = "spearman")
r_bar_vif   <- cor(a$pct_cerca_bares, a$tasa_violencia_intrafamiliar, method = "spearman")
r_bar_hp    <- cor(a$pct_cerca_bares, a$tasa_hurto_personas, method = "spearman")
r_pob_hom   <- cor(a$pct_pobreza, a$tasa_homicidios, method = "spearman")
r_pob_vif   <- cor(a$pct_pobreza, a$tasa_violencia_intrafamiliar, method = "spearman")
r_hac_hp    <- cor(a$personas_por_vivienda, a$tasa_hurto_personas, method = "spearman")
r_hac_hom   <- cor(a$personas_por_vivienda, a$tasa_homicidios, method = "spearman")
r_olla_perc <- cor(a$pct_cerca_ollas, a$pct_percibe_inseguridad, method = "spearman")
r_hac_pob   <- cor(a$personas_por_vivienda, a$pct_pobreza, method = "spearman")
r_hac_e12   <- cor(a$personas_por_vivienda, a$pct_estrato_1_2, method = "spearman")

Hallazgo Pregunta 5. Las “ollas” se asocian con violencia, no con hurto. El % de viviendas cerca de expendios de droga se correlaciona positivamente con homicidios (ρ = 0,64) y violencia intrafamiliar (ρ = 0,66), y negativamente con el hurto a personas (ρ = -0,41). Los bares muestran una asociación más débil: con violencia (ρ = 0,44 con violencia intrafamiliar y 0,35 con homicidios) y casi ninguna con hurtos (ρ = 0,10). Las ollas también van de la mano de la percepción de inseguridad (ρ = 0,67), lo que es coherente con la pregunta 4: la percepción acompaña a la violencia y a ese problema de entorno.

Hallazgo Pregunta 6. La pobreza y el hacinamiento van con la violencia, y a contramano del hurto. El % en pobreza se asocia con homicidios (ρ = 0,64) y violencia intrafamiliar (ρ = 0,76). Las personas por vivienda, nuestro indicador de hacinamiento, correlacionan con el hurto a personas (ρ = -0,73, fuertemente negativa) y poco con homicidios (ρ = 0,24): las UPZ con viviendas más llenas son también las más pobres (ρ = 0,68 con % en pobreza y 0,71 con % de estrato 1-2), donde se denuncia menos hurto.

P7. ¿Dónde se concentran las denuncias y dónde queda el CAI más lejos?

Cómo usar los mapas: pasa el cursor sobre cualquier UPZ y se sombrea con borde coral; aparece una ficha con su población, sus tasas, los minutos al CAI, la percepción de inseguridad y el salario. Con la rueda del ratón haces zoom y arrastrando te desplazas.

niveles_q <- c("1 (más baja)", "2", "3", "4", "5 (más alta)")
cortes    <- quantile(a$tasa_total, probs = seq(0, 1, .2))

mapa_upz <- mapa_upz %>%
  mutate(q_tasa = if_else(poblacion_baja, "Excluida (< 10.000 hab.)",
                          as.character(cut(tasa_total, breaks = cortes, include.lowest = TRUE, labels = niveles_q))),
         q_tasa = factor(q_tasa, levels = c(niveles_q, "Excluida (< 10.000 hab.)")))

pal_q <- c(setNames(colorRampPalette(c("#F1EAF4", morado))(5), niveles_q),
           "Excluida (< 10.000 hab.)" = gris)
# Texto que aparece al pasar el cursor sobre cada UPZ (HTML dentro de la etiqueta)
mapa_upz <- mapa_upz %>%
  mutate(etiqueta = paste0(
    "<div style='font-size:13px;line-height:1.4;min-width:210px'>",
    "<b style='font-size:15px;color:#0B2E3A'>", upz_nombre, "</b><br>",
    "<span style='color:#168C86'>Localidad: ", localidad, "</span>",
    "<hr style='margin:5px 0;border-top:1px solid #ddd'>",
    "Población: <b>", mil(poblacion), "</b> hab.<br>",
    if_else(poblacion_baja,
            "<i style='color:#D9006C'>Excluida del análisis de tasas (&lt; 10.000 hab.)</i><br>", ""),
    "Tasa total: <b>", fmt(tasa_total), "</b> por 10.000 hab.<br>",
    "&nbsp;&nbsp;· Hurto a personas: ", fmt(tasa_hurto_personas), "<br>",
    "&nbsp;&nbsp;· Homicidios: ", fmt(tasa_homicidios), "<br>",
    "&nbsp;&nbsp;· Viol. intrafamiliar: ", fmt(tasa_violencia_intrafamiliar), "<br>",
    "Minutos al CAI: <b>", f2(min_cai_policia, 1), "</b><br>",
    "% percibe inseguridad: ", f2(pct_percibe_inseguridad, 1), " %<br>",
    "Salario promedio: $", mil(salario_promedio),
    "</div>"))

# Para que el HTML pese menos, simplificamos un poco los contornos (~20 m) solo para los mapas interactivos
sf_use_s2(FALSE)
mapa_upz <- st_simplify(mapa_upz, preserveTopology = TRUE, dTolerance = 0.0002)
loc_shp  <- st_simplify(loc_shp,  preserveTopology = TRUE, dTolerance = 0.0002)

pal_tasa <- colorFactor(palette = unname(pal_q), levels = names(pal_q))
pal_cai  <- colorNumeric(c("#E3F3F2", "#0A4F4B"), domain = mapa_upz$min_cai_policia)

# Opciones comunes: sombrear la UPZ al pasar el cursor y mostrar la etiqueta
resaltar  <- highlightOptions(weight = 3.5, color = "#FF6B4A", fillOpacity = 1, bringToFront = TRUE)
estilo_et <- labelOptions(direction = "auto", textsize = "13px",
                          style = list("padding" = "8px 10px", "border-radius" = "10px",
                                       "box-shadow" = "0 3px 12px rgba(0,0,0,.3)",
                                       "border" = "1px solid #168C86"))

hacer_mapa <- function(relleno, leyenda) {
  leaflet(mapa_upz, height = 520, options = leafletOptions(minZoom = 10)) %>%
    addProviderTiles(providers$CartoDB.Positron) %>%
    addPolygons(fillColor = relleno, fillOpacity = .85, color = "white", weight = .8,
                label = ~lapply(etiqueta, HTML), labelOptions = estilo_et,
                highlightOptions = resaltar) %>%
    # bordes de las localidades como referencia (no interactivos)
    addPolygons(data = loc_shp, fill = FALSE, color = "#4A4A4A", weight = 1.3, opacity = .75,
                options = pathOptions(interactive = FALSE)) %>%
    leyenda
}

mapa_tasa <- hacer_mapa(
  ~pal_tasa(q_tasa),
  . %>% addLegend(colors = unname(pal_q), labels = names(pal_q), opacity = .9,
                  title = "Tasa total<br>(quintiles)", position = "bottomright"))

mapa_cai <- hacer_mapa(
  ~pal_cai(min_cai_policia),
  . %>% addLegend(pal = pal_cai, values = ~min_cai_policia, opacity = .9,
                  title = "Minutos<br>al CAI", position = "bottomright"))

tags$div(class = "mapas-grid",
  tags$div(class = "mapa-card",
           tags$h4("Las denuncias por habitante se concentran en el centro"),
           tags$p("Tasa total por 10.000 hab. (ene-jul 2023), en quintiles"), mapa_tasa),
  tags$div(class = "mapa-card",
           tags$h4("Y es también donde el CAI queda más cerca"),
           tags$p("Minutos promedio caminando hasta el CAI más cercano (2021)"), mapa_cai))

Las denuncias por habitante se concentran en el centro

Tasa total por 10.000 hab. (ene-jul 2023), en quintiles

Y es también donde el CAI queda más cerca

Minutos promedio caminando hasta el CAI más cercano (2021)

Fuentes: SDSCJ, DANE, Encuesta Multipropósito 2021. Líneas grises = localidades. Gris claro en el mapa de la izquierda = UPZ excluidas por población baja (siguen mostrando sus datos al pasar el cursor).

Hallazgo Pregunta 7. Los mapas confirman la Pregunta 1 y Pregunta 2 en el territorio: las tasas totales más altas se agrupan en una franja que va del centro hacia el norte y el oriente-centro de la ciudad, que es también donde los minutos al CAI son menores. Las UPZ de los bordes (noroccidente y sur) tienen CAI a mayor distancia y tasas totales de denuncia más bajas. Esos mapas ocultan que la violencia (homicidios y violencia intrafamiliar) sigue otra geografía, ligada a pobreza y estratos 1-2 (P3 y P6), que la tasa total no ve porque los hurtos pesan mucho más en el conteo.

4. Hallazgos

Bogotá tiene dos geografías de delito, y según desde donde se mire concluye cosas opuestas.

  1. El mapa de las denuncias totales es, sobre todo, un mapa de hurtos (la correlación de la tasa total con el hurto a personas es ρ ≈ 0,99, y con homicidios y violencia intrafamiliar es casi cero).
  2. Los hurtos se denuncian más en el centro y en UPZ de mayor ingreso, donde además el CAI queda más cerca y la gente dice sentirse menos insegura en su entorno inmediato.
  3. La violencia (homicidios, violencia intrafamiliar) tiene otra geografía: UPZ con más pobreza, estratos 1-2, más hacinamiento, más cercanía a ollas y mayor percepción de inseguridad. Ahí el CAI queda algo más lejos (mediana de 18,6 min en UPZ de estratos 1-2 frente a 14,7 en estratos 5-6), pero la distancia al CAI no se asocia con la violencia.
  4. Respondiendo la pregunta central (P2): sí hay una relación entre la distancia al CAI y las denuncias, pero es inversa (más lejos, menos denuncias por habitante) y solo en hurtos. Esto se explica mejor por dónde hay actividad, ingreso y hábito de denunciar que por el efecto de la policía.
  5. La percepción de inseguridad refleja la violencia cotidiana, no el hurto. Quien vive en una UPZ con alto hurto denunciado no necesariamente la percibe como insegura en su entorno, y viceversa.

Es importante que para hace un buen diagnóstico se debería separar el hurto y la violencia para visibilizar el comportamiento integral de la población.

5. Limitaciones y conclusión

Lo que los datos no permiten concluir

  • Correlación no es causalidad. Nada de lo anterior prueba que un CAI, una olla, un bar o el estrato causen un nivel de delito. Son asociaciones entre territorios (UPZ), que no necesariamente valen para personas.
  • Población flotante. Las tasas usan residentes como denominador. En el centro, zonas comerciales y nodos de transporte hay muchas personas que no residen allí, lo que infla la tasa (por ejemplo, Las Nieves).
  • Periodos y años distintos. Delitos y población son de 2023 (enero-julio), la encuesta y las luminarias de 2021. Los delitos son solo siete meses y no tienen en cuenta estacionalidad.
  • Encuesta de muestra y UPZ agrupadas. En 32 UPZ la encuesta da el valor de un grupo; las UPZ vecinas comparten dato (pobreza, salario, estrato, percepción, ollas, bares y minutos al CAI), por lo que hay menos observaciones independientes que las 101 del análisis.
  • Distancia al CAI es una medida gruesa. Son minutos promedio caminando en la encuesta, no la cobertura real ni la dotación o el número de uniformados.
  • Faltan delitos sexuales (la fuente no los publica para 2023), que probablemente cambian la lectura de la violencia.

Conclusión

La pregunta “¿qué nos dicen los datos sobre inseguridad y territorio?” tiene una respuesta incómoda para quien quiera un único indicador: depende de qué inseguridad se mida. Las denuncias de hurto, que dominan la tasa total, se concentran en el centro, en UPZ de mayor ingreso y con CAI más cercano.La violencia y la percepción de inseguridad, en cambio, siguen la pobreza, el hacinamiento y las “ollas”, en zonas más periféricas.

Sobre la pregunta de nuestro equipo, la distancia al CAI se relaciona con las denuncias de hurto, pero en sentido inverso al esperado, y no con la violencia; antes de hablar de “efecto policial” haría falta separar presencia policial, actividad económica y subregistro.

## [1] "R version 4.6.1 (2026-06-24 ucrt)"