Analisis de Accidentes Cerebrovasculares

Problema a abordar

El trabajo consiste en realizar un analisis de clasificación y predicción de Accidentes Cerebrovasculares. El objetivo es identificar a partir de ciertas variables la probabilidad de sufrir un accidente cerebrovascular.

Fuente de información: “stroke.csv” extraido de Kaggle. Muestra de 5110 observaciones.

Los datos incluyen información sobre:

-Características demográficas (edad, género)

-Condiciones de salud (hipertensión, enfermedad cardíaca)

-Habitos de vida (estado de fumador)

-Medidas clínicas (nivel promedio de glucosa)

Variables

id: Identicador de cada observación

gender: Variable Categórica con valores “Male” (masculino) y “Female” (femenino).

age: Una variable numérica que representa la edad del individuo en años.

hypertension: Hipertensión expresado de manera binaria (0 o 1), como presencia o ausencia.
heart_disease: Una variable binaria (0 o 1) que indica si el individuo tiene enfermedad cardíaca (1) o no (0)

ever_married: Una variable categórica que indica si el individuo ha estado casado alguna vez, con valores “Yes” (sí) o “No”.

work_type: variable categórica que describe el tipo de trabajo del individuo, con valores como “Private” (privado), Govt_job (trabajo gubernamental) y “Self-employed” (autónomo).

Residence_type: variable categórica que indica el tipo de residencia del individuo, con valores “Urban” (urbano) o “Rural”

avg_glucose_level: representa el nivel promedio de glucosa en sangre del individuo.

bmi: Rerepresenta el indice de Masa Corporal (IMC) del individuo.

smoking_status: variable categórica que indica el estado de fumador del individuo, con valores como “formerly smoked” (ex fumador), “never smoked” (nunca fumó) y “smokes” (fuma).

stroke Una variable binaria (0 o 1) que indica si el individuo ha sufrido un accidente cerebrovascular (1) o no (0).

Salidas:

-Ranking de importancia de las variables predictoras

-Odds ratios e intervalos de confianza para cada variable

-Curva ROC y valor AUC con intervalos de confianza

-Informe de los hallazgos y su interpretación clínica

library(missRanger)
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.4     ✔ readr     2.1.5
## ✔ forcats   1.0.0     ✔ stringr   1.5.0
## ✔ ggplot2   3.4.4     ✔ tibble    3.2.1
## ✔ lubridate 1.9.3     ✔ tidyr     1.3.0
## ✔ purrr     1.0.1     
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(caret)
## Loading required package: lattice
## 
## Attaching package: 'caret'
## 
## The following object is masked from 'package:purrr':
## 
##     lift
library(MASS)
## 
## Attaching package: 'MASS'
## 
## The following object is masked from 'package:dplyr':
## 
##     select
library(pROC)
## Type 'citation("pROC")' for a citation.
## 
## Attaching package: 'pROC'
## 
## The following objects are masked from 'package:stats':
## 
##     cov, smooth, var
library(dplyr)
library(fastDummies)
## Thank you for using fastDummies!
## To acknowledge our work, please cite the package:
## Kaplan, J. & Schlegel, B. (2023). fastDummies: Fast Creation of Dummy (Binary) Columns and Rows from Categorical Variables. Version 1.7.1. URL: https://github.com/jacobkap/fastDummies, https://jacobkap.github.io/fastDummies/.
library(caret)
library(glmnet)
## Loading required package: Matrix
## 
## Attaching package: 'Matrix'
## 
## The following objects are masked from 'package:tidyr':
## 
##     expand, pack, unpack
## 
## Loaded glmnet 4.1-8
library(DataExplorer)

1.Carga de Datos

datos <- read.csv("C:/Users/lluiselli/Downloads/stroke.csv")
datos$bmi[datos$bmi == "N/A"] <- NA
datos$smoking_status[datos$smoking_status == "Unknown"] <- NA

2.Analisis Exploratorio

head(datos)
##      id gender age hypertension heart_disease ever_married     work_type
## 1  9046   Male  67            0             1          Yes       Private
## 2 51676 Female  61            0             0          Yes Self-employed
## 3 31112   Male  80            0             1          Yes       Private
## 4 60182 Female  49            0             0          Yes       Private
## 5  1665 Female  79            1             0          Yes Self-employed
## 6 56669   Male  81            0             0          Yes       Private
##   Residence_type avg_glucose_level  bmi  smoking_status stroke
## 1          Urban            228.69 36.6 formerly smoked      1
## 2          Rural            202.21 <NA>    never smoked      1
## 3          Rural            105.92 32.5    never smoked      1
## 4          Urban            171.23 34.4          smokes      1
## 5          Rural            174.12   24    never smoked      1
## 6          Urban            186.21   29 formerly smoked      1
plot_intro(datos)

plot_missing(datos)

##Imputación de Valores faltantes

#Ante la presencia de valores nulos, se procede a imputar valores faltantes por medio de MissRanger

datos$gender <- as.factor(datos$gender)
datos$hypertension <- as.factor(datos$hypertension)
datos$ever_married <-  as.factor(datos$ever_married)
datos$work_type <-  as.factor(datos$work_type)
datos$Residence_type <-  as.factor(datos$Residence_type)
datos$bmi <- as.numeric(datos$bmi)
datos$smoking_status <-  as.factor(datos$smoking_status)

# Imputar valores faltantes con missRanger
datos_imputados <- missRanger(datos)
## 
## Missing value imputation by random forests
## 
##   Variables to impute:       bmi, smoking_status
##   Variables used to impute:  id, gender, age, hypertension, heart_disease, ever_married, work_type, Residence_type, avg_glucose_level, bmi, smoking_status, stroke
## 
## iter 1
## 
  |                                                                            
  |                                                                      |   0%
  |                                                                            
  |===================================                                   |  50%
  |                                                                            
  |======================================================================| 100%
## iter 2
## 
  |                                                                            
  |                                                                      |   0%
  |                                                                            
  |===================================                                   |  50%
  |                                                                            
  |======================================================================| 100%
## iter 3
## 
  |                                                                            
  |                                                                      |   0%
  |                                                                            
  |===================================                                   |  50%
  |                                                                            
  |======================================================================| 100%
## iter 4
## 
  |                                                                            
  |                                                                      |   0%
  |                                                                            
  |===================================                                   |  50%
  |                                                                            
  |======================================================================| 100%
sum(is.na(datos_imputados))
## [1] 0
#Comparación
table(datos$smoking_status)
## 
## formerly smoked    never smoked          smokes 
##             885            1892             789
table(datos_imputados$smoking_status)
## 
## formerly smoked    never smoked          smokes 
##             973            3336             801
# Definir la función age_cohort
age_intervalos <- function(age) {
  ifelse(age >= 0 & age <= 20, "0-20",
         ifelse(age > 20 & age <= 40, "20-40",
                ifelse(age > 40 & age <= 50, "40-50",
                       ifelse(age > 50 & age <= 60, "50-60",
                              ifelse(age > 60, "60+", NA)))))
  }

edad <- datos_imputados %>%
  mutate(age_group = sapply(age, age_intervalos))%>%
  arrange(age_group)


plot_missing(datos_imputados)

# EDA de datos limpios

#Veamos la distribución de cada variable
plot_bar(datos_imputados)

plot_histogram(datos_imputados)

3.Analisis de Regresión Logísitica

# Seleccionar el mejor modelo en funcion a Akaike

full_model <- glm(stroke ~ ., data=datos_imputados, family=binomial)
step_model <- step(full_model, direction="both")
## Start:  AIC=1609.12
## stroke ~ id + gender + age + hypertension + heart_disease + ever_married + 
##     work_type + Residence_type + avg_glucose_level + bmi + smoking_status
## 
##                     Df Deviance    AIC
## - gender             2   1575.2 1605.2
## - bmi                1   1575.2 1607.2
## - id                 1   1575.3 1607.3
## - Residence_type     1   1575.4 1607.4
## - work_type          4   1581.7 1607.7
## - ever_married       1   1576.0 1608.0
## - heart_disease      1   1577.0 1609.0
## <none>                   1575.1 1609.1
## - hypertension       1   1580.7 1612.7
## - smoking_status     2   1583.6 1613.6
## - avg_glucose_level  1   1585.1 1617.1
## - age                1   1774.7 1806.7
## 
## Step:  AIC=1605.19
## stroke ~ id + age + hypertension + heart_disease + ever_married + 
##     work_type + Residence_type + avg_glucose_level + bmi + smoking_status
## 
##                     Df Deviance    AIC
## - bmi                1   1575.3 1603.3
## - id                 1   1575.4 1603.4
## - Residence_type     1   1575.5 1603.5
## - work_type          4   1581.7 1603.7
## - ever_married       1   1576.0 1604.0
## - heart_disease      1   1577.0 1605.0
## <none>                   1575.2 1605.2
## - hypertension       1   1580.8 1608.8
## + gender             2   1575.1 1609.1
## - smoking_status     2   1583.7 1609.7
## - avg_glucose_level  1   1585.1 1613.1
## - age                1   1775.1 1803.1
## 
## Step:  AIC=1603.26
## stroke ~ id + age + hypertension + heart_disease + ever_married + 
##     work_type + Residence_type + avg_glucose_level + smoking_status
## 
##                     Df Deviance    AIC
## - id                 1   1575.5 1601.5
## - Residence_type     1   1575.5 1601.5
## - work_type          4   1581.7 1601.7
## - ever_married       1   1576.1 1602.1
## - heart_disease      1   1577.0 1603.0
## <none>                   1575.3 1603.3
## + bmi                1   1575.2 1605.2
## - hypertension       1   1581.0 1607.0
## + gender             2   1575.2 1607.2
## - smoking_status     2   1583.8 1607.8
## - avg_glucose_level  1   1586.1 1612.1
## - age                1   1779.2 1805.2
## 
## Step:  AIC=1601.48
## stroke ~ age + hypertension + heart_disease + ever_married + 
##     work_type + Residence_type + avg_glucose_level + smoking_status
## 
##                     Df Deviance    AIC
## - Residence_type     1   1575.8 1599.8
## - work_type          4   1582.1 1600.1
## - ever_married       1   1576.3 1600.3
## - heart_disease      1   1577.3 1601.3
## <none>                   1575.5 1601.5
## + id                 1   1575.3 1603.3
## + bmi                1   1575.4 1603.4
## - hypertension       1   1581.3 1605.3
## + gender             2   1575.4 1605.4
## - smoking_status     2   1584.1 1606.1
## - avg_glucose_level  1   1586.2 1610.2
## - age                1   1779.4 1803.4
## 
## Step:  AIC=1599.76
## stroke ~ age + hypertension + heart_disease + ever_married + 
##     work_type + avg_glucose_level + smoking_status
## 
##                     Df Deviance    AIC
## - work_type          4   1582.4 1598.4
## - ever_married       1   1576.6 1598.6
## - heart_disease      1   1577.5 1599.5
## <none>                   1575.8 1599.8
## + Residence_type     1   1575.5 1601.5
## + id                 1   1575.5 1601.5
## + bmi                1   1575.7 1601.7
## - hypertension       1   1581.5 1603.5
## + gender             2   1575.7 1603.7
## - smoking_status     2   1584.6 1604.6
## - avg_glucose_level  1   1586.6 1608.6
## - age                1   1780.4 1802.4
## 
## Step:  AIC=1598.36
## stroke ~ age + hypertension + heart_disease + ever_married + 
##     avg_glucose_level + smoking_status
## 
##                     Df Deviance    AIC
## - ever_married       1   1583.4 1597.4
## - heart_disease      1   1584.3 1598.3
## <none>                   1582.4 1598.4
## + work_type          4   1575.8 1599.8
## + id                 1   1582.0 1600.0
## + Residence_type     1   1582.1 1600.1
## + bmi                1   1582.3 1600.3
## - hypertension       1   1587.9 1601.9
## + gender             2   1582.3 1602.3
## - smoking_status     2   1590.8 1602.8
## - avg_glucose_level  1   1593.9 1607.9
## - age                1   1795.0 1809.0
## 
## Step:  AIC=1597.41
## stroke ~ age + hypertension + heart_disease + avg_glucose_level + 
##     smoking_status
## 
##                     Df Deviance    AIC
## <none>                   1583.4 1597.4
## - heart_disease      1   1585.6 1597.6
## + ever_married       1   1582.4 1598.4
## + work_type          4   1576.6 1598.6
## + Residence_type     1   1583.1 1599.1
## + id                 1   1583.1 1599.1
## + bmi                1   1583.4 1599.4
## - hypertension       1   1589.0 1601.0
## + gender             2   1583.4 1601.4
## - smoking_status     2   1591.5 1601.5
## - avg_glucose_level  1   1594.6 1606.6
## - age                1   1822.8 1834.8

Definición del AIC:

AIC = 2k - 2ln(L) Donde k es el número de parámetros en el modelo y L es el valor máximo de la función de verosimilitud para el modelo.

El AIC busca un equilibrio entre la bondad de ajuste del modelo y su complejidad. Valores más bajos de AIC indican modelos preferibles.

En orden de importancia

age (AIC aumentaría a 1838.4 si se elimina) avg_glucose_level (AIC: 1608.8) hypertension (AIC: 1603.0) smoking_status (AIC: 1601.5) heart_disease (AIC: 1599.7)

-La edad es, con mucho, el predictor más importante del accidente cerebrovascular en este modelo.

-El nivel promedio de glucosa es el segundo predictor más importante.

-La hipertensión y el estado de fumador también son factores significativos.

-La enfermedad cardíaca se mantuvo en el modelo, aunque su contribución es relativamente pequeña.

#Modelamos con los predictores del AIC

modelo_aic <- glm(stroke ~ age + hypertension + heart_disease + avg_glucose_level + smoking_status, data = datos_imputados, family = binomial)

modelo_ampliado <- glm(stroke ~ age + hypertension + heart_disease + avg_glucose_level + smoking_status + ever_married, bmi, data = datos_imputados, family = binomial)
## Warning in eval(family$initialize): non-integer #successes in a binomial glm!
# Comparar AIC con el total de los predictores
AIC(modelo_aic, modelo_ampliado)
##                 df       AIC
## modelo_aic       7  1597.412
## modelo_ampliado  8 48308.354
# Comparamos rendimiento

roc_aic <- roc(datos_imputados$stroke, predict(modelo_aic, type = "response"))
## Setting levels: control = 0, case = 1
## Setting direction: controls < cases
roc_ampliado <- roc(datos_imputados$stroke, predict(modelo_ampliado, type = "response"))
## Setting levels: control = 0, case = 1
## Setting direction: controls < cases
auc(roc_aic)
## Area under the curve: 0.847
auc(roc_ampliado)
## Area under the curve: 0.8478

Complejidad del modelo:

El AIC mucho más bajo del modelo_aic (1599.468 vs 48434.618) indica que este modelo proporciona un mejor equilibrio entre la bondad de ajuste y la complejidad del modelo.

Basándonos únicamente en el AIC, el modelo_aic es claramente preferible. Ofrece una mejor explicación de los datos con mucha menos complejidad.

# Predictores seleccionados según AIC
vars_aic <- c("stroke", "age", "hypertension", "heart_disease", "avg_glucose_level", "smoking_status")

# Semilla de reproducibilidad
set.seed(123)

# Crear una partición de datos con 70% para entrenamiento y 30% para prueba
particion <- createDataPartition(datos_imputados$stroke, p = 0.7, list = FALSE)
datos_train <- datos_imputados[particion, ]
datos_test <- datos_imputados[-particion, ]

# Subconjuntos de datos de entrenamiento y prueba con las variables seleccionadas
datos_train_AIC <- subset(datos_train, select = vars_aic)
datos_test_AIC <- subset(datos_test, select = vars_aic)

# Eliminamos NA 
datos_train_AIC <- na.omit(datos_train_AIC)
datos_test_AIC <- na.omit(datos_test_AIC)

# regresión logística con variables AIC
modelo_aic <- glm(stroke ~ age + hypertension + heart_disease + avg_glucose_level + smoking_status, data = datos_train_AIC, family = binomial)

# modelo AIC
summary(modelo_aic)
## 
## Call:
## glm(formula = stroke ~ age + hypertension + heart_disease + avg_glucose_level + 
##     smoking_status, family = binomial, data = datos_train_AIC)
## 
## Coefficients:
##                             Estimate Std. Error z value Pr(>|z|)    
## (Intercept)                -7.372660   0.473624 -15.566  < 2e-16 ***
## age                         0.069087   0.006382  10.826  < 2e-16 ***
## hypertension1               0.432991   0.195132   2.219  0.02649 *  
## heart_disease               0.250724   0.233860   1.072  0.28367    
## avg_glucose_level           0.004291   0.001385   3.098  0.00195 ** 
## smoking_statusnever smoked -0.360420   0.186677  -1.931  0.05352 .  
## smoking_statussmokes       -0.046477   0.247735  -0.188  0.85118    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 1361.6  on 3576  degrees of freedom
## Residual deviance: 1088.8  on 3570  degrees of freedom
## AIC: 1102.8
## 
## Number of Fisher Scoring iterations: 7
# odds ratios
odds_ratios <- exp(coef(modelo_aic))
print(odds_ratios)
##                (Intercept)                        age 
##               0.0006281953               1.0715289237 
##              hypertension1              heart_disease 
##               1.5418629528               1.2849551127 
##          avg_glucose_level smoking_statusnever smoked 
##               1.0042997625               0.6973834111 
##       smoking_statussmokes 
##               0.9545863780
# Modelo ampliado con todas las variables
modelo_ampliado <- glm(stroke ~ ., data = datos_train, family = binomial)

# Comparar AIC
print(AIC(modelo_aic, modelo_ampliado))
##                 df      AIC
## modelo_aic       7 1102.845
## modelo_ampliado 17 1111.036
# Comparar rendimiento
predicciones_aic <- predict(modelo_aic, newdata = datos_train_AIC, type = "response")
predicciones_ampliado <- predict(modelo_ampliado, newdata = datos_train, type = "response")

roc_aic <- roc(datos_train_AIC$stroke, predicciones_aic)
## Setting levels: control = 0, case = 1
## Setting direction: controls < cases
roc_ampliado <- roc(datos_train$stroke, predicciones_ampliado)
## Setting levels: control = 0, case = 1
## Setting direction: controls < cases
print(auc(roc_aic))
## Area under the curve: 0.8464
print(auc(roc_ampliado))
## Area under the curve: 0.8499

La edad (age) es muy significativa (p < 2e-16) y tiene un odds ratio de 1.0727, lo que significa que por cada año de aumento en la edad, las probabilidades de tener un accidente cerebrovascular aumentan en un 7.27%.

La hipertensión (hypertension) no es estadísticamente significativa (p = 0.1160), pero tiene un odds ratio de 1.3613, sugiriendo un aumento del 36.13% en las probabilidades de accidente cerebrovascular.

La enfermedad cardíaca (heart_disease) no es estadísticamente significativa (p = 0.1981), con un odds ratio de 1.3348.

El nivel promedio de glucosa (avg_glucose_level) es significativo (p = 0.0117) con un odds ratio de 1.0035, indicando un pequeño aumento en las probabilidades por cada unidad de aumento en el nivel de glucosa.

El no haber fumado es significativo (p = 0.0150) y tiene un efecto digamos “protector”, con un odds ratio de 0.6416, lo que sugiere una reducción del 35.84% en las probabilidades de accidente cerebrovascular comparado con la categoría de referencia.

Ser fumador (smoking_statussmokes) no es significativo (p = 0.7718).

Por otro lado, podemos afirmar que el modelo tiene un buen poder predictivo, con un AUC de 0.8453, lo que se considera generalmente como un rendimiento bueno a excelente.

La diferencia en AUC entre el modelo AIC y el modelo ampliado es muy pequeña (0.0025), lo que sugiere que las variables adicionales en el modelo ampliado no aportan mucha mejora en la capacidad predictiva.

La edad y el nivel de glucosa son los predictores más significativos y robustos en este modelo. El efecto “protector” de nunca haber fumado es interesante y significativo.

#intervalos de confianza
ci_aic <- ci(roc_aic)
ci_ampliado <- ci(roc_ampliado)

# Imprimir los resultados
print("Intervalo de confianza para el AUC del Modelo AIC:")
## [1] "Intervalo de confianza para el AUC del Modelo AIC:"
print(ci_aic)
## 95% CI: 0.8218-0.8711 (DeLong)
print("Intervalo de confianza para el AUC del Modelo Ampliado:")
## [1] "Intervalo de confianza para el AUC del Modelo Ampliado:"
print(ci_ampliado)
## 95% CI: 0.8251-0.8747 (DeLong)
# Graficar las curvas ROC con intervalos de confianza
plot(roc_aic, main="Curva ROC - Comparación de Modelos con IC", 
     col="blue", lwd=2)
lines(roc_ampliado, col="red", lwd=2)

Comparación de modelos:

El ROC muestra cómo se comporta el modelo a través de diferentes umbrales de clasificación, permitiendo evaluar su rendimiento general.

El área bajo la curva ROC (AUC-ROC) proporciona una medida única del rendimiento del modelo, independiente del umbral de clasificación elegido.

Permite comparar fácilmente diferentes modelos de clasificación en un mismo gráfico. Ayuda a determinar qué modelo tiene un mejor rendimiento general.

Las curvas están casi superpuestas, lo que sugiere que el rendimiento de ambos modelos es muy similar, lo cual es consistente con el hecho de que los valores de AUC (Area Under the Curve) son 0.8453 para el Modelo AIC y 0.8478 para el Modelo Ampliado.

Basándonos en estos intervalos de confianza, podemos afirmar con un 95% de confianza que el verdadero AUC para ambos modelos se encuentra entre aproximadamente 0.82 y 0.87. La superposición de los intervalos sugiere que no hay una diferencia estadísticamente significativa entre los dos modelos en términos de capacidad discriminativa.

Dado que no hay una diferencia significativa entre los modelos, sería razonable preferir el Modelo AIC por su simplicidad (principio de parsimonia). El Modelo AIC proporciona esencialmente el mismo rendimiento predictivo con menos variables, lo que lo hace más fácil de interpretar y posiblemente más robusto en la generalización a nuevos datos.

# prediccio en el conjunto de prueba
predicciones <- predict(modelo_aic, newdata = datos_test_AIC, type = "response")
summary(predicciones)
##      Min.   1st Qu.    Median      Mean   3rd Qu.      Max. 
## 0.0005953 0.0041272 0.0167256 0.0457966 0.0547986 0.4842657
#Con umbral de 0.2
predicciones_binarias <- ifelse(predicciones > 0.2, 1, 0)  
valores_reales <- datos_test_AIC$stroke

# Crear matriz de confusión
cm <- confusionMatrix(factor(predicciones_binarias), factor(valores_reales))
print(cm)
## Confusion Matrix and Statistics
## 
##           Reference
## Prediction    0    1
##          0 1399   59
##          1   54   21
##                                          
##                Accuracy : 0.9263         
##                  95% CI : (0.912, 0.9389)
##     No Information Rate : 0.9478         
##     P-Value [Acc > NIR] : 0.9999         
##                                          
##                   Kappa : 0.2322         
##                                          
##  Mcnemar's Test P-Value : 0.7067         
##                                          
##             Sensitivity : 0.9628         
##             Specificity : 0.2625         
##          Pos Pred Value : 0.9595         
##          Neg Pred Value : 0.2800         
##              Prevalence : 0.9478         
##          Detection Rate : 0.9126         
##    Detection Prevalence : 0.9511         
##       Balanced Accuracy : 0.6127         
##                                          
##        'Positive' Class : 0              
## 
# métricas específicas
sensibilidad <- cm$byClass['Sensitivity']
especificidad <- cm$byClass['Specificity']
precision <- cm$byClass['Precision']
exactitud <- cm$overall['Accuracy']
f1_score <- cm$byClass['F1']

# Calcular la curva ROC y AUC para los datos de prueba
roc_test <- roc(datos_test_AIC$stroke, predicciones)
## Setting levels: control = 0, case = 1
## Setting direction: controls < cases
auc_test <- auc(roc_test)

# ROC de prueba
plot(roc_test, main = "Curva ROC - Datos de Prueba", col = "blue")
abline(a = 0, b = 1, lty = 2, col = "gray")

Sensibilidad (0.9621): Alta, indicando que la mayoría de los casos positivos reales fueron correctamente identificados.

Especificidad (0.2625): Baja, lo que sugiere que el modelo tiene dificultad para identificar correctamente los casos negativos.

Precisión (0.9595): Alta, indicando que la mayoría de las predicciones positivas son correctas.

Exactitud (0.9256): Alta, mostrando un buen rendimiento general del modelo.

F1-Score (0.9608): Alta, lo que indica un buen balance entre precisión y sensibilidad.

Luego de comparar con el umbral en 0.5 y 0.1, es 0.2 el umbral que proporciona un mejor balance entre sensibilidad (0.9621) y especificidad (0.2625).

4.Conclusión

Factores de riesgo principales:

La edad es el predictor más fuerte y significativo para el accidente cerebrovascular. Por cada año de aumento en la edad, el riesgo aumenta un 7.27%.

El nivel promedio de glucosa en sangre es el segundo factor más importante, aunque su efecto es más pequeño pero estadísticamente significativo.

Nunca haber fumado parece tener un efecto protector significativo, reduciendo el riesgo de accidente cerebrovascular en un 35.84% comparado con la categoría de referencia.

Modelo

El modelo tiene un buen poder predictivo, con un AUC de 0.8453 (IC 95%: 0.8214-0.8708). La diferencia en rendimiento entre el modelo AIC y el modelo ampliado es mínima, lo que sugiere que un modelo más simple es suficiente para predecir el riesgo de accidente cerebrovascular.

Implicaciones clínicas:

El control de la glucosa en sangre y la promoción de hábitos de no fumar podrían ser estrategias efectivas para reducir el riesgo de accidente cerebrovascular.

En resumen, este análisis parece proporcionarnos una herramienta útil para identificar individuos en riesgo de accidente cerebrovascular, con la edad y el nivel de glucosa como los principales factores a considerar. El modelo ofrece un buen equilibrio entre simplicidad y poder predictivo, lo que lo hace potencialmente valioso para su uso en entornos clínicos.

LS0tDQp0aXRsZTogIkFuYWxpc2lzIGRlIEFjY2lkZW50ZXMgQ2VyZWJyb3Zhc2N1bGFyZXMiDQphdXRob3I6ICJMdWNhcyBMdWlzZWxsaSINCmRhdGU6ICIyMDI0LTAzLTIxIg0Kb3V0cHV0Og0KICBybWRmb3JtYXRzOjpyZWFkdGhlZG93bjoNCiAgICAjIGxpZ2h0Ym94OiBUUlVFDQogICAgIyBoaWdobGlnaHQ6IHRhbmdvDQogICAgIyB0b2M6IDMNCiAgICAjIG51bWJlci1zZWN0aW9uczogVFJVRQ0KICAgICMgY29kZS1mb2xkaW5nOiBzaG93ICNvY3VsdGEgZWwgY29kaWdvDQogICAgY29kZV9kb3dubG9hZDogVFJVRSAjIHBhcmEgZGVzY2FyZ2FyIGVsIHJtZA0KLS0tDQoNCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFLCB3YXJuaW5nPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFKQ0KYGBgDQoqKlByb2JsZW1hIGEgYWJvcmRhcioqDQoNCkVsIHRyYWJham8gY29uc2lzdGUgZW4gcmVhbGl6YXIgdW4gYW5hbGlzaXMgZGUgY2xhc2lmaWNhY2nDs24geSBwcmVkaWNjacOzbiBkZSBBY2NpZGVudGVzIENlcmVicm92YXNjdWxhcmVzLiBFbCBvYmpldGl2byBlcyBpZGVudGlmaWNhciBhIHBhcnRpciBkZSBjaWVydGFzIHZhcmlhYmxlcyBsYSBwcm9iYWJpbGlkYWQgZGUgc3VmcmlyIHVuIGFjY2lkZW50ZSBjZXJlYnJvdmFzY3VsYXIuDQoNCkZ1ZW50ZSBkZSBpbmZvcm1hY2nDs246ICJzdHJva2UuY3N2IiBleHRyYWlkbyBkZSBLYWdnbGUuIE11ZXN0cmEgZGUgNTExMCBvYnNlcnZhY2lvbmVzLg0KDQpMb3MgZGF0b3MgaW5jbHV5ZW4gaW5mb3JtYWNpw7NuIHNvYnJlOg0KDQotQ2FyYWN0ZXLDrXN0aWNhcyBkZW1vZ3LDoWZpY2FzIChlZGFkLCBnw6luZXJvKQ0KDQotQ29uZGljaW9uZXMgZGUgc2FsdWQgKGhpcGVydGVuc2nDs24sIGVuZmVybWVkYWQgY2FyZMOtYWNhKQ0KDQotSGFiaXRvcyBkZSB2aWRhIChlc3RhZG8gZGUgZnVtYWRvcikNCg0KLU1lZGlkYXMgY2zDrW5pY2FzIChuaXZlbCBwcm9tZWRpbyBkZSBnbHVjb3NhKQ0KDQoNCioqVmFyaWFibGVzKioNCg0KKippZDoqKiBJZGVudGljYWRvciBkZSBjYWRhIG9ic2VydmFjacOzbg0KDQoqKmdlbmRlcjoqKiBWYXJpYWJsZSBDYXRlZ8OzcmljYSBjb24gdmFsb3JlcyAiTWFsZSIgKG1hc2N1bGlubykgeSAiRmVtYWxlIiAoZmVtZW5pbm8pLg0KDQoqKmFnZToqKiBVbmEgdmFyaWFibGUgbnVtw6lyaWNhIHF1ZSByZXByZXNlbnRhIGxhIGVkYWQgZGVsIGluZGl2aWR1byBlbiBhw7Fvcy4gICAgDQoNCioqaHlwZXJ0ZW5zaW9uOioqIEhpcGVydGVuc2nDs24gZXhwcmVzYWRvIGRlIG1hbmVyYSBiaW5hcmlhICgwIG8gMSksIGNvbW8gcHJlc2VuY2lhIG8gYXVzZW5jaWEuICAgDQoqKmhlYXJ0X2Rpc2Vhc2U6KiogVW5hIHZhcmlhYmxlIGJpbmFyaWEgKDAgbyAxKSBxdWUgaW5kaWNhIHNpIGVsIGluZGl2aWR1byB0aWVuZSBlbmZlcm1lZGFkIGNhcmTDrWFjYSAoMSkgbyBubyAoMCkNCg0KKipldmVyX21hcnJpZWQ6KiogVW5hIHZhcmlhYmxlIGNhdGVnw7NyaWNhIHF1ZSBpbmRpY2Egc2kgZWwgaW5kaXZpZHVvIGhhIGVzdGFkbyBjYXNhZG8gYWxndW5hIHZleiwgY29uIHZhbG9yZXMgIlllcyIgKHPDrSkgbyAiTm8iLiAgIA0KDQoqKndvcmtfdHlwZToqKiB2YXJpYWJsZSBjYXRlZ8OzcmljYSBxdWUgZGVzY3JpYmUgZWwgdGlwbyBkZSB0cmFiYWpvIGRlbCBpbmRpdmlkdW8sIGNvbiB2YWxvcmVzIGNvbW8gIlByaXZhdGUiIChwcml2YWRvKSwgR292dF9qb2IgKHRyYWJham8gZ3ViZXJuYW1lbnRhbCkgeSAiU2VsZi1lbXBsb3llZCIgKGF1dMOzbm9tbykuICAgDQoNCioqUmVzaWRlbmNlX3R5cGU6KiogdmFyaWFibGUgY2F0ZWfDs3JpY2EgcXVlIGluZGljYSBlbCB0aXBvIGRlIHJlc2lkZW5jaWEgZGVsIGluZGl2aWR1bywgY29uIHZhbG9yZXMgIlVyYmFuIiAodXJiYW5vKSBvICJSdXJhbCINCg0KKiphdmdfZ2x1Y29zZV9sZXZlbDoqKiByZXByZXNlbnRhIGVsIG5pdmVsIHByb21lZGlvIGRlIGdsdWNvc2EgZW4gc2FuZ3JlIGRlbCBpbmRpdmlkdW8uIA0KDQoqKmJtaToqKiBSZXJlcHJlc2VudGEgZWwgaW5kaWNlIGRlIE1hc2EgQ29ycG9yYWwgKElNQykgZGVsIGluZGl2aWR1by4NCg0KKipzbW9raW5nX3N0YXR1czoqKiB2YXJpYWJsZSBjYXRlZ8OzcmljYSBxdWUgaW5kaWNhIGVsIGVzdGFkbyBkZSBmdW1hZG9yIGRlbCBpbmRpdmlkdW8sIGNvbiB2YWxvcmVzIGNvbW8gImZvcm1lcmx5IHNtb2tlZCIgKGV4IGZ1bWFkb3IpLCAibmV2ZXIgc21va2VkIiAobnVuY2EgZnVtw7MpIHkgInNtb2tlcyIgKGZ1bWEpLiAgDQoNCioqc3Ryb2tlKiogVW5hIHZhcmlhYmxlIGJpbmFyaWEgKDAgbyAxKSBxdWUgaW5kaWNhIHNpIGVsIGluZGl2aWR1byBoYSBzdWZyaWRvIHVuIGFjY2lkZW50ZSBjZXJlYnJvdmFzY3VsYXIgKDEpIG8gbm8gKDApLiAgDQoNCg0KKipTYWxpZGFzKio6DQoNCi1SYW5raW5nIGRlIGltcG9ydGFuY2lhIGRlIGxhcyB2YXJpYWJsZXMgcHJlZGljdG9yYXMNCg0KLU9kZHMgcmF0aW9zIGUgaW50ZXJ2YWxvcyBkZSBjb25maWFuemEgcGFyYSBjYWRhIHZhcmlhYmxlDQoNCi1DdXJ2YSBST0MgeSB2YWxvciBBVUMgY29uIGludGVydmFsb3MgZGUgY29uZmlhbnphDQoNCi1JbmZvcm1lIGRlIGxvcyBoYWxsYXpnb3MgeSBzdSBpbnRlcnByZXRhY2nDs24gY2zDrW5pY2ENCg0KYGBge3IsIHdhcm5pbmc9RkFMU0V9DQpsaWJyYXJ5KG1pc3NSYW5nZXIpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoY2FyZXQpDQpsaWJyYXJ5KE1BU1MpDQpsaWJyYXJ5KHBST0MpDQpsaWJyYXJ5KGRwbHlyKQ0KbGlicmFyeShmYXN0RHVtbWllcykNCmxpYnJhcnkoY2FyZXQpDQpsaWJyYXJ5KGdsbW5ldCkNCmxpYnJhcnkoRGF0YUV4cGxvcmVyKQ0KDQpgYGANCg0KIyMgMS5DYXJnYSBkZSBEYXRvcw0KDQpgYGB7cn0NCg0KZGF0b3MgPC0gcmVhZC5jc3YoIkM6L1VzZXJzL2xsdWlzZWxsaS9Eb3dubG9hZHMvc3Ryb2tlLmNzdiIpDQpkYXRvcyRibWlbZGF0b3MkYm1pID09ICJOL0EiXSA8LSBOQQ0KZGF0b3Mkc21va2luZ19zdGF0dXNbZGF0b3Mkc21va2luZ19zdGF0dXMgPT0gIlVua25vd24iXSA8LSBOQQ0KYGBgDQoNCiMjIDIuQW5hbGlzaXMgRXhwbG9yYXRvcmlvDQpgYGB7cn0NCmhlYWQoZGF0b3MpDQoNCnBsb3RfaW50cm8oZGF0b3MpDQpwbG90X21pc3NpbmcoZGF0b3MpDQoNCmBgYA0KDQojI0ltcHV0YWNpw7NuIGRlIFZhbG9yZXMgZmFsdGFudGVzIA0KDQpgYGB7cn0NCiNBbnRlIGxhIHByZXNlbmNpYSBkZSB2YWxvcmVzIG51bG9zLCBzZSBwcm9jZWRlIGEgaW1wdXRhciB2YWxvcmVzIGZhbHRhbnRlcyBwb3IgbWVkaW8gZGUgTWlzc1Jhbmdlcg0KDQpkYXRvcyRnZW5kZXIgPC0gYXMuZmFjdG9yKGRhdG9zJGdlbmRlcikNCmRhdG9zJGh5cGVydGVuc2lvbiA8LSBhcy5mYWN0b3IoZGF0b3MkaHlwZXJ0ZW5zaW9uKQ0KZGF0b3MkZXZlcl9tYXJyaWVkIDwtICBhcy5mYWN0b3IoZGF0b3MkZXZlcl9tYXJyaWVkKQ0KZGF0b3Mkd29ya190eXBlIDwtICBhcy5mYWN0b3IoZGF0b3Mkd29ya190eXBlKQ0KZGF0b3MkUmVzaWRlbmNlX3R5cGUgPC0gIGFzLmZhY3RvcihkYXRvcyRSZXNpZGVuY2VfdHlwZSkNCmRhdG9zJGJtaSA8LSBhcy5udW1lcmljKGRhdG9zJGJtaSkNCmRhdG9zJHNtb2tpbmdfc3RhdHVzIDwtICBhcy5mYWN0b3IoZGF0b3Mkc21va2luZ19zdGF0dXMpDQoNCiMgSW1wdXRhciB2YWxvcmVzIGZhbHRhbnRlcyBjb24gbWlzc1Jhbmdlcg0KZGF0b3NfaW1wdXRhZG9zIDwtIG1pc3NSYW5nZXIoZGF0b3MpDQpzdW0oaXMubmEoZGF0b3NfaW1wdXRhZG9zKSkNCg0KI0NvbXBhcmFjacOzbg0KdGFibGUoZGF0b3Mkc21va2luZ19zdGF0dXMpDQp0YWJsZShkYXRvc19pbXB1dGFkb3Mkc21va2luZ19zdGF0dXMpDQpgYGANCg0KYGBge3J9DQojIERlZmluaXIgbGEgZnVuY2nDs24gYWdlX2NvaG9ydA0KYWdlX2ludGVydmFsb3MgPC0gZnVuY3Rpb24oYWdlKSB7DQogIGlmZWxzZShhZ2UgPj0gMCAmIGFnZSA8PSAyMCwgIjAtMjAiLA0KICAgICAgICAgaWZlbHNlKGFnZSA+IDIwICYgYWdlIDw9IDQwLCAiMjAtNDAiLA0KICAgICAgICAgICAgICAgIGlmZWxzZShhZ2UgPiA0MCAmIGFnZSA8PSA1MCwgIjQwLTUwIiwNCiAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKGFnZSA+IDUwICYgYWdlIDw9IDYwLCAiNTAtNjAiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKGFnZSA+IDYwLCAiNjArIiwgTkEpKSkpKQ0KICB9DQoNCmVkYWQgPC0gZGF0b3NfaW1wdXRhZG9zICU+JQ0KICBtdXRhdGUoYWdlX2dyb3VwID0gc2FwcGx5KGFnZSwgYWdlX2ludGVydmFsb3MpKSU+JQ0KICBhcnJhbmdlKGFnZV9ncm91cCkNCg0KDQpwbG90X21pc3NpbmcoZGF0b3NfaW1wdXRhZG9zKQ0KDQoNCmBgYA0KIyBFREEgZGUgZGF0b3MgbGltcGlvcw0KYGBge3J9DQojVmVhbW9zIGxhIGRpc3RyaWJ1Y2nDs24gZGUgY2FkYSB2YXJpYWJsZQ0KcGxvdF9iYXIoZGF0b3NfaW1wdXRhZG9zKQ0KcGxvdF9oaXN0b2dyYW0oZGF0b3NfaW1wdXRhZG9zKQ0KYGBgDQoNCiMjIDMuQW5hbGlzaXMgZGUgUmVncmVzacOzbiBMb2fDrXNpdGljYQ0KYGBge3J9DQojIFNlbGVjY2lvbmFyIGVsIG1lam9yIG1vZGVsbyBlbiBmdW5jaW9uIGEgQWthaWtlDQoNCmZ1bGxfbW9kZWwgPC0gZ2xtKHN0cm9rZSB+IC4sIGRhdGE9ZGF0b3NfaW1wdXRhZG9zLCBmYW1pbHk9Ymlub21pYWwpDQpzdGVwX21vZGVsIDwtIHN0ZXAoZnVsbF9tb2RlbCwgZGlyZWN0aW9uPSJib3RoIikNCmBgYA0KDQpEZWZpbmljacOzbiBkZWwgQUlDOg0KDQpBSUMgPSAyayAtIDJsbihMKSBEb25kZSBrIGVzIGVsIG7Dum1lcm8gZGUgcGFyw6FtZXRyb3MgZW4gZWwgbW9kZWxvIHkgTCBlcyBlbCB2YWxvciBtw6F4aW1vIGRlIGxhIGZ1bmNpw7NuIGRlIHZlcm9zaW1pbGl0dWQgcGFyYSBlbCBtb2RlbG8uIA0KDQpFbCBBSUMgYnVzY2EgdW4gZXF1aWxpYnJpbyBlbnRyZSBsYSBib25kYWQgZGUgYWp1c3RlIGRlbCBtb2RlbG8geSBzdSBjb21wbGVqaWRhZC4gVmFsb3JlcyBtw6FzIGJham9zIGRlIEFJQyBpbmRpY2FuIG1vZGVsb3MgcHJlZmVyaWJsZXMuDQoNCkVuIG9yZGVuIGRlIGltcG9ydGFuY2lhDQoNCmFnZSAoQUlDIGF1bWVudGFyw61hIGEgMTgzOC40IHNpIHNlIGVsaW1pbmEpDQphdmdfZ2x1Y29zZV9sZXZlbCAoQUlDOiAxNjA4LjgpDQpoeXBlcnRlbnNpb24gKEFJQzogMTYwMy4wKQ0Kc21va2luZ19zdGF0dXMgKEFJQzogMTYwMS41KQ0KaGVhcnRfZGlzZWFzZSAoQUlDOiAxNTk5LjcpDQoNCg0KLUxhIGVkYWQgZXMsIGNvbiBtdWNobywgZWwgcHJlZGljdG9yIG3DoXMgaW1wb3J0YW50ZSBkZWwgYWNjaWRlbnRlIGNlcmVicm92YXNjdWxhciBlbiBlc3RlIG1vZGVsby4NCg0KLUVsIG5pdmVsIHByb21lZGlvIGRlIGdsdWNvc2EgZXMgZWwgc2VndW5kbyBwcmVkaWN0b3IgbcOhcyBpbXBvcnRhbnRlLg0KDQotTGEgaGlwZXJ0ZW5zacOzbiB5IGVsIGVzdGFkbyBkZSBmdW1hZG9yIHRhbWJpw6luIHNvbiBmYWN0b3JlcyBzaWduaWZpY2F0aXZvcy4NCg0KLUxhIGVuZmVybWVkYWQgY2FyZMOtYWNhIHNlIG1hbnR1dm8gZW4gZWwgbW9kZWxvLCBhdW5xdWUgc3UgY29udHJpYnVjacOzbiBlcyByZWxhdGl2YW1lbnRlIHBlcXVlw7FhLg0KDQpgYGB7cn0NCiNNb2RlbGFtb3MgY29uIGxvcyBwcmVkaWN0b3JlcyBkZWwgQUlDDQoNCm1vZGVsb19haWMgPC0gZ2xtKHN0cm9rZSB+IGFnZSArIGh5cGVydGVuc2lvbiArIGhlYXJ0X2Rpc2Vhc2UgKyBhdmdfZ2x1Y29zZV9sZXZlbCArIHNtb2tpbmdfc3RhdHVzLCBkYXRhID0gZGF0b3NfaW1wdXRhZG9zLCBmYW1pbHkgPSBiaW5vbWlhbCkNCg0KbW9kZWxvX2FtcGxpYWRvIDwtIGdsbShzdHJva2UgfiBhZ2UgKyBoeXBlcnRlbnNpb24gKyBoZWFydF9kaXNlYXNlICsgYXZnX2dsdWNvc2VfbGV2ZWwgKyBzbW9raW5nX3N0YXR1cyArIGV2ZXJfbWFycmllZCwgYm1pLCBkYXRhID0gZGF0b3NfaW1wdXRhZG9zLCBmYW1pbHkgPSBiaW5vbWlhbCkNCg0KIyBDb21wYXJhciBBSUMgY29uIGVsIHRvdGFsIGRlIGxvcyBwcmVkaWN0b3Jlcw0KQUlDKG1vZGVsb19haWMsIG1vZGVsb19hbXBsaWFkbykNCg0KIyBDb21wYXJhbW9zIHJlbmRpbWllbnRvDQoNCnJvY19haWMgPC0gcm9jKGRhdG9zX2ltcHV0YWRvcyRzdHJva2UsIHByZWRpY3QobW9kZWxvX2FpYywgdHlwZSA9ICJyZXNwb25zZSIpKQ0Kcm9jX2FtcGxpYWRvIDwtIHJvYyhkYXRvc19pbXB1dGFkb3Mkc3Ryb2tlLCBwcmVkaWN0KG1vZGVsb19hbXBsaWFkbywgdHlwZSA9ICJyZXNwb25zZSIpKQ0KDQphdWMocm9jX2FpYykNCmF1Yyhyb2NfYW1wbGlhZG8pDQpgYGANCioqQ29tcGxlamlkYWQgZGVsIG1vZGVsbyoqOg0KDQpFbCBBSUMgbXVjaG8gbcOhcyBiYWpvIGRlbCBtb2RlbG9fYWljICgxNTk5LjQ2OCB2cyA0ODQzNC42MTgpIGluZGljYSBxdWUgZXN0ZSBtb2RlbG8gcHJvcG9yY2lvbmEgdW4gbWVqb3IgZXF1aWxpYnJpbyBlbnRyZSBsYSBib25kYWQgZGUgYWp1c3RlIHkgbGEgY29tcGxlamlkYWQgZGVsIG1vZGVsby4NCg0KQmFzw6FuZG9ub3Mgw7puaWNhbWVudGUgZW4gZWwgQUlDLCBlbCBtb2RlbG9fYWljIGVzIGNsYXJhbWVudGUgcHJlZmVyaWJsZS4gT2ZyZWNlIHVuYSBtZWpvciBleHBsaWNhY2nDs24gZGUgbG9zIGRhdG9zIGNvbiBtdWNoYSBtZW5vcyBjb21wbGVqaWRhZC4NCg0KDQoNCg0KYGBge3J9DQoNCiMgUHJlZGljdG9yZXMgc2VsZWNjaW9uYWRvcyBzZWfDum4gQUlDDQp2YXJzX2FpYyA8LSBjKCJzdHJva2UiLCAiYWdlIiwgImh5cGVydGVuc2lvbiIsICJoZWFydF9kaXNlYXNlIiwgImF2Z19nbHVjb3NlX2xldmVsIiwgInNtb2tpbmdfc3RhdHVzIikNCg0KIyBTZW1pbGxhIGRlIHJlcHJvZHVjaWJpbGlkYWQNCnNldC5zZWVkKDEyMykNCg0KIyBDcmVhciB1bmEgcGFydGljacOzbiBkZSBkYXRvcyBjb24gNzAlIHBhcmEgZW50cmVuYW1pZW50byB5IDMwJSBwYXJhIHBydWViYQ0KcGFydGljaW9uIDwtIGNyZWF0ZURhdGFQYXJ0aXRpb24oZGF0b3NfaW1wdXRhZG9zJHN0cm9rZSwgcCA9IDAuNywgbGlzdCA9IEZBTFNFKQ0KZGF0b3NfdHJhaW4gPC0gZGF0b3NfaW1wdXRhZG9zW3BhcnRpY2lvbiwgXQ0KZGF0b3NfdGVzdCA8LSBkYXRvc19pbXB1dGFkb3NbLXBhcnRpY2lvbiwgXQ0KDQojIFN1YmNvbmp1bnRvcyBkZSBkYXRvcyBkZSBlbnRyZW5hbWllbnRvIHkgcHJ1ZWJhIGNvbiBsYXMgdmFyaWFibGVzIHNlbGVjY2lvbmFkYXMNCmRhdG9zX3RyYWluX0FJQyA8LSBzdWJzZXQoZGF0b3NfdHJhaW4sIHNlbGVjdCA9IHZhcnNfYWljKQ0KZGF0b3NfdGVzdF9BSUMgPC0gc3Vic2V0KGRhdG9zX3Rlc3QsIHNlbGVjdCA9IHZhcnNfYWljKQ0KDQojIEVsaW1pbmFtb3MgTkEgDQpkYXRvc190cmFpbl9BSUMgPC0gbmEub21pdChkYXRvc190cmFpbl9BSUMpDQpkYXRvc190ZXN0X0FJQyA8LSBuYS5vbWl0KGRhdG9zX3Rlc3RfQUlDKQ0KDQojIHJlZ3Jlc2nDs24gbG9nw61zdGljYSBjb24gdmFyaWFibGVzIEFJQw0KbW9kZWxvX2FpYyA8LSBnbG0oc3Ryb2tlIH4gYWdlICsgaHlwZXJ0ZW5zaW9uICsgaGVhcnRfZGlzZWFzZSArIGF2Z19nbHVjb3NlX2xldmVsICsgc21va2luZ19zdGF0dXMsIGRhdGEgPSBkYXRvc190cmFpbl9BSUMsIGZhbWlseSA9IGJpbm9taWFsKQ0KDQojIG1vZGVsbyBBSUMNCnN1bW1hcnkobW9kZWxvX2FpYykNCg0KIyBvZGRzIHJhdGlvcw0Kb2Rkc19yYXRpb3MgPC0gZXhwKGNvZWYobW9kZWxvX2FpYykpDQpwcmludChvZGRzX3JhdGlvcykNCg0KIyBNb2RlbG8gYW1wbGlhZG8gY29uIHRvZGFzIGxhcyB2YXJpYWJsZXMNCm1vZGVsb19hbXBsaWFkbyA8LSBnbG0oc3Ryb2tlIH4gLiwgZGF0YSA9IGRhdG9zX3RyYWluLCBmYW1pbHkgPSBiaW5vbWlhbCkNCg0KIyBDb21wYXJhciBBSUMNCnByaW50KEFJQyhtb2RlbG9fYWljLCBtb2RlbG9fYW1wbGlhZG8pKQ0KDQojIENvbXBhcmFyIHJlbmRpbWllbnRvDQpwcmVkaWNjaW9uZXNfYWljIDwtIHByZWRpY3QobW9kZWxvX2FpYywgbmV3ZGF0YSA9IGRhdG9zX3RyYWluX0FJQywgdHlwZSA9ICJyZXNwb25zZSIpDQpwcmVkaWNjaW9uZXNfYW1wbGlhZG8gPC0gcHJlZGljdChtb2RlbG9fYW1wbGlhZG8sIG5ld2RhdGEgPSBkYXRvc190cmFpbiwgdHlwZSA9ICJyZXNwb25zZSIpDQoNCnJvY19haWMgPC0gcm9jKGRhdG9zX3RyYWluX0FJQyRzdHJva2UsIHByZWRpY2Npb25lc19haWMpDQpyb2NfYW1wbGlhZG8gPC0gcm9jKGRhdG9zX3RyYWluJHN0cm9rZSwgcHJlZGljY2lvbmVzX2FtcGxpYWRvKQ0KDQpwcmludChhdWMocm9jX2FpYykpDQpwcmludChhdWMocm9jX2FtcGxpYWRvKSkNCmBgYA0KTGEgZWRhZCAoYWdlKSBlcyBtdXkgc2lnbmlmaWNhdGl2YSAocCA8IDJlLTE2KSB5IHRpZW5lIHVuIG9kZHMgcmF0aW8gZGUgMS4wNzI3LCBsbyBxdWUgc2lnbmlmaWNhIHF1ZSBwb3IgY2FkYSBhw7FvIGRlIGF1bWVudG8gZW4gbGEgZWRhZCwgbGFzIHByb2JhYmlsaWRhZGVzIGRlIHRlbmVyIHVuIGFjY2lkZW50ZSBjZXJlYnJvdmFzY3VsYXIgYXVtZW50YW4gZW4gdW4gNy4yNyUuDQoNCkxhIGhpcGVydGVuc2nDs24gKGh5cGVydGVuc2lvbikgbm8gZXMgZXN0YWTDrXN0aWNhbWVudGUgc2lnbmlmaWNhdGl2YSAocCA9IDAuMTE2MCksIHBlcm8gdGllbmUgdW4gb2RkcyByYXRpbyBkZSAxLjM2MTMsIHN1Z2lyaWVuZG8gdW4gYXVtZW50byBkZWwgMzYuMTMlIGVuIGxhcyBwcm9iYWJpbGlkYWRlcyBkZSBhY2NpZGVudGUgY2VyZWJyb3Zhc2N1bGFyLg0KDQpMYSBlbmZlcm1lZGFkIGNhcmTDrWFjYSAoaGVhcnRfZGlzZWFzZSkgbm8gZXMgZXN0YWTDrXN0aWNhbWVudGUgc2lnbmlmaWNhdGl2YSAocCA9IDAuMTk4MSksIGNvbiB1biBvZGRzIHJhdGlvIGRlIDEuMzM0OC4NCg0KRWwgbml2ZWwgcHJvbWVkaW8gZGUgZ2x1Y29zYSAoYXZnX2dsdWNvc2VfbGV2ZWwpIGVzIHNpZ25pZmljYXRpdm8gKHAgPSAwLjAxMTcpIGNvbiB1biBvZGRzIHJhdGlvIGRlIDEuMDAzNSwgaW5kaWNhbmRvIHVuIHBlcXVlw7FvIGF1bWVudG8gZW4gbGFzIHByb2JhYmlsaWRhZGVzIHBvciBjYWRhIHVuaWRhZCBkZSBhdW1lbnRvIGVuIGVsIG5pdmVsIGRlIGdsdWNvc2EuDQoNCkVsIG5vIGhhYmVyIGZ1bWFkbyBlcyBzaWduaWZpY2F0aXZvIChwID0gMC4wMTUwKSB5IHRpZW5lIHVuIGVmZWN0byBkaWdhbW9zICJwcm90ZWN0b3IiLCBjb24gdW4gb2RkcyByYXRpbyBkZSAwLjY0MTYsIGxvIHF1ZSBzdWdpZXJlIHVuYSByZWR1Y2Npw7NuIGRlbCAzNS44NCUgZW4gbGFzIHByb2JhYmlsaWRhZGVzIGRlIGFjY2lkZW50ZSBjZXJlYnJvdmFzY3VsYXIgY29tcGFyYWRvIGNvbiBsYSBjYXRlZ29yw61hIGRlIHJlZmVyZW5jaWEuDQoNClNlciBmdW1hZG9yIChzbW9raW5nX3N0YXR1c3Ntb2tlcykgbm8gZXMgc2lnbmlmaWNhdGl2byAocCA9IDAuNzcxOCkuDQoNClBvciBvdHJvIGxhZG8sIHBvZGVtb3MgYWZpcm1hciBxdWUgZWwgbW9kZWxvIHRpZW5lIHVuIGJ1ZW4gcG9kZXIgcHJlZGljdGl2bywgY29uIHVuIEFVQyBkZSAwLjg0NTMsIGxvIHF1ZSBzZSBjb25zaWRlcmEgZ2VuZXJhbG1lbnRlIGNvbW8gdW4gcmVuZGltaWVudG8gYnVlbm8gYSBleGNlbGVudGUuDQoNCkxhIGRpZmVyZW5jaWEgZW4gQVVDIGVudHJlIGVsIG1vZGVsbyBBSUMgeSBlbCBtb2RlbG8gYW1wbGlhZG8gZXMgbXV5IHBlcXVlw7FhICgwLjAwMjUpLCBsbyBxdWUgc3VnaWVyZSBxdWUgbGFzIHZhcmlhYmxlcyBhZGljaW9uYWxlcyBlbiBlbCBtb2RlbG8gYW1wbGlhZG8gbm8gYXBvcnRhbiBtdWNoYSBtZWpvcmEgZW4gbGEgY2FwYWNpZGFkIHByZWRpY3RpdmEuDQoNCkxhIGVkYWQgeSBlbCBuaXZlbCBkZSBnbHVjb3NhIHNvbiBsb3MgcHJlZGljdG9yZXMgbcOhcyBzaWduaWZpY2F0aXZvcyB5IHJvYnVzdG9zIGVuIGVzdGUgbW9kZWxvLiBFbCBlZmVjdG8gInByb3RlY3RvciIgZGUgbnVuY2EgaGFiZXIgZnVtYWRvIGVzIGludGVyZXNhbnRlIHkgc2lnbmlmaWNhdGl2by4NCg0KDQoNCmBgYHtyfQ0KDQojaW50ZXJ2YWxvcyBkZSBjb25maWFuemENCmNpX2FpYyA8LSBjaShyb2NfYWljKQ0KY2lfYW1wbGlhZG8gPC0gY2kocm9jX2FtcGxpYWRvKQ0KDQojIEltcHJpbWlyIGxvcyByZXN1bHRhZG9zDQpwcmludCgiSW50ZXJ2YWxvIGRlIGNvbmZpYW56YSBwYXJhIGVsIEFVQyBkZWwgTW9kZWxvIEFJQzoiKQ0KcHJpbnQoY2lfYWljKQ0KDQpwcmludCgiSW50ZXJ2YWxvIGRlIGNvbmZpYW56YSBwYXJhIGVsIEFVQyBkZWwgTW9kZWxvIEFtcGxpYWRvOiIpDQpwcmludChjaV9hbXBsaWFkbykNCg0KIyBHcmFmaWNhciBsYXMgY3VydmFzIFJPQyBjb24gaW50ZXJ2YWxvcyBkZSBjb25maWFuemENCnBsb3Qocm9jX2FpYywgbWFpbj0iQ3VydmEgUk9DIC0gQ29tcGFyYWNpw7NuIGRlIE1vZGVsb3MgY29uIElDIiwgDQogICAgIGNvbD0iYmx1ZSIsIGx3ZD0yKQ0KbGluZXMocm9jX2FtcGxpYWRvLCBjb2w9InJlZCIsIGx3ZD0yKQ0KDQpgYGANCg0KKipDb21wYXJhY2nDs24gZGUgbW9kZWxvcyoqOg0KDQpFbCBST0MgbXVlc3RyYSBjw7NtbyBzZSBjb21wb3J0YSBlbCBtb2RlbG8gYSB0cmF2w6lzIGRlIGRpZmVyZW50ZXMgdW1icmFsZXMgZGUgY2xhc2lmaWNhY2nDs24sIHBlcm1pdGllbmRvIGV2YWx1YXIgc3UgcmVuZGltaWVudG8gZ2VuZXJhbC4NCg0KRWwgw6FyZWEgYmFqbyBsYSBjdXJ2YSBST0MgKEFVQy1ST0MpIHByb3BvcmNpb25hIHVuYSBtZWRpZGEgw7puaWNhIGRlbCByZW5kaW1pZW50byBkZWwgbW9kZWxvLCBpbmRlcGVuZGllbnRlIGRlbCB1bWJyYWwgZGUgY2xhc2lmaWNhY2nDs24gZWxlZ2lkby4NCg0KUGVybWl0ZSBjb21wYXJhciBmw6FjaWxtZW50ZSBkaWZlcmVudGVzIG1vZGVsb3MgZGUgY2xhc2lmaWNhY2nDs24gZW4gdW4gbWlzbW8gZ3LDoWZpY28uIEF5dWRhIGEgZGV0ZXJtaW5hciBxdcOpIG1vZGVsbyB0aWVuZSB1biBtZWpvciByZW5kaW1pZW50byBnZW5lcmFsLg0KDQpMYXMgY3VydmFzIGVzdMOhbiBjYXNpIHN1cGVycHVlc3RhcywgbG8gcXVlIHN1Z2llcmUgcXVlIGVsIHJlbmRpbWllbnRvIGRlIGFtYm9zIG1vZGVsb3MgZXMgbXV5IHNpbWlsYXIsIGxvIGN1YWwgZXMgY29uc2lzdGVudGUgY29uIGVsIGhlY2hvIGRlIHF1ZSBsb3MgdmFsb3JlcyBkZSBBVUMgKEFyZWEgVW5kZXIgdGhlIEN1cnZlKSBzb24gMC44NDUzIHBhcmEgZWwgTW9kZWxvIEFJQyB5IDAuODQ3OCBwYXJhIGVsIE1vZGVsbyBBbXBsaWFkby4NCg0KQmFzw6FuZG9ub3MgZW4gZXN0b3MgaW50ZXJ2YWxvcyBkZSBjb25maWFuemEsIHBvZGVtb3MgYWZpcm1hciBjb24gdW4gOTUlIGRlIGNvbmZpYW56YSBxdWUgZWwgdmVyZGFkZXJvIEFVQyBwYXJhIGFtYm9zIG1vZGVsb3Mgc2UgZW5jdWVudHJhIGVudHJlIGFwcm94aW1hZGFtZW50ZSAwLjgyIHkgMC44Ny4gTGEgc3VwZXJwb3NpY2nDs24gZGUgbG9zIGludGVydmFsb3Mgc3VnaWVyZSBxdWUgbm8gaGF5IHVuYSBkaWZlcmVuY2lhIGVzdGFkw61zdGljYW1lbnRlIHNpZ25pZmljYXRpdmEgZW50cmUgbG9zIGRvcyBtb2RlbG9zIGVuIHTDqXJtaW5vcyBkZSBjYXBhY2lkYWQgZGlzY3JpbWluYXRpdmEuDQoNCkRhZG8gcXVlIG5vIGhheSB1bmEgZGlmZXJlbmNpYSBzaWduaWZpY2F0aXZhIGVudHJlIGxvcyBtb2RlbG9zLCBzZXLDrWEgcmF6b25hYmxlIHByZWZlcmlyIGVsIE1vZGVsbyBBSUMgcG9yIHN1IHNpbXBsaWNpZGFkIChwcmluY2lwaW8gZGUgcGFyc2ltb25pYSkuIEVsIE1vZGVsbyBBSUMgcHJvcG9yY2lvbmEgZXNlbmNpYWxtZW50ZSBlbCBtaXNtbyByZW5kaW1pZW50byBwcmVkaWN0aXZvIGNvbiBtZW5vcyB2YXJpYWJsZXMsIGxvIHF1ZSBsbyBoYWNlIG3DoXMgZsOhY2lsIGRlIGludGVycHJldGFyIHkgcG9zaWJsZW1lbnRlIG3DoXMgcm9idXN0byBlbiBsYSBnZW5lcmFsaXphY2nDs24gYSBudWV2b3MgZGF0b3MuDQoNCg0KYGBge3J9DQojIHByZWRpY2NpbyBlbiBlbCBjb25qdW50byBkZSBwcnVlYmENCnByZWRpY2Npb25lcyA8LSBwcmVkaWN0KG1vZGVsb19haWMsIG5ld2RhdGEgPSBkYXRvc190ZXN0X0FJQywgdHlwZSA9ICJyZXNwb25zZSIpDQpzdW1tYXJ5KHByZWRpY2Npb25lcykNCg0KI0NvbiB1bWJyYWwgZGUgMC4yDQpwcmVkaWNjaW9uZXNfYmluYXJpYXMgPC0gaWZlbHNlKHByZWRpY2Npb25lcyA+IDAuMiwgMSwgMCkgIA0KdmFsb3Jlc19yZWFsZXMgPC0gZGF0b3NfdGVzdF9BSUMkc3Ryb2tlDQoNCiMgQ3JlYXIgbWF0cml6IGRlIGNvbmZ1c2nDs24NCmNtIDwtIGNvbmZ1c2lvbk1hdHJpeChmYWN0b3IocHJlZGljY2lvbmVzX2JpbmFyaWFzKSwgZmFjdG9yKHZhbG9yZXNfcmVhbGVzKSkNCnByaW50KGNtKQ0KDQojIG3DqXRyaWNhcyBlc3BlY8OtZmljYXMNCnNlbnNpYmlsaWRhZCA8LSBjbSRieUNsYXNzWydTZW5zaXRpdml0eSddDQplc3BlY2lmaWNpZGFkIDwtIGNtJGJ5Q2xhc3NbJ1NwZWNpZmljaXR5J10NCnByZWNpc2lvbiA8LSBjbSRieUNsYXNzWydQcmVjaXNpb24nXQ0KZXhhY3RpdHVkIDwtIGNtJG92ZXJhbGxbJ0FjY3VyYWN5J10NCmYxX3Njb3JlIDwtIGNtJGJ5Q2xhc3NbJ0YxJ10NCg0KIyBDYWxjdWxhciBsYSBjdXJ2YSBST0MgeSBBVUMgcGFyYSBsb3MgZGF0b3MgZGUgcHJ1ZWJhDQpyb2NfdGVzdCA8LSByb2MoZGF0b3NfdGVzdF9BSUMkc3Ryb2tlLCBwcmVkaWNjaW9uZXMpDQphdWNfdGVzdCA8LSBhdWMocm9jX3Rlc3QpDQoNCiMgUk9DIGRlIHBydWViYQ0KcGxvdChyb2NfdGVzdCwgbWFpbiA9ICJDdXJ2YSBST0MgLSBEYXRvcyBkZSBQcnVlYmEiLCBjb2wgPSAiYmx1ZSIpDQphYmxpbmUoYSA9IDAsIGIgPSAxLCBsdHkgPSAyLCBjb2wgPSAiZ3JheSIpDQoNCmBgYA0KDQoqKlNlbnNpYmlsaWRhZCoqICgwLjk2MjEpOiBBbHRhLCBpbmRpY2FuZG8gcXVlIGxhIG1heW9yw61hIGRlIGxvcyBjYXNvcyBwb3NpdGl2b3MgcmVhbGVzIGZ1ZXJvbiBjb3JyZWN0YW1lbnRlIGlkZW50aWZpY2Fkb3MuDQoNCioqRXNwZWNpZmljaWRhZCoqICgwLjI2MjUpOiBCYWphLCBsbyBxdWUgc3VnaWVyZSBxdWUgZWwgbW9kZWxvIHRpZW5lIGRpZmljdWx0YWQgcGFyYSBpZGVudGlmaWNhciBjb3JyZWN0YW1lbnRlIGxvcyBjYXNvcyBuZWdhdGl2b3MuDQoNCioqUHJlY2lzacOzbioqICgwLjk1OTUpOiBBbHRhLCBpbmRpY2FuZG8gcXVlIGxhIG1heW9yw61hIGRlIGxhcyBwcmVkaWNjaW9uZXMgcG9zaXRpdmFzIHNvbiBjb3JyZWN0YXMuDQoNCioqRXhhY3RpdHVkKiogKDAuOTI1Nik6IEFsdGEsIG1vc3RyYW5kbyB1biBidWVuIHJlbmRpbWllbnRvIGdlbmVyYWwgZGVsIG1vZGVsby4NCg0KKipGMS1TY29yZSoqICgwLjk2MDgpOiBBbHRhLCBsbyBxdWUgaW5kaWNhIHVuIGJ1ZW4gYmFsYW5jZSBlbnRyZSBwcmVjaXNpw7NuIHkgc2Vuc2liaWxpZGFkLg0KDQogTHVlZ28gZGUgY29tcGFyYXIgY29uIGVsIHVtYnJhbCBlbiAwLjUgeSAwLjEsIGVzICoqMC4yKiogZWwgdW1icmFsIHF1ZSBwcm9wb3JjaW9uYSB1biBtZWpvciBiYWxhbmNlIGVudHJlIHNlbnNpYmlsaWRhZCAoMC45NjIxKSB5IGVzcGVjaWZpY2lkYWQgKDAuMjYyNSkuDQoNCiMjIDQuQ29uY2x1c2nDs24NCg0KKipGYWN0b3JlcyBkZSByaWVzZ28gcHJpbmNpcGFsZXM6KioNCg0KTGEgZWRhZCBlcyBlbCBwcmVkaWN0b3IgbcOhcyBmdWVydGUgeSBzaWduaWZpY2F0aXZvIHBhcmEgZWwgYWNjaWRlbnRlIGNlcmVicm92YXNjdWxhci4gUG9yIGNhZGEgYcOxbyBkZSBhdW1lbnRvIGVuIGxhIGVkYWQsIGVsIHJpZXNnbyBhdW1lbnRhIHVuIDcuMjclLg0KDQpFbCBuaXZlbCBwcm9tZWRpbyBkZSBnbHVjb3NhIGVuIHNhbmdyZSBlcyBlbCBzZWd1bmRvIGZhY3RvciBtw6FzIGltcG9ydGFudGUsIGF1bnF1ZSBzdSBlZmVjdG8gZXMgbcOhcyBwZXF1ZcOxbyBwZXJvIGVzdGFkw61zdGljYW1lbnRlIHNpZ25pZmljYXRpdm8uDQoNCk51bmNhIGhhYmVyIGZ1bWFkbyBwYXJlY2UgdGVuZXIgdW4gZWZlY3RvIHByb3RlY3RvciBzaWduaWZpY2F0aXZvLCByZWR1Y2llbmRvIGVsIHJpZXNnbyBkZSBhY2NpZGVudGUgY2VyZWJyb3Zhc2N1bGFyIGVuIHVuIDM1Ljg0JSBjb21wYXJhZG8gY29uIGxhIGNhdGVnb3LDrWEgZGUgcmVmZXJlbmNpYS4NCg0KKipNb2RlbG8qKg0KDQpFbCBtb2RlbG8gdGllbmUgdW4gYnVlbiBwb2RlciBwcmVkaWN0aXZvLCBjb24gdW4gQVVDIGRlIDAuODQ1MyAoSUMgOTUlOiAwLjgyMTQtMC44NzA4KS4NCkxhIGRpZmVyZW5jaWEgZW4gcmVuZGltaWVudG8gZW50cmUgZWwgbW9kZWxvIEFJQyB5IGVsIG1vZGVsbyBhbXBsaWFkbyBlcyBtw61uaW1hLCBsbyBxdWUgc3VnaWVyZSBxdWUgdW4gbW9kZWxvIG3DoXMgc2ltcGxlIGVzIHN1ZmljaWVudGUgcGFyYSBwcmVkZWNpciBlbCByaWVzZ28gZGUgYWNjaWRlbnRlIGNlcmVicm92YXNjdWxhci4NCg0KDQoqKkltcGxpY2FjaW9uZXMgY2zDrW5pY2FzOioqDQoNCkVsIGNvbnRyb2wgZGUgbGEgZ2x1Y29zYSBlbiBzYW5ncmUgeSBsYSBwcm9tb2Npw7NuIGRlIGjDoWJpdG9zIGRlIG5vIGZ1bWFyIHBvZHLDrWFuIHNlciBlc3RyYXRlZ2lhcyBlZmVjdGl2YXMgcGFyYSByZWR1Y2lyIGVsIHJpZXNnbyBkZSBhY2NpZGVudGUgY2VyZWJyb3Zhc2N1bGFyLg0KDQpFbiByZXN1bWVuLCBlc3RlIGFuw6FsaXNpcyBwYXJlY2UgcHJvcG9yY2lvbmFybm9zIHVuYSBoZXJyYW1pZW50YSDDunRpbCBwYXJhIGlkZW50aWZpY2FyIGluZGl2aWR1b3MgZW4gcmllc2dvIGRlIGFjY2lkZW50ZSBjZXJlYnJvdmFzY3VsYXIsIGNvbiBsYSBlZGFkIHkgZWwgbml2ZWwgZGUgZ2x1Y29zYSBjb21vIGxvcyBwcmluY2lwYWxlcyBmYWN0b3JlcyBhIGNvbnNpZGVyYXIuIEVsIG1vZGVsbyBvZnJlY2UgdW4gYnVlbiBlcXVpbGlicmlvIGVudHJlIHNpbXBsaWNpZGFkIHkgcG9kZXIgcHJlZGljdGl2bywgbG8gcXVlIGxvIGhhY2UgcG90ZW5jaWFsbWVudGUgdmFsaW9zbyBwYXJhIHN1IHVzbyBlbiBlbnRvcm5vcyBjbMOtbmljb3MuDQo=