library(tidyverse) # manipular datos y graficar
library(sf) # leer y dibujar mapas
library(scales) # formatear números (puntos de miles, %)
library(patchwork) # poner dos mapas lado a lado
library(kableExtra) # tablas con estilo
library(plotly) # gráficos interactivos (información al pasar el mouse)azul <- "#2F6DB5" # hurto (delito patrimonial)
vino <- "#A6243D" # violencia contra las personas
gris <- "#CDD0D5" # contexto
noche <- "#1F2430" # títulos
tema_clase <- theme_minimal(base_size = 12) +
theme(
plot.title.position = "plot",
plot.title = element_text(face = "bold", size = 15, color = noche),
plot.subtitle = element_text(size = 10.5, color = "grey35"),
plot.caption = element_text(hjust = 0, color = "grey45", size = 8.5),
panel.grid.minor = element_blank()
)
fuente <- "Fuente: SDSCJ (delitos ene–jul 2023), DANE (población 2023) y Encuesta Multipropósito 2021."
tabla_bonita <- function(df, resaltar = NULL) {
k <- df %>%
kbl() %>%
kable_styling(bootstrap_options = c("hover", "condensed"), full_width = TRUE) %>%
row_spec(0, bold = TRUE, color = "white", background = vino)
if (!is.null(resaltar)) k <- k %>% row_spec(resaltar, bold = TRUE, background = "#F8E9EC")
k
}# Tabla de variables y mapa de las UPZ (rutas relativas)
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)
# Nos quedamos solo con las variables de las 8 preguntas
datos <- upz %>%
select(upz_cod, upz_nombre, localidad, # identificación
poblacion, area_km2, # demografía y territorio
tasa_violencia_intrafamiliar, tasa_hurto_personas, # delitos: tasas
tasa_homicidios,
em_agrupada, # encuesta
pct_estrato_1_2, pct_estrato_3_4, pct_estrato_5_6,
pct_percibe_inseguridad, pct_cerca_ollas,
pct_cerca_lotes_oscuros, min_cai_policia)En Bogotá, la inseguridad suele resumirse en un número: cuántos delitos se denuncian. Pero detrás de ese número hay fenómenos muy distintos: no es lo mismo un robo en una calle comercial que una agresión dentro de un hogar.
Este informe explora las 112 UPZ de Bogotá para responder una pregunta de fondo: ¿qué nos dicen los datos sobre la inseguridad en la ciudad y su relación con el territorio y las condiciones de vida? Comparamos tres tipos de inseguridad —el hurto , la violencia intrafamiliar (VIF) y el homicidio — y cómo la percibe la ciudadanía.No es lo mismo un robo en una calle comercial que una agresión dentro de un hogar. Y no siempre la gente siente más miedo donde más se denuncia.
¿La violencia intrafamiliar se concentra predominantemente en las UPZ de estratos bajos, o se presenta de forma heterogénea a través de los estratos medios y altos?
¿Ocurren más hurtos a personas en UPZ con alta presencia de estratos 5 y 6 o de estratos 1 y 2?
¿El delito de hurto y la violencia intrafamiliar se concentran en las mismas UPZ?
¿La presencia de microtráfico tiene alguna relación con la violencia por homicidios en las UPZ de Bogotá?
¿Cuáles son las 10 UPZ con menor tasa de hurto, y estas se sienten más seguras que el resto de la ciudad?
¿¿Qué genera más miedo en la ciudadanía: el hurto o el deterioro del entorno por la cercanía a ollas de microtráfico O lotes oscuros?
¿Cuáles son las UPZ con mayor porcentaje de viviendas cercanas a lotes baldíos u oscuros, y en cuál de ellas la percepción de inseguridad supera el 90 %?
¿Tener un CAI de policía más cerca se asocia con una mayor percepción de seguridad en la zona?
Para responder las ocho preguntas elegimos 13 variables de cuatro bloques de la base: identificación, demografía, delitos y la Encuesta Multipropósito. La tabla muestra cada variable y la pregunta que ayuda a responder.
Estas 13 variables se consideraron por la mayor relevancia al enfoque de estudio
tibble(
Bloque = c("Identificación", "Identificación", "Identificación",
"Demografía", "Demografía",
"Delitos", "Delitos", "Delitos",
"Encuesta", "Encuesta", "Encuesta", "Encuesta", "Encuesta"),
Variable = c("upz_cod", "upz_nombre", "localidad",
"poblacion", "area_km2",
"tasa_violencia_intrafamiliar", "tasa_hurto_personas", "tasa_homicidios",
"pct_estrato_1_2 / 3_4 / 5_6", "pct_percibe_inseguridad",
"pct_cerca_ollas", "pct_cerca_lotes_oscuros", "min_cai_policia"),
`Para qué la usamos` = c(
"Llave para unir la tabla con el mapa (P3)",
"Nombrar las UPZ en tablas, rankings y gráficos",
"Ubicar cada UPZ en la ciudad",
"Filtrar UPZ con poca población y calcular tasas de Bogotá",
"Medir el hurto por km² (P2)",
"Violencia intrafamiliar (P1, P3, P6)",
"Hurto a personas (P2, P3, P5, P6)",
"Homicidios (P4, P6)",
"Estrato predominante de cada UPZ (P1, P2)",
"Percepción de inseguridad (P5, P6, P7, P8)",
"Microtráfico (P4, P6)",
"Lotes baldíos u oscuros (P6, P7)",
"Cercanía al CAI (P8)")
) %>%
tabla_bonita()| Bloque | Variable | Para qué la usamos |
|---|---|---|
| Identificación | upz_cod | Llave para unir la tabla con el mapa (P3) |
| Identificación | upz_nombre | Nombrar las UPZ en tablas, rankings y gráficos |
| Identificación | localidad | Ubicar cada UPZ en la ciudad |
| Demografía | poblacion | Filtrar UPZ con poca población y calcular tasas de Bogotá |
| Demografía | area_km2 | Medir el hurto por km² (P2) |
| Delitos | tasa_violencia_intrafamiliar | Violencia intrafamiliar (P1, P3, P6) |
| Delitos | tasa_hurto_personas | Hurto a personas (P2, P3, P5, P6) |
| Delitos | tasa_homicidios | Homicidios (P4, P6) |
| Encuesta | pct_estrato_1_2 / 3_4 / 5_6 | Estrato predominante de cada UPZ (P1, P2) |
| Encuesta | pct_percibe_inseguridad | Percepción de inseguridad (P5, P6, P7, P8) |
| Encuesta | pct_cerca_ollas | Microtráfico (P4, P6) |
| Encuesta | pct_cerca_lotes_oscuros | Lotes baldíos u oscuros (P6, P7) |
| Encuesta | min_cai_policia | Cercanía al CAI (P8) |
Antes de analizar, revisamos que los datos estén completos y bien construidos: cuántas UPZ y columnas hay, si faltan valores y si cada UPZ aparece una sola vez.
tibble(
Revisión = c("UPZ (filas) en la base original",
"Columnas en la base original",
"Datos faltantes en nuestras variables",
"UPZ distintas (llave única)"),
Resultado = c(nrow(upz), ncol(upz), sum(is.na(datos)),
n_distinct(datos$upz_cod))
) %>%
tabla_bonita()| Revisión | Resultado |
|---|---|
| UPZ (filas) en la base original | 112 |
| Columnas en la base original | 67 |
| Datos faltantes en nuestras variables | 0 |
| UPZ distintas (llave única) | 112 |
La base se encuentra en condiciones para iniciar un análisis, dado que esta sin datos faltantes y con una llave única.
Antes de confiar en una tasa revisamos su denominador: la población. Una tasa divide los casos entre los habitantes, así que en una UPZ con muy pocos habitantes un solo caso puede dispararla. La tabla muestra las UPZ con menos de 10.000 habitantes.
datos %>%
filter(poblacion < 10000) %>%
arrange(poblacion) %>%
select(UPZ = upz_nombre, Localidad = localidad, `Población` = poblacion,
`Tasa de hurto` = tasa_hurto_personas,
`Tasa de VIF` = tasa_violencia_intrafamiliar) %>%
mutate(across(where(is.numeric), ~ round(.x, 1))) %>%
tabla_bonita()| UPZ | Localidad | Población | Tasa de hurto | Tasa de VIF |
|---|---|---|---|---|
| El Mochuelo | Ciudad Bolívar | 30 | 6333.3 | 0.0 |
| Aeropuerto El Dorado | Fontibón | 883 | 4507.4 | 11.3 |
| Parque Entrenubes | Usme | 1169 | 42.8 | 17.1 |
| Parque Salitre | Barrios Unidos | 1442 | 943.1 | 27.7 |
| Paseo De Los Libertadores | Usaquén | 2690 | 163.6 | 0.0 |
| Guaymaral | Suba | 2692 | 107.7 | 7.4 |
| Jardin Botanico | Engativá | 2900 | 520.7 | 31.0 |
| Parque Simon Bolivar - Can | Teusaquillo | 3323 | 1700.3 | 81.2 |
| La Academia | Suba | 5260 | 142.6 | 9.5 |
| Monte Blanco | Ciudad Bolívar | 6575 | 30.4 | 50.2 |
| Zona Industrial | Puente Aranda | 6666 | 1296.1 | 229.5 |
peso <- datos %>%
summarise(upz = sum(poblacion < 10000),
pct_pob = 100 * sum(poblacion[poblacion < 10000]) / sum(poblacion))Encontramos 11 UPZ con menos de 10.000 habitantes. Casi todas son zonas de paso, como el Aeropuerto El Dorado o los parques Simón Bolívar y Salitre: muchos visitantes y pocos residentes, lo que dispara la tasa (en el aeropuerto supera las 4.500 denuncias por 10.000 habitantes).
Decisión: las excluimos del análisis y las mostramos en gris en el mapa. Son solo el 0,4 % de la población, así que no cambian el panorama de la ciudad.
El histograma muestra cuántas UPZ hay según su número de habitantes. En vino, las que excluimos.
mediana_pob <- median(datos$poblacion)
ggplot(datos, aes(x = poblacion, fill = pob_baja)) +
geom_histogram(bins = 30, color = "white") +
# Mediana: línea suave
geom_vline(xintercept = mediana_pob, color = "grey40", linetype = "dotted", linewidth = 0.6) +
annotate("text", x = mediana_pob + 4000, y = 16, hjust = 0,
label = "Mediana: 54.000", color = "grey30", size = 3.5) +
# Cola hacia la derecha
annotate("text", x = 250000, y = 6, hjust = 0.5,
label = "Cola hacia la derecha:\nTibabuyes, El Rincón\ny Bosa Central",
color = "grey35", size = 3.2) +
annotate("segment", x = 220000, xend = 300000, y = 3.8, yend = 3.8,
arrow = arrow(length = unit(0.2, "cm")), color = "grey50") +
scale_fill_manual(values = c(`TRUE` = vino, `FALSE` = gris),
labels = c(`TRUE` = "Excluidas (11)", `FALSE` = "Analizadas (101)"),
name = NULL) +
scale_x_continuous(labels = label_comma(big.mark = ".")) +
labs(title = "La mayoría de UPZ son medianas; unas pocas son muy pequeñas o muy grandes",
subtitle = "Número de UPZ según su población · en vino, las 11 UPZ con menos de 10.000 habitantes · línea punteada: mediana",
x = "Población de la UPZ (2023)", y = "Número de UPZ", caption = fuente) +
tema_clase +
theme(legend.position = "top")La mitad de las UPZ tiene entre 30.000 y 101.000 habitantes, con una mediana de 54.000. La distribución tiene una cola hacia la derecha: unas pocas UPZ residenciales de la periferia, como Tibabuyes y El Rincón en Suba o Bosa Central, superan los 200.000 habitantes. Por eso comparamos las UPZ con tasas por habitante y no con el número de casos, que crecería solo por el tamaño.
Excluimos las UPZ con pocos habitantes debido a que , un solo caso la mueve bruscamente; en cambio una con cientos de miles, apenas la altera.
Revisamos las tres tasas que usan nuestras preguntas en las 101 UPZ.
datos_f %>%
select(`Hurto a personas` = tasa_hurto_personas,
`Violencia intrafamiliar` = tasa_violencia_intrafamiliar,
`Homicidios` = tasa_homicidios) %>%
pivot_longer(everything(), names_to = "Delito", values_to = "tasa") %>%
group_by(Delito) %>%
summarise(
`Mínimo` = min(tasa),
Q1 = quantile(tasa, 0.25),
Mediana = median(tasa),
Media = mean(tasa),
Q3 = quantile(tasa, 0.75),
`Máximo` = max(tasa),
`Desv. est.` = sd(tasa)
) %>%
mutate(across(where(is.numeric), ~ round(.x, 1))) %>%
tabla_bonita()| Delito | Mínimo | Q1 | Mediana | Media | Q3 | Máximo | Desv. est. |
|---|---|---|---|---|---|---|---|
| Homicidios | 0.0 | 0.2 | 0.6 | 0.9 | 1.1 | 6.2 | 1.1 |
| Hurto a personas | 15.7 | 54.3 | 96.0 | 167.7 | 159.7 | 1487.5 | 223.9 |
| Violencia intrafamiliar | 5.4 | 12.5 | 17.6 | 21.7 | 23.3 | 232.1 | 24.1 |
La UPZ típica (mediana) registra 96 denuncias de hurto, 18 de violencia intrafamiliar y 0,6 homicidios por cada 10.000 habitantes. El hurto es 5 veces la VIF y más de 150 veces los homicidios.
En las tres, la media es mayor que la mediana: la mayoría de las UPZ tiene valores bajos y unas pocas se disparan.
Las tres tasas varían mucho entre UPZ: su desviación estándar es incluso mayor que su media. Pero esa variación no viene de la mayoría, sino de unas pocas UPZ con valores muy altos. En el hurto el efecto es tan fuerte que el promedio (167,7) supera al 75 % de las UPZ: no representa a la UPZ típica, sino que lo arrastran los extremos. Por eso describimos cada tasa con la mediana y medimos las relaciones con la correlación de Spearman, que no se dejan influir por esos valores.
Para comparar la inseguridad por estrato necesitábamos clasificar cada UPZ, pero la base no asigna un estrato único: reporta qué porcentaje de las viviendas pertenece a los estratos 1–2, 3–4 y 5–6. Por eso construimos una variable nueva, el estrato predominante, que asigna a cada UPZ el rango con la mayor proporción de viviendas.
datos_f <- datos_f %>%
mutate(
estrato_dom = case_when(
pct_estrato_1_2 >= pmax(pct_estrato_3_4, pct_estrato_5_6) ~ "Estrato 1–2",
pct_estrato_3_4 >= pct_estrato_5_6 ~ "Estrato 3–4",
TRUE ~ "Estrato 5–6"
),
estrato_dom = factor(estrato_dom, levels = c("Estrato 1–2", "Estrato 3–4", "Estrato 5–6"))
)
datos_f %>%
count(`Estrato predominante` = estrato_dom, name = "UPZ") %>%
mutate(`% de las UPZ` = round(100 * UPZ / sum(UPZ), 1)) %>%
tabla_bonita()| Estrato predominante | UPZ | % de las UPZ |
|---|---|---|
| Estrato 1–2 | 41 | 40.6 |
| Estrato 3–4 | 53 | 52.5 |
| Estrato 5–6 | 7 | 6.9 |
De las 101 UPZ, el 41 % corresponden al estrato 1–2, el 52 % de estrato 3–4 y solo el 7 % de estrato 5–6. Esta clasificación simplifica la realidad, porque una UPZ puede mezclar viviendas de varios estratos, pero permite comparar grupos de forma clara.
Antes de responder cada pregunta, revisamos de forma general cómo se relacionan las variables. Usamos la correlación de Spearman, que va de −1 a 1: en vino, las variables que aumentan juntas; en azul, las que se mueven en sentido contrario.
nombres <- c(
tasa_hurto_personas = "Hurto a personas",
tasa_violencia_intrafamiliar = "Violencia intrafamiliar",
tasa_homicidios = "Homicidios",
pct_estrato_1_2 = "% estrato 1–2",
pct_estrato_3_4 = "% estrato 3–4",
pct_estrato_5_6 = "% estrato 5–6",
pct_percibe_inseguridad = "% percibe inseguridad",
pct_cerca_ollas = "% cerca de ollas",
pct_cerca_lotes_oscuros = "% cerca de lotes oscuros",
min_cai_policia = "Minutos al CAI"
)
datos_f %>%
select(all_of(names(nombres))) %>%
cor(method = "spearman") %>%
as.data.frame() %>%
rownames_to_column("var1") %>%
pivot_longer(-var1, names_to = "var2", values_to = "rho") %>%
mutate(var1 = factor(nombres[var1], levels = nombres),
var2 = factor(nombres[var2], levels = nombres)) %>%
filter(as.integer(var1) > as.integer(var2)) %>% # solo el triángulo inferior
ggplot(aes(x = var2, y = fct_rev(var1), fill = rho)) +
geom_tile(color = "white", linewidth = 0.8) +
geom_text(aes(label = format(round(rho, 2), nsmall = 2, decimal.mark = ","),
color = abs(rho) > 0.5), size = 3.2) +
scale_fill_gradient2(low = azul, mid = "white", high = vino,
midpoint = 0, limits = c(-1, 1), name = "Spearman") +
scale_color_manual(values = c(`TRUE` = "white", `FALSE` = noche), guide = "none") +
labs(title = "El hurto y la violencia se relacionan con variables opuestas",
subtitle = "Correlación de Spearman entre las variables del análisis · 101 UPZ",
x = NULL, y = NULL, caption = fuente) +
tema_clase +
theme(axis.text.x = element_text(angle = 45, hjust = 1), panel.grid = element_blank())
Esta matriz nos permite tener un panorama general de como se relacionan
las variables elegidas entre si, dandonos un panorama hacia donde llevar
la historia, puesto que se abordaran más adetalle en los hallazgos por
cada pregunta. Por el momento se puede destacar que la presencia de
ollas es alta en estratos bajos y si nos vamos al otro extremo vemos que
la percepción de seguridad es mayor en estratos 5-6.
Hasta ahora exploramos las denuncias por delitos. Las preguntas también usan cuatro variables de la Encuesta Multipropósito, que describen lo que la gente percibe de su entorno.
datos_f %>%
select(`% que percibe inseguridad` = pct_percibe_inseguridad,
`% de viviendas cerca de ollas` = pct_cerca_ollas,
`% de viviendas cerca de lotes oscuros` = pct_cerca_lotes_oscuros,
`Minutos caminando al CAI` = min_cai_policia) %>%
pivot_longer(everything(), names_to = "Variable", values_to = "valor") %>%
group_by(Variable) %>%
summarise(`Mínimo` = min(valor),
Q1 = quantile(valor, 0.25),
Mediana = median(valor),
Q3 = quantile(valor, 0.75),
`Máximo` = max(valor)) %>%
mutate(across(where(is.numeric), ~ round(.x, 1))) %>%
tabla_bonita()| Variable | Mínimo | Q1 | Mediana | Q3 | Máximo |
|---|---|---|---|---|---|
| % de viviendas cerca de lotes oscuros | 0.6 | 11.3 | 17.9 | 24.9 | 59.8 |
| % de viviendas cerca de ollas | 0.3 | 10.1 | 20.9 | 30.5 | 75.6 |
| % que percibe inseguridad | 17.4 | 48.5 | 66.0 | 74.3 | 92.1 |
| Minutos caminando al CAI | 10.1 | 15.1 | 17.5 | 20.5 | 35.1 |
La percepción de inseguridad es alta en buena parte de la ciudad: en la UPZ típica, el 66 % de las personas reporta problemas de inseguridad en su entorno, y en tres de cada cuatro UPZ supera el 48 %.
En la UPZ típica, una de cada cinco viviendas tiene cerca una olla de microtráfico. En cambio, el tiempo caminando al CAI varía poco: la mitad de las UPZ está entre 15 y 20 minutos.
En este apartado le daremos respuesta a las preguntas plantedas por medio de visualización grafica e informaremos los hallazgos evidenciados en cada una de ellas.
tasa_bogota_vif <- sum(datos$tasa_violencia_intrafamiliar * datos$poblacion) / sum(datos$poblacion)
datos_f %>%
mutate(y = pmin(tasa_violencia_intrafamiliar, 99)) %>% # recorta el valor extremo
ggplot(aes(x = estrato_dom, y = y)) +
geom_boxplot(fill = "#F3D9DE", color = "grey55", width = 0.5,
outlier.color = vino, outlier.size = 2.5) +
geom_hline(yintercept = tasa_bogota_vif, color = azul, linetype = "dashed") +
annotate("text", x = 3.45, y = tasa_bogota_vif + 2.5, label = "Bogotá: 20,2",
color = azul, hjust = 1, size = 3.2) +
coord_cartesian(ylim = c(0, 100)) +
labs(title = "La violencia intrafamiliar se denuncia más en los estratos bajos,\npero también hay UPZ críticas en los estratos medios",
subtitle = "Tasa de VIF por UPZ según estrato predominante · eje recortado: una UPZ de estrato 3–4 llega a 232",
x = NULL, y = "Denuncias de VIF por 10.000 hab", caption = fuente) +
tema_clase +
theme(panel.grid.major.x = element_blank())Se evidencia que la violencia intrafamiliar en Bogotá no se concentra exclusivamente en los estratos bajos, pero tampoco se distribuye de forma pareja: los estratos 1-2 son los que, en conjunto, cargan con la mayor tasa de denuncias, mientras que los estratos 5-6 registran los niveles más bajos y homogéneos (alrededor de 9,4). Sin embargo, no se debe pasar por alto el comportamiento de denuncias en estratos medios: aunque su mediana es más baja (15,5), allí aparecen las UPZ más críticas de toda la ciudad, con tasas superiores a 80 denuncias por 10.000 habitantes, por encima del caso más extremo de los estratos bajos y más de cuatro veces el promedio de Bogotá.
En resumen, podemos decir que el problema es predominante en los estratos bajos, pero heterogéneo en la población. Además, estas cifras miden lo que se denuncia y no necesariamente todo lo que ocurre, por lo que las tasas bajas de los estratos altos podrían esconder subregistros.
datos_f %>%
group_by(estrato_dom) %>%
summarise(hurto = median(tasa_hurto_personas)) %>%
mutate(destacar = estrato_dom == "Estrato 5–6") %>%
ggplot(aes(x = hurto, y = estrato_dom, fill = destacar)) +
geom_col(width = 0.6) +
geom_text(aes(label = round(hurto), color = destacar),
hjust = -0.3, size = 4.2, fontface = "bold") +
scale_fill_manual(values = c(`TRUE` = vino, `FALSE` = gris), guide = "none") +
scale_color_manual(values = c(`TRUE` = vino, `FALSE` = "grey55"), guide = "none") +
scale_x_continuous(limits = c(0, 175), expand = c(0, 0)) +
labs(title = "Las denuncias por hurto predominan en UPZ de estratos medios y altos",
x = "Denuncias de hurto por cada 10.000 habitantes", y = NULL, caption = fuente) +
tema_clase +
theme(panel.grid.major.y = element_blank())El hurto a personas en Bogotá es, sobre todo, un fenómeno de estratos medios y altos: las UPZ de estratos 5-6 registran 154 denuncias por cada 10.000 habitantes y las de estratos 3-4, 147, frente a solo 52 en los estratos 1-2, es decir, casi tres veces menos. Esto contrasta con la violencia intrafamiliar, que se denuncia más en los estratos bajos, lo que revela que la inseguridad no golpea igual a todos: en unas zonas la amenaza está en el hogar y en otras en la calle. Sin embargo, la baja tasa de denuncias en los estratos 1-2 no indica que el hurto no ocurra; podría deberse a un tema de cultura ciudadana y a la percepción que tiene esta población sobre la importancia de denunciar este tipo de delitos, y sobre cuánto vale el esfuerzo frente al resultado obtenido al hacerlo.
med_hurto <- median(datos_f$tasa_hurto_personas)
med_vif <- median(datos_f$tasa_violencia_intrafamiliar)
mapa <- upz_shp %>%
left_join(datos %>% select(upz_cod, nom = upz_nombre, loc = localidad, poblacion, pob_baja,
tasa_hurto_personas, tasa_violencia_intrafamiliar),
by = "upz_cod") %>%
mutate(grupo = case_when(
is.na(pob_baja) | pob_baja ~ "Excluida (menos de 10.000 hab)",
tasa_hurto_personas > med_hurto & tasa_violencia_intrafamiliar > med_vif ~ "Ambos altos",
tasa_hurto_personas > med_hurto ~ "Solo hurto alto",
tasa_violencia_intrafamiliar > med_vif ~ "Solo VIF alta",
TRUE ~ "Ambos bajos"),
grupo = factor(grupo, levels = c("Solo hurto alto", "Solo VIF alta", "Ambos altos",
"Ambos bajos", "Excluida (menos de 10.000 hab)")),
info = paste0("<b>", nom, "</b><br>", loc,
"<br>Población: ", format(poblacion, big.mark = ".", decimal.mark = ","), " hab",
"<br>Tasa de hurto: ", round(tasa_hurto_personas, 1),
"<br>Tasa de VIF: ", round(tasa_violencia_intrafamiliar, 1),
"<br><b>", grupo, "</b>"))
g_mapa <- ggplot(mapa) +
geom_sf(aes(fill = grupo, text = info), color = "white", linewidth = 0.2) +
scale_fill_manual(values = c("Solo hurto alto" = azul,
"Solo VIF alta" = vino,
"Ambos altos" = "#3A1F4D",
"Ambos bajos" = gris,
"Excluida (menos de 10.000 hab)" = "#EFEFEF"),
name = NULL) +
theme_void()
ggplotly(g_mapa, tooltip = "text") %>%
layout(
title = list(
text = paste0("<b>El hurto y la violencia intrafamiliar se concentran<br>",
"en zonas distintas de Bogotá</b>",
"<br><span style='font-size:12px; color:grey'>",
"Alto = tasa por encima de la mediana de las 101 UPZ</span>"),
x = 0.01, xanchor = "left", font = list(size = 18, color = noche)),
margin = list(t = 80),
legend = list(title = list(text = ""),
orientation = "v",
x = 0.01, y = 0.01, xanchor = "left", yanchor = "bottom",
bgcolor = "rgba(255,255,255,0.85)")) %>%
config(displayModeBar = FALSE)