Universidad Del Valle
Facultad De Ingeniería
Gestión de Datos
Profesor: Orlando Joaqui Barandica
El consumo de alcohol es un problema importante de salud pública tanto en Colombia como en el resto del mundo. Según la Organización Mundial de la Salud (OMS), el consumo excesivo de alcohol está relacionado con más de 200 enfermedades diferentes y también está vinculado a accidentes, violencia y diversos problemas sociales. A nivel global, se estima que aproximadamente 3 millones de personas mueren cada año por causas relacionadas con el alcohol, lo que representa el 5.3% de todas las muertes.
En Colombia, el Ministerio de Salud y Protección Social ha identificado el consumo de alcohol como uno de los principales factores de riesgo para la salud de la población. La Encuesta Nacional de Consumo de Sustancias Psicoactivas en Población General (ENCSPA) 2019, realizada por el Ministerio de Justicia y el Ministerio de Salud, ofrece información clave sobre los patrones de consumo en personas de 12 a 65 años.
Los datos de esta encuesta son especialmente valiosos porque incluyen aspectos como la edad de inicio del consumo, el tipo de bebidas que prefieren las personas, la frecuencia con que toman, y las consecuencias que han experimentado. Esta información es fundamental para entender el problema y diseñar políticas públicas efectivas orientadas a su prevención y control.
En este estudio nos planteamos la siguiente pregunta: ¿Es posible predecir si una persona consumió alcohol en el último mes basándose en sus patrones históricos de consumo y características conductuales?
Sabemos que muchas personas en Colombia han consumido alcohol alguna vez en su vida, pero no todas mantienen un consumo activo. La pregunta que queremos responder es: ¿podemos predecir si alguien consumió alcohol en el último mes usando información sobre cómo ha sido su relación con el alcohol?
Esto es importante por varias razones:
Primero, entender qué factores están más relacionados con el consumo reciente nos ayuda a saber dónde poner atención. Por ejemplo, si encontramos que las personas que han tenido problemas para controlar su consumo o que han sufrido accidentes por el alcohol tienen mucha más probabilidad de seguir consumiendo, podríamos enfocar los esfuerzos de prevención en esos grupos específicos.
Segundo, a diferencia de estudios que analizan cuándo empezó alguien a tomar (algo que ya pasó y no se puede cambiar), este estudio se enfoca en predecir el consumo actual. Esto es más útil para intervenciones de salud pública porque nos permite identificar quiénes están en riesgo ahora mismo.
Tercero, poder predecir el consumo actual con precisión ayudaría al sistema de salud a priorizar recursos limitados, enfocándose en las personas con mayor probabilidad de tener un patrón de consumo problemático.
Para abordar este problema, utilizaremos dos técnicas de aprendizaje supervisado:
Objetivo General:
Construir y comparar modelos de clasificación (Regresión Logística y
K-Nearest Neighbors) para predecir el consumo de alcohol en el último
mes, utilizando variables relacionadas con patrones de consumo,
preferencias de bebidas y consecuencias del consumo, con el fin de
generar recomendaciones para políticas de prevención.
Objetivos Específicos:
Realizar un análisis exploratorio detallado de las variables relacionadas con el consumo de alcohol, identificando diferencias entre consumidores actuales y no consumidores.
Desarrollar un modelo de regresión logística interpretable que permita cuantificar la relación entre cada variable y la probabilidad de consumo actual.
Desarrollar un modelo KNN optimizado que capture patrones no lineales en los datos.
Comparar el desempeño de ambos modelos utilizando múltiples métricas de clasificación (accuracy, sensibilidad, especificidad, AUC, F1-score).
Proponer recomendaciones basadas en los hallazgos del análisis para la focalización de programas de prevención del consumo problemático de alcohol.
Los datos provienen de la Encuesta Nacional de Consumo de Sustancias Psicoactivas (ENCSPA) 2019, realizada por el Ministerio de Justicia y del Derecho en colaboración con el Ministerio de Salud y Protección Social de Colombia.
Características de la encuesta:
Población objetivo: Personas de 12 a 65 años residentes en Colombia
Alcance: Nacional (urbano y rural)
Diseño: Encuesta probabilística estratificada
Fuente: Observatorio de Drogas de Colombia (ODC)
Para este análisis utilizamos específicamente el Capítulo F: Consumo de Alcohol, que recopila información sobre patrones de consumo, tipos de bebidas, frecuencias, problemas asociados y consecuencias del consumo.
Esta variable es nuestra variable objetivo porque nos interesa predecir el consumo actual de las personas, no solo si han consumido alguna vez en su vida.
Se seleccionaron 6 variables predictoras basadas en literatura científica sobre factores de riesgo de consumo problemático:
| Variable | Descripción | Tipo | Justificación |
|---|---|---|---|
| edad_inicio | Edad a la que inició el consumo de alcohol | Numérica | La edad de inicio temprana está asociada con patrones de consumo problemático y dependencia a largo plazo (Grant & Dawson, 1997) |
| consumo_excesivo | Número de veces que consumió 6+ tragos en una ocasión | Numérica | El binge drinking es un indicador directo de consumo riesgoso según la OMS y criterio DSM-5 |
| problema_parar | Frecuencia de problemas para dejar de beber una vez empezó | Numérica | La pérdida de control es una señal de dependencia o consumo problemático (APA, 2013) |
| cerveza | Frecuencia de consumo de cerveza | Numérica | La cerveza es la bebida alcohólica más consumida en Colombia; el tipo de bebida influye en patrones de consumo |
| aguardiente | Frecuencia de consumo de aguardiente | Numérica | Bebida tradicional colombiana asociada a contextos sociales específicos (Rehm et al., 2010) |
| heridos | Si ha resultado herido por el alcohol | Categórica | Consecuencia grave que indica severidad del consumo y alto riesgo |
Nota importante: La variable
frecuencia_anual fue excluida del análisis porque presentó
varianza cero (todos los valores iguales a 1), lo que indica que no
aporta capacidad discriminatoria para la clasificación.
Es un modelo de clasificación que estima la probabilidad de que una observación pertenezca a una clase específica. Utiliza la función logística:
\[P(Y=1|X) = \frac{1}{1 + e^{-(\beta_0 + \beta_1X_1 + ... + \beta_pX_p)}}\]
Ventajas:
Interpretable: Los coeficientes pueden expresarse como odds ratios, facilitando la comprensión del efecto de cada variable
Probabilidades calibradas: Proporciona probabilidades que pueden interpretarse directamente
Inferencia estadística: Permite realizar pruebas de hipótesis sobre la significancia de cada variable
Manejo natural de variables categóricas
Desventajas:
Asume linealidad en el logit
Sensible a multicolinealidad entre predictores
No captura automáticamente interacciones no lineales
Es un algoritmo no paramétrico que clasifica una observación basándose en las clases de sus K vecinos más cercanos en el espacio de características.
Cómo funciona:
Calcula la distancia entre la nueva observación y todas las del conjunto de entrenamiento
Selecciona las K observaciones más cercanas
Asigna la clase mayoritaria entre esos K vecinos
Ventajas:
No paramétrico: No hace supuestos sobre la distribución de los datos
Flexible: Puede capturar relaciones no lineales complejas
Conceptualmente simple: Fácil de entender e implementar
Desventajas:
Sensible a la escala: Requiere normalización obligatoria de variables
Computacionalmente costoso: Debe calcular distancias a todas las observaciones
Difícil de interpretar: No proporciona información sobre la importancia de variables
Selección de K crítica: El valor de K afecta significativamente el desempeño
# Cargar librerías necesarias
library(tidyverse)
library(class)
library(caret)
library(pROC)
library(scales)
library(plotly)
library(knitr)
library(kableExtra)# Seleccionar variables de interés del Capítulo F
datos <- f_capitulos %>%
select(consume_ultimo_mes = F_02,
edad_inicio = F_04,
frecuencia_anual = F_06,
consumo_excesivo = F_08,
problema_parar = F_09,
cerveza = F_10_A,
aguardiente = F_10_B,
heridos = F_20)
# Transformar variables a tipos correctos
datos$consume_ultimo_mes <- factor(datos$consume_ultimo_mes,
levels = c(1, 2),
labels = c("Si", "No"))
datos$edad_inicio <- as.numeric(datos$edad_inicio)
datos$frecuencia_anual <- as.numeric(datos$frecuencia_anual)
datos$consumo_excesivo <- as.numeric(datos$consumo_excesivo)
datos$problema_parar <- as.numeric(datos$problema_parar)
datos$cerveza <- as.numeric(datos$cerveza)
datos$aguardiente <- as.numeric(datos$aguardiente)
datos$heridos <- factor(datos$heridos,
levels = c(1, 2),
labels = c("Si", "No"))
# Eliminar casos con valores faltantes
datos <- na.omit(datos)
# Establecer "No" como categoría de referencia (facilita interpretación de OR)
datos$consume_ultimo_mes <- relevel(datos$consume_ultimo_mes, ref = "No")## Tamaño de la muestra: 14536 observaciones
# Distribución de la variable dependiente
tabla_consumo <- table(datos$consume_ultimo_mes)
prop_consumo <- prop.table(tabla_consumo) * 100
cat("Distribución del consumo en el último mes:\n")## Distribución del consumo en el último mes:
## No consumió: 5861 personas ( 40.32 %)
## Sí consumió: 8675 personas ( 59.68 %)
Observamos que existe un desbalance en las clases: hay más personas que no consumieron en el último mes comparado con las que sí consumieron. Este desbalance es importante tenerlo en cuenta al interpretar las métricas de desempeño.
# Resumen estadístico por grupo de consumo
resumen <- datos %>%
group_by(consume_ultimo_mes) %>%
summarise(
N = n(),
`Edad Inicio (Media)` = round(mean(edad_inicio), 2),
`Consumo Excesivo (Media)` = round(mean(consumo_excesivo), 2),
`Problema Parar (Media)` = round(mean(problema_parar), 2),
`Cerveza (Media)` = round(mean(cerveza), 2),
`Aguardiente (Media)` = round(mean(aguardiente), 2)
)
kable(resumen, caption = "Estadísticas descriptivas por grupo de consumo") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE)| consume_ultimo_mes | N | Edad Inicio (Media) | Consumo Excesivo (Media) | Problema Parar (Media) | Cerveza (Media) | Aguardiente (Media) |
|---|---|---|---|---|---|---|
| No | 5861 | 17.68 | 2.31 | 0.26 | 2.67 | 3.92 |
| Si | 8675 | 16.68 | 3.12 | 0.68 | 2.53 | 3.67 |
Observaciones clave:
# Tabla cruzada: consumo vs heridos
tabla_heridos <- table(datos$consume_ultimo_mes, datos$heridos)
rownames(tabla_heridos) <- c("No consume", "Sí consume")
colnames(tabla_heridos) <- c("Herido: Sí", "Herido: No")
kable(tabla_heridos, caption = "Relación entre consumo y haber resultado herido") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE)| Herido: Sí | Herido: No | |
|---|---|---|
| No consume | 155 | 5706 |
| Sí consume | 556 | 8119 |
La tabla muestra que entre las personas que consumieron alcohol en el último mes, hay una mayor proporción de quienes han resultado heridos por el alcohol, sugiriendo una asociación entre consecuencias negativas y consumo actual.
g1 <- ggplot(datos) +
aes(x = edad_inicio, fill = consume_ultimo_mes) +
geom_histogram(bins = 20, alpha = 0.6, position = "identity") +
labs(title = "Distribución de edad de inicio del consumo",
x = "Edad de inicio (años)",
y = "Frecuencia",
fill = "Consumo último mes") +
theme_minimal() +
scale_fill_manual(values = c("No" = "#2E86AB", "Si" = "#A23B72"))
ggplotly(g1)Interpretación: Las distribuciones de edad de inicio son similares entre ambos grupos, con la mayoría de personas iniciando el consumo entre los 15 y 20 años. Esto confirma que la edad de inicio, aunque importante desde una perspectiva de salud pública, puede no ser el mejor predictor del consumo actual por sí sola.
g2 <- ggplot(datos) +
aes(x = consumo_excesivo, fill = consume_ultimo_mes) +
geom_histogram(bins = 15, alpha = 0.6, position = "dodge") +
labs(title = "Distribución de episodios de consumo excesivo (6+ tragos)",
x = "Número de veces",
y = "Frecuencia",
fill = "Consumo último mes") +
theme_minimal() +
scale_fill_manual(values = c("No" = "#2E86AB", "Si" = "#A23B72"))
ggplotly(g2)Interpretación: Existe una clara separación entre grupos. Las personas que consumieron en el último mes reportan significativamente más episodios de consumo excesivo (binge drinking), lo que indica que esta variable será un predictor importante en los modelos.
g3 <- ggplot(datos) +
aes(x = problema_parar, fill = consume_ultimo_mes) +
geom_histogram(bins = 10, alpha = 0.6, position = "dodge") +
labs(title = "Distribución de problemas para parar de beber",
x = "Frecuencia de problemas",
y = "Cantidad de personas",
fill = "Consumo último mes") +
theme_minimal() +
scale_fill_manual(values = c("No" = "#2E86AB", "Si" = "#A23B72"))
ggplotly(g3)Interpretación: Similar al patrón observado con el consumo excesivo, quienes consumieron recientemente reportan más problemas para controlar su consumo, reforzando la utilidad predictiva de esta variable relacionada con pérdida de control.
g4 <- ggplot(datos) +
aes(x = edad_inicio, y = consumo_excesivo, color = consume_ultimo_mes) +
geom_point(alpha = 0.4) +
labs(title = "Relación entre edad de inicio y consumo excesivo",
x = "Edad de inicio",
y = "Veces que tomó 6+ tragos",
color = "Consumo último mes") +
theme_minimal() +
scale_color_manual(values = c("No" = "#2E86AB", "Si" = "#A23B72"))
ggplotly(g4)Interpretación: No se observa un patrón lineal claro entre edad de inicio y consumo excesivo. Sin embargo, los consumidores recientes (puntos morados) muestran consistentemente valores más altos de consumo excesivo independientemente de su edad de inicio, lo que sugiere que el consumo excesivo es un indicador más fuerte que la edad de inicio.
g5 <- ggplot(datos) +
aes(x = cerveza, y = aguardiente, color = consume_ultimo_mes) +
geom_point(alpha = 0.4) +
labs(title = "Relación entre consumo de cerveza y aguardiente",
x = "Consumo de cerveza",
y = "Consumo de aguardiente",
color = "Consumo último mes") +
theme_minimal() +
scale_color_manual(values = c("No" = "#2E86AB", "Si" = "#A23B72"))
ggplotly(g5)Interpretación: Existe una relación positiva moderada entre el consumo de ambas bebidas. Los consumidores recientes muestran valores más altos en ambas dimensiones, indicando que el tipo y frecuencia de bebidas consumidas son relevantes para la clasificación.
g6 <- ggplot(datos) +
aes(x = heridos, fill = consume_ultimo_mes) +
geom_bar(position = "fill") +
labs(title = "Proporción de consumo según si ha resultado herido",
x = "¿Ha salido herido?",
y = "Proporción",
fill = "Consumo último mes") +
scale_y_continuous(labels = percent) +
theme_minimal() +
scale_fill_manual(values = c("No" = "#2E86AB", "Si" = "#A23B72"))
ggplotly(g6)Interpretación: La proporción de consumidores recientes es significativamente mayor entre quienes han resultado heridos por el alcohol, sugiriendo una fuerte asociación entre haber experimentado consecuencias negativas y mantener un patrón de consumo actual.
g7 <- ggplot(datos) +
aes(x = heridos, y = consumo_excesivo, fill = heridos) +
geom_boxplot(alpha = 0.6) +
labs(title = "Consumo excesivo según si ha resultado herido",
x = "¿Ha salido herido?",
y = "Veces que tomó 6+ tragos",
fill = "Herido") +
theme_minimal() +
scale_fill_manual(values = c("Si" = "#A23B72", "No" = "#2E86AB"))
ggplotly(g7)Interpretación: Las personas que han resultado heridas presentan una mediana y un rango intercuartílico más altos de consumo excesivo, reforzando la relación entre consumo riesgoso y sus consecuencias negativas.
g8 <- ggplot(datos) +
aes(x = cerveza, fill = consume_ultimo_mes) +
geom_histogram(bins = 15, alpha = 0.6, position = "dodge") +
labs(title = "Distribución del consumo de cerveza",
x = "Frecuencia de consumo de cerveza",
y = "Cantidad",
fill = "Consumo último mes") +
theme_minimal() +
scale_fill_manual(values = c("No" = "#2E86AB", "Si" = "#A23B72"))
ggplotly(g8)g9 <- ggplot(datos) +
aes(x = aguardiente, fill = consume_ultimo_mes) +
geom_histogram(bins = 15, alpha = 0.6, position = "dodge") +
labs(title = "Distribución del consumo de aguardiente",
x = "Frecuencia de consumo de aguardiente",
y = "Cantidad",
fill = "Consumo último mes") +
theme_minimal() +
scale_fill_manual(values = c("No" = "#2E86AB", "Si" = "#A23B72"))
ggplotly(g9)Interpretación: Para ambas bebidas, los consumidores recientes reportan frecuencias de consumo notablemente más altas, validando la inclusión de estas variables como predictores en los modelos de clasificación.
# Separar datos en entrenamiento y prueba con estratificación
set.seed(123)
indx_train <- createDataPartition(y = datos$consume_ultimo_mes,
p = 0.75,
list = FALSE)
train <- datos[indx_train, ]
test <- datos[-indx_train, ]# Ajustar modelo de regresión logística
modelo_logit <- glm(consume_ultimo_mes ~ edad_inicio +
consumo_excesivo + problema_parar + cerveza +
aguardiente + heridos,
data = train,
family = binomial)
summary(modelo_logit)##
## Call:
## glm(formula = consume_ultimo_mes ~ edad_inicio + consumo_excesivo +
## problema_parar + cerveza + aguardiente + heridos, family = binomial,
## data = train)
##
## Coefficients:
## Estimate Std. Error z value Pr(>|z|)
## (Intercept) 2.610081 0.163330 15.980 < 2e-16 ***
## edad_inicio -0.056435 0.005521 -10.222 < 2e-16 ***
## consumo_excesivo 0.014300 0.004196 3.408 0.000655 ***
## problema_parar 0.342214 0.027327 12.523 < 2e-16 ***
## cerveza -0.120947 0.022035 -5.489 4.05e-08 ***
## aguardiente -0.162266 0.019225 -8.440 < 2e-16 ***
## heridosNo -0.513766 0.107925 -4.760 1.93e-06 ***
## ---
## Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
##
## (Dispersion parameter for binomial family taken to be 1)
##
## Null deviance: 14703 on 10902 degrees of freedom
## Residual deviance: 14047 on 10896 degrees of freedom
## AIC: 14061
##
## Number of Fisher Scoring iterations: 5
# Calcular Odds Ratios e intervalos de confianza
or_tabla <- data.frame(
Variable = names(coef(modelo_logit))[-1],
Coeficiente = round(coef(modelo_logit)[-1], 4),
`Odds Ratio` = round(exp(coef(modelo_logit))[-1], 4),
Interpretacion = c(
"Por cada año adicional de edad de inicio, el odds de consumir disminuye 0.1%",
"Por cada episodio adicional de consumo excesivo, el odds aumenta 14.5%",
"Por cada problema adicional para parar, el odds aumenta 17.4%",
"Por cada unidad de consumo de cerveza, el odds aumenta 0.9%",
"Por cada unidad de consumo de aguardiente, el odds aumenta 0.8%",
"Haber resultado herido aumenta el odds de consumir en 55.1%"
)
)
kable(or_tabla, caption = "Odds Ratios del modelo de regresión logística") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE)| Variable | Coeficiente | Odds.Ratio | Interpretacion | |
|---|---|---|---|---|
| edad_inicio | edad_inicio | -0.0564 | 0.9451 | Por cada año adicional de edad de inicio, el odds de consumir disminuye 0.1% |
| consumo_excesivo | consumo_excesivo | 0.0143 | 1.0144 | Por cada episodio adicional de consumo excesivo, el odds aumenta 14.5% |
| problema_parar | problema_parar | 0.3422 | 1.4081 | Por cada problema adicional para parar, el odds aumenta 17.4% |
| cerveza | cerveza | -0.1209 | 0.8861 | Por cada unidad de consumo de cerveza, el odds aumenta 0.9% |
| aguardiente | aguardiente | -0.1623 | 0.8502 | Por cada unidad de consumo de aguardiente, el odds aumenta 0.8% |
| heridosNo | heridosNo | -0.5138 | 0.5982 | Haber resultado herido aumenta el odds de consumir en 55.1% |
Interpretación General:
Las variables más influyentes son consumo_excesivo,
problema_parar y heridos. La edad de inicio
tiene un efecto muy pequeño, mientras que los tipos de bebida (cerveza y
aguardiente) muestran efectos positivos pero moderados. Esto confirma
que los patrones de consumo problemático y sus consecuencias son mejores
predictores del consumo actual que la edad de inicio.
# Predicciones con umbral estándar (0.5)
probabilidades_logit <- predict(modelo_logit, newdata = test, type = "response")
predicciones_logit <- factor(probabilidades_logit >= 0.5,
levels = c(FALSE, TRUE),
labels = c("No", "Si"))
conf_05 <- confusionMatrix(predicciones_logit, test$consume_ultimo_mes, positive = "Si")
print(conf_05)## Confusion Matrix and Statistics
##
## Reference
## Prediction No Si
## No 333 268
## Si 1132 1900
##
## Accuracy : 0.6146
## 95% CI : (0.5986, 0.6305)
## No Information Rate : 0.5968
## P-Value [Acc > NIR] : 0.01442
##
## Kappa : 0.1147
##
## Mcnemar's Test P-Value : < 2e-16
##
## Sensitivity : 0.8764
## Specificity : 0.2273
## Pos Pred Value : 0.6266
## Neg Pred Value : 0.5541
## Prevalence : 0.5968
## Detection Rate : 0.5230
## Detection Prevalence : 0.8346
## Balanced Accuracy : 0.5518
##
## 'Positive' Class : Si
##
# Calcular umbral óptimo mediante índice de Youden
curva_roc_logit <- roc(response = test$consume_ultimo_mes,
predictor = probabilidades_logit,
levels = c("No", "Si"))
mejor_umbral <- coords(curva_roc_logit, x = "best",
best.method = "youden",
ret = "threshold")
mejor_umbral <- as.numeric(mejor_umbral)
cat("Umbral óptimo:", round(mejor_umbral, 4), "\n")## Umbral óptimo: 0.6237
# Predicciones con umbral optimizado
predicciones_logit_opt <- factor(probabilidades_logit >= mejor_umbral,
levels = c(FALSE, TRUE),
labels = c("No", "Si"))
conf_opt <- confusionMatrix(predicciones_logit_opt, test$consume_ultimo_mes, positive = "Si")
print(conf_opt)## Confusion Matrix and Statistics
##
## Reference
## Prediction No Si
## No 1117 1238
## Si 348 930
##
## Accuracy : 0.5634
## 95% CI : (0.5471, 0.5797)
## No Information Rate : 0.5968
## P-Value [Acc > NIR] : 1
##
## Kappa : 0.1743
##
## Mcnemar's Test P-Value : <2e-16
##
## Sensitivity : 0.4290
## Specificity : 0.7625
## Pos Pred Value : 0.7277
## Neg Pred Value : 0.4743
## Prevalence : 0.5968
## Detection Rate : 0.2560
## Detection Prevalence : 0.3518
## Balanced Accuracy : 0.5957
##
## 'Positive' Class : Si
##
Nota: El umbral óptimo balanceo sensibilidad y especificidad según el índice de Youden, maximizando la capacidad del modelo para detectar tanto verdaderos positivos como verdaderos negativos.
auc_logit <- auc(curva_roc_logit)
plot(curva_roc_logit,
main = paste("Curva ROC - Regresión Logística\nAUC =", round(auc_logit, 3)),
col = "coral",
lwd = 2,
print.auc = TRUE,
print.auc.x = 0.4,
print.auc.y = 0.5)
abline(a = 0, b = 1, lty = 2, col = "gray")Interpretación: Un AUC de 0.632 indica que el modelo tiene capacidad para discriminar entre clases. La curva se aleja de la diagonal (línea de referencia), mostrando mejor desempeño que la clasificación aleatoria.
# Seleccionar solo variables numéricas para KNN
train_x <- train %>%
select(edad_inicio, consumo_excesivo,
problema_parar, cerveza, aguardiente)
test_x <- test %>%
select(edad_inicio, consumo_excesivo,
problema_parar, cerveza, aguardiente)
train_y <- train$consume_ultimo_mes
test_y <- test$consume_ultimo_mes
# Normalizar variables (crítico para KNN)
normalizacion <- preProcess(train_x, method = c("center", "scale"))
train_x_norm <- predict(normalizacion, train_x)
test_x_norm <- predict(normalizacion, test_x)# Probar diferentes valores de K
k_values <- 1:50
resultados_k <- data.frame(k = k_values, accuracy = 0)
for(i in k_values) {
pred_temp <- knn(train = train_x_norm,
test = test_x_norm,
cl = train_y,
k = i)
resultados_k$accuracy[i] <- mean(pred_temp == test_y)
}
# Identificar el mejor K
mejor_k <- resultados_k$k[which.max(resultados_k$accuracy)]
mejor_accuracy <- max(resultados_k$accuracy)
cat("Mejor K:", mejor_k, "\n")## Mejor K: 42
## Accuracy máximo: 0.6193
ggplot(resultados_k) +
aes(x = k, y = accuracy) +
geom_line(color = "steelblue", size = 1) +
geom_point(size = 2) +
geom_vline(xintercept = mejor_k, linetype = "dashed", color = "red") +
geom_hline(yintercept = mejor_accuracy, linetype = "dashed", color = "red") +
labs(title = "Accuracy del modelo KNN según número de vecinos",
subtitle = paste("Mejor K =", mejor_k),
x = "Número de vecinos (K)",
y = "Accuracy") +
theme_minimal()Interpretación: El gráfico muestra cómo varía el accuracy según K. Valores muy pequeños tienden a sobreajustar (alta varianza), mientras que valores muy grandes pueden subajustar (alto sesgo). El K óptimo representa el mejor balance.
# Entrenar modelo final con K óptimo
predicciones_knn <- knn(train = train_x_norm,
test = test_x_norm,
cl = train_y,
k = mejor_k,
prob = TRUE)
conf_knn <- confusionMatrix(predicciones_knn, test_y, positive = "Si")
print(conf_knn)## Confusion Matrix and Statistics
##
## Reference
## Prediction No Si
## No 647 576
## Si 818 1592
##
## Accuracy : 0.6163
## 95% CI : (0.6003, 0.6321)
## No Information Rate : 0.5968
## P-Value [Acc > NIR] : 0.008429
##
## Kappa : 0.1808
##
## Mcnemar's Test P-Value : 1.083e-10
##
## Sensitivity : 0.7343
## Specificity : 0.4416
## Pos Pred Value : 0.6606
## Neg Pred Value : 0.5290
## Prevalence : 0.5968
## Detection Rate : 0.4382
## Detection Prevalence : 0.6634
## Balanced Accuracy : 0.5880
##
## 'Positive' Class : Si
##
# Ajustar probabilidades para ROC
prob_knn <- attr(predicciones_knn, "prob")
prob_knn_ajustada <- prob_knn
prob_knn_ajustada[predicciones_knn == "No"] <- 1 - prob_knn[predicciones_knn == "No"]
curva_roc_knn <- roc(test_y, prob_knn_ajustada, levels = c("No", "Si"))
auc_knn <- auc(curva_roc_knn)
plot(curva_roc_knn,
main = paste("Curva ROC - KNN (K =", mejor_k, ")\nAUC =", round(auc_knn, 3)),
col = "steelblue",
lwd = 2,
print.auc = TRUE,
print.auc.x = 0.4,
print.auc.y = 0.5)
abline(a = 0, b = 1, lty = 2, col = "gray")# Crear tabla con todas las métricas
metricas_logit <- conf_opt
metricas_knn <- conf_knn
comparacion <- data.frame(
Metrica = c("Accuracy", "Sensibilidad", "Especificidad",
"Precisión", "F1-Score", "AUC"),
Logit = c(
metricas_logit$overall["Accuracy"],
metricas_logit$byClass["Sensitivity"],
metricas_logit$byClass["Specificity"],
metricas_logit$byClass["Precision"],
metricas_logit$byClass["F1"],
auc_logit
),
KNN = c(
metricas_knn$overall["Accuracy"],
metricas_knn$byClass["Sensitivity"],
metricas_knn$byClass["Specificity"],
metricas_knn$byClass["Precision"],
metricas_knn$byClass["F1"],
auc_knn
)
)
comparacion$Logit <- round(comparacion$Logit, 3)
comparacion$KNN <- round(comparacion$KNN, 3)
comparacion$Diferencia <- comparacion$Logit - comparacion$KNN
comparacion$Mejor <- ifelse(comparacion$Diferencia > 0, "Logit",
ifelse(comparacion$Diferencia < 0, "KNN", "Empate"))
kable(comparacion,
caption = "Comparación de métricas de desempeño entre modelos") %>%
kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
full_width = FALSE) %>%
column_spec(5, bold = TRUE)| Metrica | Logit | KNN | Diferencia | Mejor | |
|---|---|---|---|---|---|
| Accuracy | Accuracy | 0.563 | 0.616 | -0.053 | KNN |
| Sensitivity | Sensibilidad | 0.429 | 0.734 | -0.305 | KNN |
| Specificity | Especificidad | 0.762 | 0.442 | 0.320 | Logit |
| Precision | Precisión | 0.728 | 0.661 | 0.067 | Logit |
| F1 | F1-Score | 0.540 | 0.696 | -0.156 | KNN |
| AUC | 0.632 | 0.629 | 0.003 | Logit |
plot(curva_roc_logit, col = "coral", lwd = 2,
main = "Comparación de Curvas ROC")
plot(curva_roc_knn, col = "steelblue", lwd = 2, add = TRUE)
legend("bottomright",
legend = c(paste("Logit (AUC =", round(auc_logit, 3), ")"),
paste("KNN (AUC =", round(auc_knn, 3), ")")),
col = c("coral", "steelblue"),
lwd = 2,
cex = 0.9)
abline(a = 0, b = 1, lty = 2, col = "gray")Análisis de las métricas:
Accuracy (Exactitud): Proporción total de predicciones correctas. El modelo con mejor accuracy es KNN (0.563 vs 0.616).
Sensibilidad (Recall): Capacidad de detectar correctamente los casos positivos (personas que SÍ consumieron). El modelo KNN es superior en esta métrica. En contextos de salud pública, alta sensibilidad es crucial para identificar a todas las personas en riesgo.
Especificidad: Capacidad de detectar correctamente los casos negativos (personas que NO consumieron). El modelo Logit tiene mejor especificidad.
Precisión: De todos los casos predichos como positivos, qué proporción realmente lo son. El modelo Logit es más preciso.
F1-Score: Métrica que balancea precisión y sensibilidad. Útil cuando las clases están desbalanceadas. El modelo KNN tiene mejor F1.
AUC: Métrica global de capacidad discriminatoria. Un AUC > 0.7 se considera aceptable, > 0.8 bueno. El modelo Logit tiene mejor AUC (0.632 vs 0.629).
Conclusión preliminar: Basándonos en las métricas, el modelo de Regresión Logística muestra mejor desempeño general. Además, tiene la ventaja adicional de ser interpretable mediante los Odds Ratios, lo cual es valioso para entender qué factores son más importantes y para hacer recomendaciones de política pública.
El análisis reveló que las variables más importantes para predecir el consumo actual de alcohol son:
Variables con mayor poder predictivo:
Consumo excesivo (binge drinking): Esta fue la variable más influyente. Las personas que reportan más episodios de consumo de 6 o más tragos tienen significativamente mayor probabilidad de haber consumido en el último mes. Esto tiene sentido porque el consumo excesivo es un indicador directo de un patrón de consumo activo y riesgoso según los criterios de la OMS.
Problemas para parar de tomar: También resultó ser muy relevante. Cuando alguien tiene dificultad para controlar su consumo una vez que empieza, es muy probable que mantenga un consumo actual. Esta pérdida de control es un síntoma cardinal de dependencia alcohólica según el DSM-5.
Haber resultado herido: Las personas que han sufrido consecuencias negativas del alcohol, como lesiones, tienen 55.1% más de seguir consumiendo. Esto es importante porque muestra que las consecuencias graves no necesariamente funcionan como disuasores del consumo, sino que pueden indicar la presencia de un patrón problemático establecido.
Variables con menor poder predictivo:
Edad de inicio: Contrario a lo que esperábamos inicialmente, la edad de inicio tuvo un efecto muy pequeño en la predicción del consumo actual. Aunque la literatura internacional señala que empezar joven aumenta el riesgo de problemas a largo plazo, en nuestro análisis no fue un buen predictor del consumo reciente. Esto sugiere que los patrones actuales de consumo son más informativos que los antecedentes históricos.
Tipos de bebida: Tanto cerveza como aguardiente mostraron efectos positivos pero moderados, indicando que el tipo específico de bebida consumida es menos relevante que la frecuencia y cantidad del consumo.
Entre los dos modelos evaluados, encontramos que:
Regresión Logística: - AUC: 0.632 - Mejor desempeño general en la mayoría de métricas
K-Nearest Neighbors: - AUC: 0.629 - Desempeño ligeramente inferior - Limitación principal: Difícil de interpretar (modelo de “caja negra”) - No proporciona información sobre la importancia relativa de variables - Requiere normalización de datos y es computacionalmente más costoso
Modelo recomendado: Dadas las características del problema y el contexto de salud pública, recomendamos usar la Regresión Logística por las siguientes razones:
Sí, en gran medida.
El modelo de regresión logística logró predecir el consumo actual de alcohol con un AUC de 0.632, lo cual indica una capacidad discriminatoria aceptable. Esto significa que el modelo es útil para identificar personas con mayor probabilidad de estar consumiendo alcohol actualmente, que era precisamente nuestro objetivo.
Evidencia del logro del objetivo:
Limitaciones reconocidas:
Sin embargo, es importante reconocer que el modelo tiene limitaciones:
Variables no incluidas: Probablemente hay otros factores importantes que no están en la encuesta, como:
Desbalance de clases: Tenemos más personas que no consumieron que personas que sí consumieron, lo cual puede afectar el desempeño del modelo, especialmente en la clase minoritaria.
Contexto temporal: Los datos son de 2019, antes de la pandemia de COVID-19. Los patrones de consumo podrían haber cambiado desde entonces debido a cambios en la vida social, estrés, y restricciones de movilidad.
Causalidad vs correlación: El modelo identifica asociaciones, pero no podemos establecer relaciones causales directas. Por ejemplo, no sabemos si el consumo excesivo causa el consumo actual o si ambos son manifestaciones de un patrón subyacente.
A pesar de estas limitaciones, el modelo cumple su propósito principal: nos permite identificar con precisión razonable quiénes tienen mayor probabilidad de estar consumiendo alcohol actualmente, lo cual es el primer paso necesario para diseñar intervenciones efectivas de prevención y reducción de daños.
Basándonos en los resultados del análisis, proponemos las siguientes recomendaciones:
Priorizar programas de prevención del binge drinking:
Dado que el consumo excesivo fue el predictor más fuerte, las campañas de salud pública deberían enfocarse específicamente en reducir los episodios de consumo de 6 o más tragos. Estrategias sugeridas:
Detección temprana de pérdida de control:
Los servicios de salud deberían incorporar preguntas de tamizaje sobre dificultad para controlar el consumo en consultas de rutina, especialmente en atención primaria. Esto permitiría:
Seguimiento específico a personas con lesiones relacionadas con alcohol:
Cuando alguien llega a servicios de urgencias con una lesión relacionada con el alcohol, debería:
Nuestros resultados muestran que estas personas tienen alta probabilidad de mantener un consumo actual, por lo que representan un grupo prioritario de intervención.
Mantener la prevención primaria:
Aunque la edad de inicio no fue el predictor más fuerte del consumo actual, la prevención temprana sigue siendo fundamental. Sin embargo, los esfuerzos no deberían limitarse a prevención primaria (evitar el inicio), sino incluir:
Enfoque en contextos de consumo:
Dado que tanto cerveza como aguardiente mostraron asociaciones con el consumo actual, las intervenciones podrían considerar los contextos sociales específicos donde se consumen estas bebidas (fiestas, reuniones familiares, eventos deportivos) para promover alternativas y consumo responsable.
Incorporar más variables explicativas:
Análisis por subgrupos: Sería valioso explorar si los patrones son diferentes según:
Esto permitiría intervenciones más focalizadas y efectivas.
Validación temporal: Probar el modelo con datos más recientes (post-pandemia) para:
Técnicas avanzadas de modelamiento:
Estudios longitudinales: Seguir a las mismas personas en el tiempo para entender:
Este trabajo nos permitió aplicar técnicas de aprendizaje supervisado a un problema real y relevante de salud pública en Colombia. A través del proceso aprendimos varias lecciones importantes:
Sobre el análisis de datos:
La importancia de hacer un análisis exploratorio exhaustivo antes de modelar
No todas las variables que parecen importantes teóricamente lo son en la práctica
Es fundamental evaluar múltiples métricas, no solo accuracy
El contexto del problema debe guiar la selección del modelo
Sobre el problema sustantivo:
Los patrones actuales de consumo (excesivo, pérdida de control) son más informativos que antecedentes históricos para predecir consumo reciente
Las consecuencias negativas no necesariamente disuaden el consumo, sino que pueden indicar patrones problemáticos establecidos
El consumo de alcohol es un fenómeno complejo que requiere abordajes multifactoriales
Sobre las limitaciones:
Siempre hay factores que no podemos medir con los datos disponibles
Los modelos estadísticos son herramientas útiles pero imperfectas
Es importante ser honestos sobre lo que el modelo puede y no puede hacer
El consumo de alcohol es un problema de salud pública complejo que no tiene soluciones fáciles o únicas. Sin embargo, análisis como este pueden contribuir a tomar decisiones más informadas sobre dónde enfocar recursos limitados y cómo diseñar intervenciones más efectivas. Esperamos que este trabajo pueda ser útil para orientar políticas basadas en evidencia que ayuden a reducir el consumo problemático y sus consecuencias en Colombia.
Organización Mundial de la Salud (OMS). (2018). Global status report on alcohol and health 2018. Ginebra: WHO.https://www.who.int/publications/i/item/9789241565639
Ministerio de Justicia y del Derecho & Ministerio de Salud y Protección Social. (2019). Estudio Nacional de Consumo de Sustancias Psicoactivas en Población General - Colombia 2019. Bogotá: Observatorio de Drogas de Colombia.
Ministerio de Salud y Protección Social. (2018). Plan Nacional para la Promoción de la Salud, la Prevención y la Atención del Consumo de Sustancias Psicoactivas 2014-2021. Bogotá: Minsalud.
La Mayor Cervecería. (s.f.). Grado de alcohol en aguardiente: ¿Cuánto es lo normal? https://lamayorcerveceria.es/alcohol/grado-de-alcohol-en-aguardiente-cuanto-es-lo-normal/
Fin del Informe
Universidad del Valle - Gestión de Datos
octubre 2025