Categorías: Uncategorized

Estimación de Antecedentes Penales en Víctimas de Homicidio: Análisis de Datos 2024-2026

Hoy, 5 de marzo de 2026, el presidente Daniel Noboa afirmó que “9 de cada 10 homicidios son personas que tienen antecedentes penales”. Esta afirmación no es menor porque se formula en un contexto de conflicto armado interno y, de ese modo, puede operar como justificación de una política contra el crimen organizado que trata al homicidio como un fenómeno social circunscrito casi exclusivamente al mundo criminal. Si esa premisa es falsa (o exagerada), entonces la política que se desprende de ella también lo es.

Este ejercicio, por tanto, intenta responder una pregunta simple: ¿cuán razonable es ese 90%?

Si nos limitamos a la base de datos pública, la respuesta directa es llanamente imposible. En los registros oficiales de homicidios para 2024, 2025 y (enero de) 2026, la variable que codifica antecedentes penales aparece sistemáticamente vacía: el 100% de los casos figura como “SIN_DATO”, una ausencia que presumiblemente será corregida o actualizada a posteriori, pero demasiado tarde para el análisis de coyuntura.

Ejemplo de registros de 2025.

Ante la restricción de datos, la alternativa inmediata es la estimación indirecta: si no es posible observar directamente si una víctima tenía antecedentes penales, podemos tratar de estimar qué probabilidad le asignaríamos en función de su perfil (edad, sexo, ocupación, hora, lugar y provincia del homicidio) tomando como referencia lo que esas mismas variables predecían en 2023, el año más reciente en que dicha variable sí se encuentra codificada. En ese año, el 21,07% de las víctimas de homicidio registró antecedentes penales (1.738 casos del universo de 8.248 casos).

En concreto, podemos entrenar una regresión logística binomial con los datos de 2023 (n = 7.791 casos, excluyendo datos faltantes), usando seis covariables categóricas para predecir la probabilidad de que una víctima registrase antecedentes penales:

Variable

Niveles

Profesión agrupada

11 niveles (10 más frecuentes + «Otras»)

Rango de edad

5 niveles (0–17, 18–29, 30–44, 45–64, 65+)

Sexo

2 niveles (Hombre, Mujer)

Hora del homicidio

4 niveles (0-5am, 6-11am, 12-17pm, 18-23pm)

Área del homicidio

2 niveles (Urbano, Rural)

Lugar del homicidio

11 niveles (10 más frecuentes + «Otros»)

Provincia del homicidio

11 niveles (10 más frecuentes + «Otras»)

 

Formalmente, este modelo tiene la siguiente forma:

$$\log\left(\frac{P(Y_i=1 \mid x_i)}{1-P(Y_i=1 \mid x_i)}\right) = \beta_0 + \beta_{\text{prof}(i)} + \beta_{\text{edad}(i)} + \beta_{\text{sexo}(i)} + \beta_{\text{hora}(i)} + \beta_{\text{área}(i)} + \beta_{\text{lugar}(i)} + \beta_{\text{prov}},$$

donde cada término representa el efecto estimado de la categoría correspondiente sobre la probabilidad de tener antecedentes penales.

A partir del modelo entrenado con datos de 2023, se calcula una probabilidad predicha para cada víctima de 2024 y 2025, y luego se promedia para obtener la proporción estimada de cada año. El predictor lineal para cada individuo puede escribirse como:

$$\hat{\eta}_i = \hat{\beta}_{0,2023} + \sum_{k=1}^{10} \hat{\beta}_{k,2023} \cdot I(\text{prof}_i = k) + \sum_{l=1}^{5} \hat{\gamma}_{l,2023} \cdot I(\text{edad}_i = l) + \cdots,$$

donde la probabilidad predicha para una víctima de 2024 o 2025 es:

$$\hat{P}(Y_i = 1 \mid x_i) = \frac{\exp(\hat{\eta}_{i,2023})}{1 + \exp(\hat{\eta}_{i,2023})}$$

Y la proporción estimada para el año \(t\in\{2024, 2025\}\) resulta del promedio de esas probabilidades individuales:

$$\hat{p}_t = \frac{1}{n_t} \sum_{i=1}^{n_t} \hat{P}_{2023}(Y_i = 1 \mid x_i)$$

Finalmente, para cuantificar la incertidumbre en estas estimaciones, utilicé un bootstrap con 1000 réplicas: en cada réplica \(b\), se reentrenó el modelo con una muestra aleatoria del conjunto de 2023 para recalcular \(\hat{p}_t^{(b)}\). Los intervalos de confianza al 95 % corresponden a los percentiles 2,5 y 97,5 de esa distribución empírica, sin asumir ninguna distribución específica:

$$IC_{95\%}(\hat{p}_t) = \left[ \hat{p}_t^{(0{,}025)},\; \hat{p}_t^{(0{,}975)} \right]$$

Los resultados son los siguientes:

Año

Casos

Proporción (e)

IC 95 %

2024

6.880

22,19%

[21,37% – 23,08%]

2025

8.933

21,88%

[21,05% – 22,75%]

Enero 2026

732

21,40%

[20,54% – 22,29%]

En términos absolutos, esto equivale a aproximadamente 1.527 víctimas con antecedentes en 2024 (IC: 1.470–1.588); 1.955 en 2025 (IC: 1.881–2.033); y, 157 en enero de 2026 (IC: 150–163).

Esta estimación depende de manera crítica de que la relación entre el perfil de las víctimas y la probabilidad de tener antecedentes penales (observada en 2023) se mantenga relativamente estable en el tiempo. Ante la ausencia de datos más recientes, asumir dicha estabilidad es quizás el único punto de partida razonable, sobre todo si se considera que los perfiles poblacionales no se alteran drásticamente de un año a otro.

Dicho de otro modo, lo que esta estimación captura es lo que esperaríamos en la distribución de antecedentes penales en las víctimas de homicidio si esa estructura fuese relativamente persistente. Incluso bajo condiciones similares a las de 2023, la proporción esperada de víctimas con antecedentes se sitúa en alrededor del 22%: un porcentaje ligeramente superior al 21,07% registrado en 2023, pero que dista enormemente del 90% afirmado por el presidente Noboa, cifra que implicaría una transformación cualitativa del homicidio como fenómeno social de una magnitud verdaderamente inaudita.

1. Descargar las bases de datos del Ministerio del Interior: Link.

2. Correr el siguiente código en R, haciendo los cambios necesarios en la ubicación del directorio:

# Cargar librerías
library(readxl)
library(dplyr)
library(lubridate)
library(boot)

Rutas de los archivos

archivo_datos <- «data/mdi_homicidios_intencionales_pm_2014_2025.xlsx»
archivo_datos_2026 <- «data/mdi_homicidiosintencionalse_pm_2026_enero_enero.xlsx»

Cargar y combinar datos

datos <- read_excel(archivo_datos)
datos_2026 <- read_excel(archivo_datos_2026)

if («coordenada_x» %in% colnames(datos)) {
datos <- datos %>% mutate(coordenada_x = as.character(coordenada_x))
}
if («coordenada_x» %in% colnames(datos_2026)) {
datos_2026 <- datos_2026 %>% mutate(coordenada_x = as.character(coordenada_x))
}
datos <- bind_rows(datos, datos_2026)

Preparar variables

datos <- datos %>%
mutate(
anio = year(fecha_infraccion),
edad_num = as.numeric(gsub(«,», «.», edad)),
rango_edad = case_when(
is.na(edad_num) ~ «SIN_DATO»,
edad_num < 18 ~ «0-17»,
edad_num <= 29 ~ «18-29»,
edad_num <= 44 ~ «30-44»,
edad_num <= 64 ~ «45-64»,
edad_num >= 65 ~ «65+»,
TRUE ~ «OTRO»
),
antecedentes_si = case_when(
antecedentes == «SI» ~ 1,
antecedentes == «NO» ~ 0,
TRUE ~ NAreal
),
hora_num = as.numeric(substr(hora_infraccion, 1, 2)),
bloque_horario = case_when(
is.na(hora_num) ~ «SIN_DATO»,
hora_num >= 0 & hora_num <= 5 ~ «Madrugada»,
hora_num >= 6 & hora_num <= 11 ~ «Mañana»,
hora_num >= 12 & hora_num <= 17 ~ «Tarde»,
hora_num >= 18 & hora_num <= 23 ~ «Noche»,
TRUE ~ «SIN_DATO»
)
) %>%
select(-hora_num)

Separar por año

datos_2023 <- datos %>% filter(anio == 2023)
datos_2024 <- datos %>% filter(anio == 2024)
datos_2025 <- datos %>% filter(anio == 2025)
datos_2026 <- datos %>% filter(anio == 2026)

Top categorías basadas en 2023

top_prof <- datos_2023 %>%
count(profesion_registro_civil, sort = TRUE) %>%
slice_head(n = 10) %>% pull(profesion_registro_civil)
top_lugar <- datos_2023 %>%
count(lugar, sort = TRUE) %>%
slice_head(n = 10) %>% pull(lugar)
top_prov <- datos_2023 %>%
count(provincia, sort = TRUE) %>%
slice_head(n = 10) %>% pull(provincia)

agrupar_prof <- function(x) ifelse(x %in% top_prof, x, «OTRAS»)
agrupar_lugar <- function(x) ifelse(x %in% top_lugar, x, «OTROS»)
agrupar_prov <- function(x) ifelse(x %in% top_prov, x, «OTRAS»)

Aplicar agrupaciones

datos_2023 <- datos_2023 %>% mutate(prof_agrupada = agrupar_prof(profesion_registro_civil),
lugar_agrupado = agrupar_lugar(lugar),
prov_agrupada = agrupar_prov(provincia))
datos_2024 <- datos_2024 %>% mutate(prof_agrupada = agrupar_prof(profesion_registro_civil),
lugar_agrupado = agrupar_lugar(lugar),
prov_agrupada = agrupar_prov(provincia))
datos_2025 <- datos_2025 %>% mutate(prof_agrupada = agrupar_prof(profesion_registro_civil),
lugar_agrupado = agrupar_lugar(lugar),
prov_agrupada = agrupar_prov(provincia))
datos_2026 <- datos_2026 %>% mutate(prof_agrupada = agrupar_prof(profesion_registro_civil),
lugar_agrupado = agrupar_lugar(lugar),
prov_agrupada = agrupar_prov(provincia))

Filtrar y factorizar para modelado

niveles_edad <- c(«0-17», «18-29», «30-44», «45-64», «65+»)
niveles_bloque <- c(«Madrugada», «Mañana», «Tarde», «Noche»)
niveles_sexo <- c(«HOMBRE», «MUJER»)
niveles_area <- c(«URBANO», «RURAL»)

para_modelo <- function(df) {
df %>%
filter(rango_edad %in% niveles_edad,
bloque_horario %in% niveles_bloque,
sexo %in% niveles_sexo) %>%
mutate(
rango_edad = factor(rango_edad, levels = niveles_edad),
bloque_horario = factor(bloque_horario, levels = niveles_bloque),
sexo = factor(sexo, levels = niveles_sexo),
area_hecho = factor(area_hecho, levels = niveles_area),
prof_agrupada = factor(prof_agrupada),
lugar_agrupado = factor(lugar_agrupado),
prov_agrupada = factor(prov_agrupada)
)
}

datos_2023_m <- para_modelo(datos_2023) %>% filter(!is.na(antecedentes_si))
datos_2024_m <- para_modelo(datos_2024)
datos_2025_m <- para_modelo(datos_2025)
datos_2026_m <- para_modelo(datos_2026)

cat(«\nTamaños muestrales:\n»)
cat(«2023:», nrow(datos_2023_m), «\n2024:», nrow(datos_2024_m),
«\n2025:», nrow(datos_2025_m), «\n2026:», nrow(datos_2026_m), «\n»)

Bootstrap para estimaciones

boot_fun <- function(data, indices) {
d <- data[indices, ]
m <- tryCatch(
glm(antecedentes_si ~ prof_agrupada + rango_edad + sexo + area_hecho +
lugar_agrupado + prov_agrupada + bloque_horario,
data = d, family = binomial),
error = function(e) NULL
)
if (is.null(m)) return(c(NA, NA, NA))
c(mean(predict(m, datos_2024_m, type = «response»)),
mean(predict(m, datos_2025_m, type = «response»)),
mean(predict(m, datos_2026_m, type = «response»)))
}

set.seed(0123)
boot_res <- boot(datos_2023_m, boot_fun, R = 1000)

Resultados

prop <- colMeans(boot_res$t, na.rm = TRUE)
ic <- apply(boot_res$t, 2, quantile, probs = c(0.025, 0.975), na.rm = TRUE)
n <- c(nrow(datos_2024_m), nrow(datos_2025_m), nrow(datos_2026_m))

cat(«\n— Estimaciones de proporción de antecedentes (SI) —\n»)
for (i in 1:3) {
año <- c(2024,2025,2026)[i]
cat(«\nAño», año, «:\n»)
cat(» Proporción estimada:», round(prop[i], 4), «\n»)
cat(» IC 95%:», round(ic[1,i], 4), «-«, round(ic[2,i], 4), «\n»)
cat(» N° esperado:», round(prop[i] n[i], 1), «\n»)
cat(» IC del número:», round(ic[1,i]
n[i], 1), «-«, round(ic[2,i] * n[i], 1), «\n»)
}

rpoleoZeta

Entradas recientes

El trágico destino de La Cacica: Consuelo Araújo y su lucha por el Vallenato frente a las FARC

Consuelo Araújo logró que el vallenato entrara a los salones bogotanos y regresara a la…

38 minutos hace

Delcy Rodríguez y Gustavo Petro fortalecen relaciones tras la captura de Nicolás Maduro por EE. UU.

La presidenta encargada de Venezuela, Delcy Rodríguez, y el mandatario colombiano Gustavo Petro se reunieron…

6 horas hace

Diagnóstico de Tuberculosis y Reclusión en Leysin: La Triste Historia de Teresa de la Parra

En febrero de 1932, Teresa de la Parra escribió, en carta a un amigo, que…

19 horas hace

El Salitre: 9 Años de Retrasos en la Reconstrucción de la Unidad Deportiva en Bogotá

Hace años que la Unidad Deportiva El Salitre no produce noticias gloriosas. Atrás quedaron las…

1 día hace

Muerte de Teresa de la Parra: Su Vida y Diagnóstico en Leysin, Suiza

Diagnóstico y reclusión en Leysin, Suiza En febrero de 1932, Teresa de la Parra escribió,…

1 día hace

El legado de Teresa de la Parra: La búsqueda de sanación en el aire seco de Cercedilla, Sierra de Madrid

Los años de enfermedad y declive físico de Teresa de la Parra (1889-1936) están narrados…

1 día hace