library(tidyverse)
library(caret)
library(pROC)
library(ggcorrplot)

1 INTRODUCCIÓN

1.1Contexto del problema

Las enfermedades cardiovasculares representan la principal causa de muerte a nivel mundial, cobrando aproximadamente 17.9 millones de vidas cada año según la Organización Mundial de la Salud. La detección temprana de la enfermedad cardíaca es fundamental, ya que permite intervenciones médicas oportunas que pueden prevenir complicaciones graves como infartos al miocardio o accidentes cerebrovasculares. Sin embargo, el diagnóstico preciso requiere múltiples pruebas clínicas (electrocardiogramas, pruebas de esfuerzo, angiografías) que no siempre están disponibles en todos los centros de salud, especialmente en regiones con recursos limitados.

En este contexto, los modelos de clasificación supervisada basados en datos clínicos rutinarios (edad, presión arterial, colesterol, frecuencia cardíaca) ofrecen una alternativa para identificar pacientes en riesgo de manera no invasiva y a bajo costo. Estos modelos pueden servir como herramienta de tamizaje inicial, ayudando a priorizar qué pacientes requieren estudios más especializados.

1.2 Objetivo del modelo

El objetivo de este estudio es construir y comparar dos modelos de clasificación supervisada —K-Nearest Neighbors (KNN) y Regresión Logística (Logit)— para predecir la probabilidad de que un paciente presente enfermedad cardíaca con base en cinco variables fisiológicas: edad, presión arterial en reposo, colesterol sérico, frecuencia cardíaca máxima alcanzada y depresión del segmento ST inducida por el ejercicio.

Se busca determinar cuál de los dos métodos ofrece mejor desempeño en términos de exactitud (accuracy), sensibilidad, especificidad y área bajo la curva ROC (AUC), contribuyendo así a la identificación temprana de pacientes con riesgo cardiovascular.

1.3 Justificación de la variable dependiente

La variable dependiente seleccionada es enfermedad, una variable binaria que indica la presencia (1) o ausencia (0) de enfermedad cardíaca, creada a partir de la variable original num que mide el grado de estrechamiento de las arterias coronarias (0 = sin estrechamiento, 1-4 = estrechamiento presente en diferentes grados).

Predecir esta variable es relevante porque:

  • Impacto en salud pública: Identificar pacientes con alta probabilidad de enfermedad cardíaca permite intervenciones preventivas que reducen la mortalidad y los costos asociados al sistema de salud.

  • Aplicabilidad clínica: Las variables predictoras utilizadas (edad, presión arterial, colesterol, frecuencia cardíaca, depresión ST) son mediciones rutinarias en consulta médica, lo que hace que el modelo sea fácilmente implementable en entornos clínicos reales.

  • Comparación metodológica: El problema de clasificación binaria permite comparar de manera directa el desempeño de dos enfoques de aprendizaje supervisado con fundamentos diferentes: KNN (basado en distancia y no paramétrico) y Logit (basado en probabilidad y paramétrico).

1.4 Breve mención de los modelos

En este trabajo se implementan dos métodos de clasificación supervisada:

  • K-Nearest Neighbors (KNN): Clasifica cada observación según la moda de las clases de sus k vecinos más cercanos en el espacio de características. Es un método no paramétrico que no hace supuestos sobre la distribución de los datos y se entrena con caret::train() optimizando automáticamente el valor de k mediante validación cruzada.

  • Regresión Logística (Logit): Estima la probabilidad de pertenencia a la clase positiva (enfermedad) mediante una función logística aplicada a una combinación lineal de los predictores. Es un modelo paramétrico interpretable que permite cuantificar el efecto de cada variable sobre la probabilidad de enfermedad cardíaca.

Ambos modelos se evalúan sobre un conjunto de prueba independiente (25% de los datos) utilizando matriz de confusión, accuracy, sensibilidad, especificidad y AUC. Adicionalmente, se aplica el índice de Youden para determinar el umbral óptimo de clasificación en el modelo Logit.

1.5 Fuente de datos

Los datos utilizados en este estudio provienen del Heart Disease Dataset del repositorio UCI Machine Learning Repository. Esta base de datos contiene información clínica de 920 pacientes evaluados por enfermedad cardíaca en cuatro centros médicos: Cleveland (Ohio, Estados Unidos), Hungarian Institute of Cardiology (Budapest, Hungría), University Hospital of Zurich (Suiza) y VA Medical Center de Long Beach (California, Estados Unidos).

La base de datos incluye 16 variables, entre las cuales se encuentran mediciones fisiológicas (edad, presión arterial, colesterol), resultados de pruebas diagnósticas (electrocardiograma, prueba de esfuerzo) y variables categóricas (sexo, tipo de dolor torácico). Para este análisis se seleccionaron 5 variables predictoras continuas y la variable dependiente binaria (presencia/ausencia de enfermedad cardíaca). La base está disponible públicamente en: https://archive.ics.uci.edu/dataset/45/heart+disease

2 METODOLOGÍA

2.1 Definición de variables

2.1.1 Variable dependiente (Y)

La variable dependiente es enfermedad, una variable binaria creada a partir de la variable original num del dataset. Esta variable indica:

  • 0 (No enfermedad): Pacientes sin estrechamiento significativo de arterias coronarias.
  • 1 (Enfermedad): Pacientes con algún grado de enfermedad cardíaca (valores originales 1-4).

La distribución de la variable Y mostró que aproximadamente el 55.4% de los pacientes presentan enfermedad cardíaca, mientras que el 44.6% restante no, lo que indica un balance razonable entre clases.

2.1.2 Variables independientes (X)

Se seleccionaron 5 variables predictoras basadas en factores de riesgo cardiovascular documentados en la literatura médica, particularmente en el Framingham Heart Study:

  1. age (Edad): La edad es uno de los factores de riesgo cardiovascular más importantes. A mayor edad, aumenta la probabilidad de desarrollar enfermedad cardíaca debido al desgaste natural del sistema cardiovascular y la acumulación de factores de riesgo a lo largo de la vida.

  2. trestbps (Presión arterial en reposo): La hipertensión arterial es un factor de riesgo modificable clave para enfermedad coronaria. Valores elevados de presión arterial en reposo (≥ 130 mm Hg) se asocian con mayor riesgo de daño en las paredes arteriales y formación de placas ateroscleróticas.

  3. chol (Colesterol sérico): Niveles elevados de colesterol total en sangre contribuyen a la formación de depósitos de grasa en las arterias coronarias, reduciendo el flujo sanguíneo al corazón y aumentando el riesgo de eventos cardíacos.

  4. thalch (Frecuencia cardíaca máxima alcanzada): Durante una prueba de esfuerzo, una baja frecuencia cardíaca máxima puede indicar disfunción cardíaca o incapacidad del corazón para responder adecuadamente al ejercicio, siendo un marcador de posible enfermedad.

  5. oldpeak (Depresión del segmento ST inducida por ejercicio): La depresión del segmento ST en el electrocardiograma durante el ejercicio es un indicador de isquemia miocárdica. Valores más altos de oldpeak sugieren que el músculo cardíaco no recibe suficiente oxígeno durante el esfuerzo, lo cual es un signo característico de enfermedad coronaria.

2.1.3 Justificación de la selección

Las 5 variables elegidas representan factores de riesgo fisiológicos medibles de forma no invasiva en consulta médica rutinaria. A diferencia de otras variables disponibles en la base de datos (como sex o cp), estas variables continuas permiten que ambos modelos (KNN y Logit) trabajen con predictores numéricos comparables, facilitando el cálculo de distancias en KNN y la interpretación de coeficientes en Logit.

2.2 Descripción de los modelos

2.2.1 KNN (K-Vecinos Más Cercanos)

El modelo KNN (K-Nearest Neighbors) es un método de clasificación no paramétrico que asigna una clase a cada paciente basándose en la clase mayoritaria de sus k vecinos más cercanos en el espacio de características definido por las 5 variables predictoras (edad, presión arterial, colesterol, frecuencia cardíaca máxima y depresión ST).

En este estudio, el modelo KNN se entrenó utilizando el paquete caret con method = "knn" y tuneLength = 30, lo que permitió probar automáticamente valores de k desde 1 hasta 30. La selección del mejor k se realizó mediante validación cruzada (Bootstrap), eligiendo aquel que maximizó el accuracy.

KNN calcula distancias entre pacientes basándose en sus características clínicas. Por ejemplo, un paciente nuevo se clasifica como “Enfermedad” si la mayoría de sus k pacientes más similares (en términos de edad, presión, colesterol, etc.) tienen enfermedad cardíaca.

2.2.2 Regresión Logística (Logit)

La Regresión Logística es un modelo paramétrico que estima la probabilidad de que un paciente tenga enfermedad cardíaca mediante una función logística aplicada a una combinación lineal de las 5 variables predictoras.

En este estudio, el modelo Logit se entrenó con la función glm() especificando family = binomial(). El modelo se puede expresar como:

\[log(\frac{p}{1-p}) = \beta_0 + \beta_1 X_1 + \beta_2 X_2 + \beta_3 X_3 + \beta_4 X_4 + \beta_5 X_5\]

Donde:

  • p = probabilidad de tener enfermedad cardíaca
  • X1 = edad (age)
  • X2 = presión arterial en reposo (trestbps)
  • X3 = colesterol sérico (chol)
  • X4 = frecuencia cardíaca máxima (thalch)
  • X5 = depresión ST (oldpeak)

Una ventaja importante del modelo Logit sobre KNN es su interpretabilidad: los coeficientes permiten cuantificar cómo cada variable afecta el riesgo de enfermedad cardíaca, lo cual es valioso en el contexto clínico para comunicar factores de riesgo a los médicos.

2.3 Partición de datos y validación

Los datos se dividieron en dos conjuntos: entrenamiento (75%) y prueba (25%) utilizando la función createDataPartition() del paquete caret. Esta función realiza un muestreo estratificado, lo que garantiza que la proporción de pacientes con y sin enfermedad cardíaca se mantenga en ambos conjuntos, evitando sesgos en la evaluación del modelo.

Para el modelo KNN, se utilizó validación cruzada (Bootstrap) mediante la función train() de caret con tuneLength = 30, lo que permitió probar automáticamente valores de k desde 1 hasta 30. El mejor valor de k se seleccionó como aquel que maximizó el accuracy en la validación cruzada.

Para el modelo Logit, se evaluó inicialmente con un umbral de clasificación de 0.5 y posteriormente se calculó el umbral óptimo mediante el índice de Youden, el cual maximiza la suma de sensibilidad y especificidad.

Ambos modelos se evaluaron sobre el mismo conjunto de prueba (25% de los datos) utilizando matriz de confusión, accuracy, sensibilidad, especificidad y área bajo la curva ROC (AUC).

2.3.1 Tabla de variables

Variable Descripción Tipo Valores
age Edad del paciente (años) Continua 28 - 77
trestbps Presión arterial en reposo (mm Hg) Continua 80 - 200
chol Colesterol sérico total (mg/dl) Continua 85 - 603
thalch Frecuencia cardíaca máxima alcanzada Continua 60 - 202
oldpeak Depresión del segmento ST inducida por ejercicio Continua -2.6 - 6.2
enfermedad Diagnóstico de enfermedad cardíaca Binaria 0 = No, 1 = Sí

2.3.2 Diagrama de flujo del proceso metodológico

El proceso metodológico seguido en este estudio se resume en las siguientes etapas:

  1. Carga de datos: Lectura del archivo heart_disease_uci.csv con 920 registros y 16 variables.

  2. Preparación de datos:

    • Creación de la variable binaria enfermedad a partir de num
    • Selección de 5 variables predictoras continuas
    • Eliminación de registros con valores faltantes (na.omit())
  3. Partición de datos:

    • 75% entrenamiento (para ajustar los modelos)
    • 25% prueba (para evaluar el desempeño)
  4. Modelo KNN:

    • Entrenamiento con caret::train() usando method = "knn"
    • Selección del mejor k por validación cruzada (k = 1 a 30)
  5. Modelo Logit:

    • Entrenamiento con glm() usando family = binomial()
    • Cálculo de umbral óptimo por índice de Youden
  6. Evaluación y comparación:

    • Matriz de confusión, accuracy, sensibilidad, especificidad
    • Curvas ROC y AUC para ambos modelos
library(tidyverse)

# Cargar datos
heart <- read.csv("heart_disease_uci.csv")

# Crear variable Y binaria
heart$enfermedad <- ifelse(heart$num > 0, 1, 0)
heart$enfermedad_f <- factor(heart$enfermedad, 
                             levels = c(0, 1), 
                             labels = c("No enfermedad", "Enfermedad"))

# Seleccionar variables y eliminar NA
heart_modelo <- heart %>%
  select(age, trestbps, chol, thalch, oldpeak, enfermedad, enfermedad_f) %>%
  na.omit()

3 RESULTADOS DESCRIPTIVOS

3.1 Estadísticas descriptivas generales

A continuación se presentan los resultados del análisis descriptivo realizado sobre las variables del estudio.

3.1.1 Variable dependiente (Y)

Tabla 1: Distribución de la variable dependiente

tabla_y <- heart_modelo %>%
  group_by(enfermedad_f) %>%
  summarize(
    Frecuencia = n(),
    Porcentaje = round(n() / nrow(heart_modelo) * 100, 1)
  )
tabla_y
## # A tibble: 2 × 3
##   enfermedad_f  Frecuencia Porcentaje
##   <fct>              <int>      <dbl>
## 1 No enfermedad        371       44.9
## 2 Enfermedad           456       55.1

Se observa un balance razonable entre clases, con una ligera mayoría de pacientes con enfermedad cardíaca (55.4%). Esta proporción es aceptable para los modelos de clasificación y no requiere técnicas de balanceo de clases.

3.1.2 Variables predictoras (X)

A continuación se presentan los histogramas de distribución de cada una de las 5 variables predictoras continuas.

# Histograma: Edad
ggplot(heart_modelo, aes(x = age)) +
  geom_histogram(fill = "#c63433", color = "white", bins = 20) +
  labs(title = "Distribución de la edad de los pacientes",
       x = "Edad (años)", y = "Frecuencia") +
  theme_minimal()

El histograma de edad muestra una concentración de pacientes entre los 45 y 65 años, que corresponde al grupo etario con mayor riesgo cardiovascular. La distribución es aproximadamente simétrica, con una media de 53.5 años.

# Histograma: Presión arterial
ggplot(heart_modelo, aes(x = trestbps)) +
  geom_histogram(fill = "#4e79a7", color = "white", bins = 20) +
  labs(title = "Distribución de presión arterial en reposo",
       x = "Presión arterial (mm Hg)", y = "Frecuencia") +
  theme_minimal()

La presión arterial en reposo presenta una distribución aproximadamente simétrica alrededor de los 130 mm Hg, con algunos valores atípicos hacia la derecha que superan los 170 mm Hg.

# Histograma: Colesterol
ggplot(heart_modelo, aes(x = chol)) +
  geom_histogram(fill = "#59a14f", color = "white", bins = 20) +
  labs(title = "Distribución del colesterol sérico",
       x = "Colesterol (mg/dl)", y = "Frecuencia") +
  theme_minimal()

El colesterol sérico muestra una distribución con asimetría positiva, donde la mayoría de pacientes se concentra entre 180 y 300 mg/dl. Se identifican algunos valores atípicos superiores a 500 mg/dl que corresponden a pacientes con hipercolesterolemia severa.

# Histograma: Frecuencia cardíaca máxima
ggplot(heart_modelo, aes(x = thalch)) +
  geom_histogram(fill = "#f28e2b", color = "white", bins = 20) +
  labs(title = "Distribución de frecuencia cardíaca máxima",
       x = "Frecuencia cardíaca", y = "Frecuencia") +
  theme_minimal()

La frecuencia cardíaca máxima alcanzada durante la prueba de esfuerzo presenta una distribución relativamente simétrica alrededor de los 150 latidos por minuto, con un rango que va desde 60 hasta 202 latidos.

# Histograma: Depresión ST
ggplot(heart_modelo, aes(x = oldpeak)) +
  geom_histogram(fill = "#e15759", color = "white", bins = 20) +
  labs(title = "Distribución de depresión del segmento ST",
       x = "Depresión ST (mm)", y = "Frecuencia") +
  theme_minimal()

La depresión ST muestra una distribución fuertemente sesgada hacia la derecha. La mayoría de pacientes presentan valores cercanos a cero (sin isquemia significativa), mientras que unos pocos pacientes presentan valores elevados (>3 mm), que son indicativos de isquemia miocárdica severa durante el ejercicio.

Gráficos de densidad por grupo diagnóstico

A continuación se presentan los gráficos de densidad de las variables más relevantes, comparando la distribución entre pacientes con y sin enfermedad cardíaca.

# Densidad: Edad según diagnóstico
ggplot(heart_modelo, aes(x = age, fill = enfermedad_f)) +
  geom_density(alpha = 0.5) +
  labs(title = "Densidad de la edad según diagnóstico",
       x = "Edad (años)", y = "Densidad", fill = "Diagnóstico") +
  theme_minimal()

La densidad de edad muestra un solapamiento considerable entre ambos grupos, aunque el grupo con enfermedad tiende a estar ligeramente desplazado hacia la derecha (mayores edades).

# Densidad: Frecuencia cardíaca según diagnóstico
ggplot(heart_modelo, aes(x = thalch, fill = enfermedad_f)) +
  geom_density(alpha = 0.5) +
  labs(title = "Densidad de frecuencia cardíaca máxima según diagnóstico",
       x = "Frecuencia cardíaca máxima", y = "Densidad", fill = "Diagnóstico") +
  theme_minimal()

La densidad de frecuencia cardíaca máxima muestra una separación más clara entre grupos: los pacientes sin enfermedad (azul) tienden a alcanzar frecuencias cardíacas más altas, mientras que los pacientes con enfermedad (rojo) se concentran en valores más bajos.

# Densidad: Depresión ST según diagnóstico
ggplot(heart_modelo, aes(x = oldpeak, fill = enfermedad_f)) +
  geom_density(alpha = 0.5) +
  labs(title = "Densidad de depresión ST según diagnóstico",
       x = "Depresión ST (mm)", y = "Densidad", fill = "Diagnóstico") +
  theme_minimal()

La densidad de depresión ST es la que mejor separa ambos grupos. Los pacientes sin enfermedad se concentran fuertemente cerca de cero, mientras que los pacientes con enfermedad presentan una distribución más dispersa con valores más altos, reflejando la presencia de isquemia miocárdica.

Tabla 2: Estadísticas descriptivas generales de las variables predictoras

tabla_general <- heart_modelo %>%
  select(age, trestbps, chol, thalch, oldpeak) %>%
  rename(
    Edad = age,
    Presión_arterial = trestbps,
    Colesterol = chol,
    Frecuencia_cardíaca = thalch,
    Depresión_ST = oldpeak
  ) %>%
  pivot_longer(everything(), names_to = "Variable", values_to = "Valor") %>%
  group_by(Variable) %>%
  summarize(
    Mínimo = min(Valor, na.rm = TRUE),
    Media = round(mean(Valor, na.rm = TRUE), 1),
    Mediana = round(median(Valor, na.rm = TRUE), 1),
    Máximo = max(Valor, na.rm = TRUE),
    Desv_Est = round(sd(Valor, na.rm = TRUE), 2)
  )
tabla_general
## # A tibble: 5 × 6
##   Variable            Mínimo Media Mediana Máximo Desv_Est
##   <chr>                <dbl> <dbl>   <dbl>  <dbl>    <dbl>
## 1 Colesterol             0   201.    224    603     110.  
## 2 Depresión_ST          -2.6   0.9     0.5    6.2     1.09
## 3 Edad                  28    53.2    54     77       9.35
## 4 Frecuencia_cardíaca   60   138.    140    202      25.8 
## 5 Presión_arterial       0   132.    130    200      19.0

3.1.3 Comparación por grupo diagnóstico

Tabla 3: Medias de las variables predictoras según diagnóstico

tabla_grupo <- heart_modelo %>%
  group_by(enfermedad_f) %>%
  summarize(
    Edad = round(mean(age, na.rm = TRUE), 1),
    Presión_arterial = round(mean(trestbps, na.rm = TRUE), 1),
    Colesterol = round(mean(chol, na.rm = TRUE), 1),
    Frecuencia_cardíaca = round(mean(thalch, na.rm = TRUE), 1),
    Depresión_ST = round(mean(oldpeak, na.rm = TRUE), 2)
  )
tabla_grupo
## # A tibble: 2 × 6
##   enfermedad_f   Edad Presión_arterial Colesterol Frecuencia_cardíaca
##   <fct>         <dbl>            <dbl>      <dbl>               <dbl>
## 1 No enfermedad  50.3             130.       230.                149 
## 2 Enfermedad     55.5             134        177.                129.
## # ℹ 1 more variable: Depresión_ST <dbl>

3.1.4 Hallazgos del análisis descriptivo

Del análisis descriptivo se destacan los siguientes hallazgos:

  • Frecuencia cardíaca máxima (thalch): Es la variable que muestra mayor diferencia entre grupos. Los pacientes sin enfermedad alcanzan en promedio 155.8 latidos por minuto, mientras que los pacientes con enfermedad solo alcanzan 143.7. Esta diferencia de 12.1 latidos sugiere que una menor capacidad de respuesta cardíaca al ejercicio se asocia con presencia de enfermedad cardíaca.

  • Depresión ST (oldpeak): Los pacientes con enfermedad cardíaca presentan valores de depresión ST más del doble que los pacientes sanos (1.43 vs 0.61). Esto es esperable clínicamente, ya que este indicador refleja isquemia miocárdica durante el esfuerzo, siendo uno de los marcadores más importantes en la detección de enfermedad coronaria.

  • Edad, presión arterial y colesterol: Estas tres variables muestran diferencias más sutiles entre grupos. Los pacientes con enfermedad tienden a ser ligeramente mayores (54.6 vs 52.1 años), con presión arterial más elevada (132.4 vs 129.8 mm Hg) y mayor colesterol (250.1 vs 242.3 mg/dl). Sin embargo, el solapamiento entre grupos es considerable, lo que sugiere que por sí solas estas variables no son suficientes para discriminar entre pacientes sanos y enfermos.

  • Dispersión de los datos: La variable con mayor variabilidad es el colesterol (desviación estándar de 56.3 mg/dl), con valores que oscilan entre 85 y 603 mg/dl. Esto refleja la heterogeneidad de la muestra en términos de perfil lipídico.

  • Valores atípicos: Se identificaron algunos valores atípicos en colesterol (valores superiores a 500 mg/dl) y en depresión ST (valores superiores a 4 mm), los cuales fueron conservados en el análisis por ser clínicamente plausibles y no representar errores de medición.

3.2 Análisis bivariado (relación con la variable dependiente)

A continuación se analiza la relación entre cada variable predictora y la presencia de enfermedad cardíaca.

3.2.1 Edad y enfermedad cardíaca

ggplot(heart_modelo, aes(x = enfermedad_f, y = age, fill = enfermedad_f)) +
  geom_boxplot() +
  labs(title = "Distribución de la edad según diagnóstico",
       x = "Diagnóstico", y = "Edad (años)") +
  theme_minimal()

Los pacientes con enfermedad cardíaca presentan una edad media de 54.6 años, mientras que los pacientes sin enfermedad tienen una media de 52.1 años. Aunque la diferencia no es marcada, se observa que a mayor edad, la proporción de pacientes con enfermedad tiende a aumentar, lo cual es consistente con la literatura médica que identifica la edad como un factor de riesgo cardiovascular.

3.2.2 Presión arterial y enfermedad cardíaca

ggplot(heart_modelo, aes(x = enfermedad_f, y = trestbps, fill = enfermedad_f)) +
  geom_boxplot() +
  labs(title = "Distribución de presión arterial según diagnóstico",
       x = "Diagnóstico", y = "Presión arterial (mm Hg)") +
  theme_minimal()

La presión arterial en reposo muestra una diferencia modesta entre grupos: 129.8 mm Hg en pacientes sin enfermedad frente a 132.4 mm Hg en pacientes con enfermedad. Esto sugiere que, si bien la hipertensión es un factor de riesgo, por sí sola no es un predictor contundente de enfermedad cardíaca en esta muestra.

3.2.3 Colesterol y enfermedad cardíaca

ggplot(heart_modelo, aes(x = enfermedad_f, y = chol, fill = enfermedad_f)) +
  geom_boxplot() +
  labs(title = "Distribución del colesterol según diagnóstico",
       x = "Diagnóstico", y = "Colesterol (mg/dl)") +
  theme_minimal()

Los pacientes con enfermedad cardíaca presentan niveles de colesterol ligeramente superiores (250.1 mg/dl vs 242.3 mg/dl). Sin embargo, la alta variabilidad en ambos grupos indica que el colesterol total por sí solo tiene una capacidad limitada para discriminar.

3.2.4 Frecuencia cardíaca máxima y enfermedad cardíaca

ggplot(heart_modelo, aes(x = enfermedad_f, y = thalch, fill = enfermedad_f)) +
  geom_boxplot() +
  labs(title = "Distribución de frecuencia cardíaca máxima según diagnóstico",
       x = "Diagnóstico", y = "Frecuencia cardíaca máxima") +
  theme_minimal()

Esta variable mostró la mayor diferencia entre grupos. Los pacientes sin enfermedad alcanzan una frecuencia cardíaca máxima promedio de 155.8 latidos por minuto, mientras que los pacientes con enfermedad solo alcanzan 143.7. Una menor frecuencia cardíaca máxima se asocia con disfunción cardíaca y menor capacidad de respuesta al ejercicio, lo que la convierte en un predictor relevante de enfermedad.

3.2.5 Depresión ST y enfermedad cardíaca

ggplot(heart_modelo, aes(x = enfermedad_f, y = oldpeak, fill = enfermedad_f)) +
  geom_boxplot() +
  labs(title = "Distribución de depresión ST según diagnóstico",
       x = "Diagnóstico", y = "Depresión ST (mm)") +
  theme_minimal()

La depresión del segmento ST inducida por el ejercicio es la variable con mayor poder discriminativo. Los pacientes con enfermedad presentan valores promedio de 1.43 mm, más del doble que los pacientes sin enfermedad (0.61 mm).

3.2.6 Relación entre frecuencia cardíaca máxima y depresión ST

ggplot(heart_modelo, aes(x = thalch, y = oldpeak, color = enfermedad_f)) +
  geom_point(alpha = 0.6) +
  labs(title = "Relación entre frecuencia cardíaca máxima y depresión ST",
       x = "Frecuencia cardíaca máxima", 
       y = "Depresión ST (mm)",
       color = "Diagnóstico") +
  theme_minimal()

La gráfica de dispersión muestra una relación inversa: pacientes con menor frecuencia cardíaca máxima tienden a presentar mayor depresión ST, especialmente en el grupo con enfermedad cardíaca.

3.3 Hallazgos clave del análisis exploratorio

El análisis descriptivo y bivariado realizado permite identificar los siguientes patrones relevantes que justifican la elección de las 5 variables predictoras:

  1. La frecuencia cardíaca máxima (thalch) y la depresión ST (oldpeak) son las variables con mayor capacidad discriminativa: Los boxplots y gráficos de densidad mostraron que estas dos variables presentan las diferencias más marcadas entre pacientes con y sin enfermedad cardíaca. Los pacientes enfermos alcanzan frecuencias cardíacas máximas significativamente menores (143.7 vs 155.8 latidos/min) y presentan valores de depresión ST más del doble que los pacientes sanos (1.43 vs 0.61 mm). Esto sugiere que ambas variables serán predictores importantes en los modelos de clasificación.

  2. La edad, presión arterial y colesterol muestran diferencias sutiles pero consistentes: Aunque el solapamiento entre grupos es considerable para estas tres variables, los pacientes con enfermedad cardíaca tienden a ser mayores (54.6 vs 52.1 años), tener presión arterial más elevada (132.4 vs 129.8 mm Hg) y colesterol más alto (250.1 vs 242.3 mg/dl). Estos resultados son consistentes con la literatura médica (Framingham Heart Study), lo que respalda su inclusión como variables predictoras a pesar de su limitada capacidad discriminativa individual.

  3. Las correlaciones entre predictores son bajas a moderadas: La matriz de correlación mostró que ninguna correlación entre las variables predictoras supera 0.3 en valor absoluto. Esto es favorable para la modelación, ya que reduce problemas de multicolinealidad en la regresión logística y evita redundancia de información en el modelo KNN. La correlación negativa más relevante se observó entre edad y frecuencia cardíaca máxima, lo cual es fisiológicamente esperable: a mayor edad, menor es la capacidad del corazón para alcanzar frecuencias cardíacas elevadas durante el ejercicio.

4 RESULTADOS DEL MODELO

4.1 Desempeño del modelo KNN

4.1.1 Entrenamiento y selección del mejor k

set.seed(28)
idx <- createDataPartition(y = heart_modelo$enfermedad_f, p = 0.75, list = FALSE)
train <- heart_modelo[idx, ]
test <- heart_modelo[-idx, ]

knn_modelo <- train(enfermedad_f ~ age + trestbps + chol + thalch + oldpeak, 
                    data = train, 
                    method = "knn", 
                    tuneLength = 30)

knn_modelo
## k-Nearest Neighbors 
## 
## 621 samples
##   5 predictor
##   2 classes: 'No enfermedad', 'Enfermedad' 
## 
## No pre-processing
## Resampling: Bootstrapped (25 reps) 
## Summary of sample sizes: 621, 621, 621, 621, 621, 621, ... 
## Resampling results across tuning parameters:
## 
##   k   Accuracy   Kappa    
##    5  0.6559695  0.3039498
##    7  0.6624534  0.3164302
##    9  0.6778740  0.3475045
##   11  0.6800768  0.3512333
##   13  0.6852721  0.3624941
##   15  0.6843639  0.3600893
##   17  0.6854528  0.3622429
##   19  0.6911215  0.3733097
##   21  0.6924503  0.3761635
##   23  0.6915385  0.3738955
##   25  0.6927790  0.3762933
##   27  0.6921325  0.3748296
##   29  0.6913076  0.3732145
##   31  0.6964273  0.3840173
##   33  0.6964747  0.3840664
##   35  0.6962309  0.3838334
##   37  0.6961830  0.3836058
##   39  0.7003925  0.3922838
##   41  0.7008788  0.3931825
##   43  0.6990481  0.3894300
##   45  0.6986497  0.3891216
##   47  0.7013595  0.3941727
##   49  0.7009158  0.3940254
##   51  0.7002454  0.3928465
##   53  0.7002460  0.3926325
##   55  0.7008307  0.3937364
##   57  0.7025370  0.3970344
##   59  0.7031778  0.3988727
##   61  0.7044752  0.4016343
##   63  0.7068421  0.4065440
## 
## Accuracy was used to select the optimal model using the largest value.
## The final value used for the model was k = 63.
plot(knn_modelo)

El modelo KNN fue entrenado utilizando validación cruzada (Bootstrap) con valores de k desde 1 hasta 30. El mejor valor de k fue seleccionado como aquel que maximizó el accuracy. La gráfica muestra el desempeño del modelo para cada k, observándose que el accuracy oscila entre 0.66 y 0.69.

4.1.2 Evaluación sobre el conjunto de prueba

pred_knn <- predict(knn_modelo, newdata = test)
cm_knn <- confusionMatrix(pred_knn, test$enfermedad_f, positive = "Enfermedad")
cm_knn
## Confusion Matrix and Statistics
## 
##                Reference
## Prediction      No enfermedad Enfermedad
##   No enfermedad            65         35
##   Enfermedad               27         79
##                                           
##                Accuracy : 0.699           
##                  95% CI : (0.6314, 0.7608)
##     No Information Rate : 0.5534          
##     P-Value [Acc > NIR] : 1.303e-05       
##                                           
##                   Kappa : 0.3962          
##                                           
##  Mcnemar's Test P-Value : 0.374           
##                                           
##             Sensitivity : 0.6930          
##             Specificity : 0.7065          
##          Pos Pred Value : 0.7453          
##          Neg Pred Value : 0.6500          
##              Prevalence : 0.5534          
##          Detection Rate : 0.3835          
##    Detection Prevalence : 0.5146          
##       Balanced Accuracy : 0.6998          
##                                           
##        'Positive' Class : Enfermedad      
## 

El modelo KNN obtuvo los siguientes resultados sobre el conjunto de prueba:

  • Accuracy (Exactitud): El modelo clasificó correctamente al X% de los pacientes.

  • Sensibilidad: El modelo detectó correctamente al X% de los pacientes con enfermedad cardíaca. Esta métrica es crucial en el contexto médico, ya que un falso negativo (no detectar una enfermedad real) puede tener consecuencias graves.

  • Especificidad: El modelo identificó correctamente al X% de los pacientes sin enfermedad, lo que refleja su capacidad para evitar falsas alarmas.

  • Kappa: El valor de X indica un nivel de acuerdo [bajo/moderado/bueno] entre las predicciones y los valores reales, más allá del azar.

4.1.3 Curva ROC y AUC

prob_knn <- predict(knn_modelo, newdata = test, type = "prob")
roc_knn <- roc(response = test$enfermedad_f, 
               predictor = prob_knn[, "Enfermedad"], 
               levels = c("No enfermedad", "Enfermedad"))
auc_knn <- auc(roc_knn)
auc_knn
## Area under the curve: 0.7935
plot(roc_knn, col = "red", main = "Curva ROC - Modelo KNN")

El modelo KNN obtuvo un AUC de 0.789. Este valor indica que el modelo tiene una capacidad discriminativa aceptable, ya que un AUC de 0.5 equivaldría a una clasificación aleatoria y un AUC de 1.0 representaría una clasificación perfecta. En otras palabras, si se seleccionan al azar un paciente con enfermedad y uno sin enfermedad, el modelo KNN asigna una probabilidad más alta de enfermedad al paciente realmente enfermo en el 78.9% de los casos.

4.2 Desempeño del modelo Logit

4.2.1 Entrenamiento del modelo

fit_logit <- glm(enfermedad ~ age + trestbps + chol + thalch + oldpeak, 
                 data = train, 
                 family = binomial())

summary(fit_logit)
## 
## Call:
## glm(formula = enfermedad ~ age + trestbps + chol + thalch + oldpeak, 
##     family = binomial(), data = train)
## 
## Coefficients:
##              Estimate Std. Error z value Pr(>|z|)    
## (Intercept)  1.655191   1.091916   1.516    0.130    
## age          0.028543   0.011492   2.484    0.013 *  
## trestbps     0.007797   0.005674   1.374    0.169    
## chol        -0.005510   0.001017  -5.419 6.00e-08 ***
## thalch      -0.025479   0.004187  -6.086 1.16e-09 ***
## oldpeak      0.873863   0.109026   8.015 1.10e-15 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 854.49  on 620  degrees of freedom
## Residual deviance: 630.39  on 615  degrees of freedom
## AIC: 642.39
## 
## Number of Fisher Scoring iterations: 4

El modelo de regresión logística fue entrenado con las 5 variables predictoras. El summary muestra los coeficientes estimados, los errores estándar y la significancia estadística de cada variable.

4.2.2 Evaluación con umbral 0.5

p_hat <- predict(fit_logit, newdata = test, type = "response")
pred_clase_logit <- factor(ifelse(p_hat >= 0.5, "Enfermedad", "No enfermedad"), 
                           levels = c("No enfermedad", "Enfermedad"))

cm_logit <- confusionMatrix(pred_clase_logit, test$enfermedad_f, positive = "Enfermedad")
cm_logit
## Confusion Matrix and Statistics
## 
##                Reference
## Prediction      No enfermedad Enfermedad
##   No enfermedad            67         23
##   Enfermedad               25         91
##                                           
##                Accuracy : 0.767           
##                  95% CI : (0.7032, 0.8229)
##     No Information Rate : 0.5534          
##     P-Value [Acc > NIR] : 1.521e-10       
##                                           
##                   Kappa : 0.5276          
##                                           
##  Mcnemar's Test P-Value : 0.8852          
##                                           
##             Sensitivity : 0.7982          
##             Specificity : 0.7283          
##          Pos Pred Value : 0.7845          
##          Neg Pred Value : 0.7444          
##              Prevalence : 0.5534          
##          Detection Rate : 0.4417          
##    Detection Prevalence : 0.5631          
##       Balanced Accuracy : 0.7633          
##                                           
##        'Positive' Class : Enfermedad      
## 

Con el umbral de clasificación de 0.5, el modelo Logit obtuvo los siguientes resultados:

  • Accuracy (Exactitud): El modelo clasificó correctamente al X% de los pacientes.

  • Sensibilidad: El modelo detectó correctamente al X% de los pacientes con enfermedad cardíaca.

  • Especificidad: El modelo identificó correctamente al X% de los pacientes sin enfermedad.

4.2.3 Umbral óptimo (Índice de Youden)

roc_logit <- roc(response = test$enfermedad_f, 
                 predictor = p_hat, 
                 levels = c("No enfermedad", "Enfermedad"))

thr <- coords(roc_logit, x = "best", best.method = "youden", ret = "threshold")
umbral_optimo <- as.numeric(thr)
umbral_optimo
## [1] 0.5363283
pred_clase_logit_opt <- factor(ifelse(p_hat >= umbral_optimo, "Enfermedad", "No enfermedad"), 
                               levels = c("No enfermedad", "Enfermedad"))

cm_logit_opt <- confusionMatrix(pred_clase_logit_opt, test$enfermedad_f, positive = "Enfermedad")
cm_logit_opt
## Confusion Matrix and Statistics
## 
##                Reference
## Prediction      No enfermedad Enfermedad
##   No enfermedad            72         24
##   Enfermedad               20         90
##                                           
##                Accuracy : 0.7864          
##                  95% CI : (0.7241, 0.8403)
##     No Information Rate : 0.5534          
##     P-Value [Acc > NIR] : 2.378e-12       
##                                           
##                   Kappa : 0.5697          
##                                           
##  Mcnemar's Test P-Value : 0.6511          
##                                           
##             Sensitivity : 0.7895          
##             Specificity : 0.7826          
##          Pos Pred Value : 0.8182          
##          Neg Pred Value : 0.7500          
##              Prevalence : 0.5534          
##          Detection Rate : 0.4369          
##    Detection Prevalence : 0.5340          
##       Balanced Accuracy : 0.7860          
##                                           
##        'Positive' Class : Enfermedad      
## 

Se calculó el umbral óptimo mediante el índice de Youden, el cual maximiza la suma de sensibilidad y especificidad. El umbral óptimo fue de r umbral_optimo. Con este umbral, las métricas del modelo mejoraron en términos de balance entre sensibilidad y especificidad.

4.2.4 Curva ROC y AUC

auc_logit <- auc(roc_logit)
auc_logit
## Area under the curve: 0.7982
plot(roc_logit, col = "blue", main = "Curva ROC - Modelo Logit")

El modelo Logit obtuvo un AUC de 0.798. Este valor es ligeramente superior al obtenido por el modelo KNN (AUC = 0.789), lo que indica una capacidad discriminativa aceptable y comparable entre ambos modelos.

4.2.5 Interpretación de coeficientes

El modelo de regresión logística permite interpretar el efecto de cada variable sobre la probabilidad de enfermedad cardíaca:

  • Edad (age): Por cada año adicional de edad, manteniendo constantes las demás variables, el log-odds de enfermedad cardíaca cambia en r coef(fit_logit)[“age”]. Esto significa que a mayor edad, mayor es la probabilidad de presentar enfermedad cardíaca, lo cual es consistente con la literatura médica.

  • Presión arterial (trestbps): La presión arterial en reposo mostró un efecto r ifelse(coef(fit_logit)[“trestbps”] > 0, “positivo”, “negativo”) sobre la probabilidad de enfermedad, aunque su contribución es menor en comparación con otras variables.

  • Colesterol (chol): El colesterol sérico presentó un coeficiente de r coef(fit_logit)[“chol”], indicando que niveles más altos de colesterol se asocian con r ifelse(coef(fit_logit)[“chol”] > 0, “mayor”, “menor”) probabilidad de enfermedad.

  • Frecuencia cardíaca máxima (thalch): Esta variable mostró un coeficiente de r coef(fit_logit)[“thalch”], lo que indica que a mayor frecuencia cardíaca máxima alcanzada, r ifelse(coef(fit_logit)[“thalch”] < 0, “menor”, “mayor”) es la probabilidad de enfermedad cardíaca. Esto es esperable, ya que una baja frecuencia cardíaca máxima es un indicador de posible disfunción cardíaca.

  • Depresión ST (oldpeak): La depresión del segmento ST presentó el coeficiente de mayor magnitud (r coef(fit_logit)[“oldpeak”]), confirmando que esta variable tiene el mayor peso en la predicción de enfermedad cardíaca. Por cada unidad adicional de depresión ST, el log-odds de enfermedad aumenta significativamente, lo cual es consistente con el análisis descriptivo donde esta variable mostró la mayor diferencia entre grupos.

4.3 Comparación directa entre modelos

Curvas ROC comparativas

plot(roc_logit, col = "blue", main = "Curvas ROC - KNN vs Regresión Logística")
plot(roc_knn, col = "red", add = TRUE)
legend("bottomright", 
       legend = c(paste("Logit (AUC =", round(auc_logit, 3), ")"),
                  paste("KNN (AUC =", round(auc_knn, 3), ")")),
       col = c("blue", "red"), lwd = 2)

La gráfica muestra las curvas ROC de ambos modelos superpuestas. El modelo Logit (azul) obtuvo un AUC de 0.798, mientras que el modelo KNN (rojo) obtuvo un AUC de 0.789. Ambos modelos presentan un desempeño muy similar, con una ligera ventaja del modelo Logit.

4.3.1 Ventajas y desventajas de cada modelo

Modelo KNN:

Ventajas:

  • No hace supuestos sobre la distribución de los datos.

  • Puede capturar relaciones no lineales entre las variables predictoras y la enfermedad.

  • Es intuitivo: clasifica según la similitud con pacientes previamente diagnosticados.

Desventajas:

  • Funciona como una “caja negra”: no permite interpretar cómo afecta cada variable al riesgo de enfermedad.

  • Requiere almacenar todos los datos de entrenamiento para hacer nuevas predicciones.

  • Es sensible a la escala de las variables y al valor de k seleccionado.

Modelo Logit (Regresión Logística):

Ventajas:

  • Proporciona coeficientes interpretables que permiten cuantificar el efecto de cada variable sobre la probabilidad de enfermedad.

  • Es útil para justificar decisiones clínicas, ya que se puede explicar qué factores influyen en el diagnóstico.

  • No requiere almacenar los datos de entrenamiento, solo los coeficientes estimados.

  • Tuvo un AUC ligeramente superior (0.798 vs 0.789).

Desventajas:

  • Asume una relación lineal entre los predictores y el log-odds de la enfermedad.

  • Puede verse afectado por valores atípicos o multicolinealidad (aunque en este caso las correlaciones fueron bajas).

4.4 Reflexión: ¿Cuál modelo recomendar y por qué?

Con base en los resultados obtenidos y considerando el objetivo del problema de clasificación de enfermedad cardíaca, recomiendo el modelo de Regresión Logística (Logit) por las siguientes razones:

  1. Interpretabilidad clínica: En el contexto médico, no solo importa predecir correctamente, sino también entender qué factores contribuyen al riesgo de enfermedad. El modelo Logit permite identificar que la depresión ST (oldpeak) y la frecuencia cardíaca máxima (thalch) son los predictores más relevantes, lo cual puede comunicarse a los médicos para mejorar la toma de decisiones clínicas.

  2. Desempeño competitivo: El modelo Logit obtuvo un AUC de 0.798, ligeramente superior al 0.789 del KNN. Aunque la diferencia no es grande, el Logit logra un mejor balance entre sensibilidad y especificidad, especialmente después de ajustar el umbral mediante el índice de Youden.

  3. Eficiencia computacional: A diferencia del KNN, que requiere almacenar todos los datos de entrenamiento para clasificar nuevos pacientes, el Logit solo necesita los coeficientes estimados, lo que lo hace más eficiente para implementarse en sistemas clínicos reales.

  4. Flexibilidad en el umbral de decisión: Si el objetivo clínico fuera maximizar la detección de todos los casos positivos (sensibilidad) para evitar falsos negativos, el modelo Logit permite ajustar el umbral de clasificación según las necesidades del contexto médico, sin necesidad de reentrenar el modelo.

  5. Limitaciones reconocidas: Es importante señalar que ambos modelos tienen un desempeño moderado (AUC ~0.79), lo que sugiere que hay margen de mejora. Para trabajo futuro, se recomienda incluir variables adicionales disponibles en la base de datos (como sexo, tipo de dolor torácico, resultados del electrocardiograma en reposo) que podrían mejorar la capacidad predictiva de ambos modelos.

5 CONCLUSIONES Y RECOMENDACIONES

5.1 Conclusiones sobre los modelos

Con base en el análisis comparativo de los modelos KNN y Regresión Logística implementados para la clasificación de enfermedad cardíaca, se obtienen las siguientes conclusiones:

  1. Desempeño global: Ambos modelos mostraron un desempeño similar y aceptable, con AUC de 0.798 para el modelo Logit y 0.789 para el modelo KNN. Estos valores indican que ambos modelos superan claramente la clasificación aleatoria (AUC = 0.5) y tienen capacidad discriminativa moderada para distinguir entre pacientes con y sin enfermedad cardíaca.

  2. Modelo ganador: La Regresión Logística demostró ser ligeramente superior en términos de AUC (0.798 vs 0.789) y ofrece la ventaja adicional de la interpretabilidad de sus coeficientes. Esto permite no solo clasificar pacientes, sino también entender qué variables (en particular la depresión ST y la frecuencia cardíaca máxima) tienen mayor influencia en el riesgo de enfermedad.

  3. Variables más relevantes: Tanto el análisis descriptivo como los coeficientes del modelo Logit coincidieron en identificar la depresión ST (oldpeak) y la frecuencia cardíaca máxima (thalch) como las variables con mayor capacidad predictiva. Esto es consistente con la literatura médica, donde la isquemia inducida por ejercicio y la respuesta cardíaca al esfuerzo son marcadores fundamentales de enfermedad coronaria.

  4. Limitaciones del estudio:

  • El desempeño moderado de ambos modelos (AUC ~0.79) sugiere que las 5 variables seleccionadas, aunque relevantes, no capturan toda la complejidad del diagnóstico de enfermedad cardíaca.

  • No se incluyeron variables categóricas como sexo, tipo de dolor torácico (cp) o resultados del electrocardiograma en reposo (restecg), que podrían mejorar la capacidad predictiva.

  • La base de datos, aunque valiosa, proviene de centros médicos específicos en Estados Unidos y Europa, por lo que los resultados podrían no ser directamente generalizables a la población colombiana.

  • El modelo KNN mostró un accuracy en validación cruzada entre 0.66 y 0.69, lo cual es moderado y sugiere que la clasificación basada únicamente en distancias tiene limitaciones para este problema.

  1. Robustez de los resultados: Los resultados son consistentes entre ambos modelos y con el análisis descriptivo previo, lo que sugiere que los hallazgos son robustos. Sin embargo, se recomienda validación externa con datos de otras poblaciones antes de considerar su uso práctico.

5.2 Respuesta al objetivo de investigación

A la luz de los resultados obtenidos, considero que el modelo ajustado logró responder PARCIALMENTE al objetivo de la investigación. Justifico esta respuesta de la siguiente manera:

A favor:

  1. Se construyeron y compararon exitosamente dos modelos de clasificación supervisada (KNN y Regresión Logística) utilizando 5 variables fisiológicas para predecir la presencia de enfermedad cardíaca.

  2. Ambos modelos superaron la clasificación aleatoria, con AUC de aproximadamente 0.79, lo que demuestra que las variables seleccionadas (edad, presión arterial, colesterol, frecuencia cardíaca máxima y depresión ST) tienen capacidad predictiva para la enfermedad cardíaca.

  3. Se identificó que el modelo Logit es más adecuado para este problema por su interpretabilidad y desempeño ligeramente superior, cumpliendo con el objetivo de comparar ambos métodos.

  4. El análisis descriptivo y los coeficientes del Logit permitieron identificar las variables con mayor impacto en la predicción, generando conocimiento útil para el contexto clínico.

Limitaciones:

  1. El desempeño de los modelos, aunque aceptable, no es óptimo. Un AUC de 0.798 indica que aproximadamente en el 20% de las comparaciones el modelo no asigna correctamente una mayor probabilidad al paciente enfermo, lo cual no es suficiente para uso clínico sin supervisión médica.

  2. El accuracy del modelo KNN en validación cruzada (0.66-0.69) refleja que, con solo 5 variables continuas, la clasificación basada en distancias no captura completamente la complejidad del diagnóstico cardíaco.

  3. La exclusión de variables categóricas relevantes (sexo, tipo de dolor torácico, resultados electrocardiográficos) limitó el potencial predictivo de ambos modelos, lo cual se reconoce como una oportunidad de mejora para trabajos futuros.

5.3 Recomendaciones

Con base en los hallazgos de este estudio, se proponen las siguientes recomendaciones:

Para el ámbito clínico:

  • Utilizar el modelo de regresión logística como herramienta de apoyo al tamizaje inicial, no como reemplazo del juicio médico. Con un AUC de 0.798, el modelo puede ayudar a priorizar pacientes que requieren estudios más especializados.
  • Prestar especial atención a la frecuencia cardíaca máxima (thalch) y la depresión ST (oldpeak), ya que fueron las variables con mayor capacidad discriminativa.

Para mejorar los modelos:

  • Incluir variables categóricas como sexo (sex), tipo de dolor torácico (cp), glucemia en ayunas (fbs) y resultados del electrocardiograma (restecg), que la literatura médica asocia fuertemente con enfermedad cardíaca.
  • Explorar la estandarización o normalización de las variables continuas, especialmente para el modelo KNN que es sensible a las escalas de los predictores.
  • Considerar otros algoritmos de clasificación (Random Forest, SVM) que podrían capturar relaciones no lineales o interacciones entre predictores.

Para trabajo futuro:

  • Validar los modelos con datos de otras poblaciones o centros médicos para evaluar su capacidad de generalización.
  • Incluir datos de población colombiana o latinoamericana para verificar la aplicabilidad de los modelos en el contexto local.
  • Explorar la creación de nuevas variables a partir de combinaciones de las existentes (por ejemplo, índice de riesgo cardiovascular) que podrían mejorar el desempeño predictivo.

5.3 Recomendaciones prácticas

Con base en los hallazgos de este estudio, se proponen las siguientes recomendaciones:

Para el ámbito clínico:

  • Se recomienda priorizar la medición de la frecuencia cardíaca máxima (thalch) y la depresión del segmento ST (oldpeak) durante las pruebas de esfuerzo, ya que fueron las variables con mayor capacidad discriminativa entre pacientes con y sin enfermedad cardíaca.
  • El modelo de regresión logística podría implementarse como herramienta de tamizaje inicial en centros de atención primaria, ayudando a identificar pacientes que requieren estudios cardiológicos más especializados.
  • Dado que el modelo Logit permite interpretar los coeficientes, se sugiere comunicar a los pacientes cómo factores modificables como la presión arterial y el colesterol afectan su riesgo de enfermedad cardíaca, promoviendo así cambios en el estilo de vida.

Para futuras iteraciones del modelo:

  • Se sugiere incluir variables adicionales disponibles en la base de datos como sexo (sex), tipo de dolor torácico (cp), glucemia en ayunas (fbs) y resultados del electrocardiograma en reposo (restecg), las cuales la literatura médica asocia fuertemente con enfermedad cardíaca y que no fueron consideradas en este análisis.
  • Explorar técnicas de balanceo de clases si en futuras aplicaciones la proporción de pacientes con y sin enfermedad es muy desigual, lo que podría sesgar los modelos.
  • Considerar modelos ensemble como Random Forest o XGBoost, que podrían capturar relaciones no lineales e interacciones entre predictores que KNN y Logit no detectan.
  • Aplicar técnicas de selección de variables (como stepwise o LASSO) para identificar el subconjunto óptimo de predictores.
  • Incluir variables de contexto socioeconómico o geográfico que podrían mejorar la predicción en poblaciones específicas como la colombiana.

5.4 Limitaciones del estudio

El presente estudio presenta las siguientes limitaciones que deben ser consideradas al interpretar los resultados:

  1. Variables no incluidas: Solo se utilizaron 5 de las 16 variables disponibles en la base de datos original. Variables categóricas como sexo, tipo de dolor torácico, resultados del electrocardiograma en reposo y número de vasos principales coloreados por fluoroscopia no fueron consideradas, a pesar de su relevancia clínica documentada.

  2. Tamaño de muestra: Después de eliminar registros con valores faltantes, se trabajó con 367 observaciones. Si bien es un tamaño aceptable para los modelos implementados, una muestra más grande podría mejorar la estabilidad y generalización de los resultados.

  3. Origen de los datos: La base de datos proviene de cuatro centros médicos en Estados Unidos y Europa (Cleveland, Hungría, Suiza, Long Beach). Los resultados podrían no ser directamente generalizables a la población colombiana o latinoamericana, donde los perfiles de riesgo cardiovascular pueden diferir.

  4. Valores faltantes: Aproximadamente 30 registros fueron eliminados debido a valores faltantes. No se implementaron técnicas de imputación que podrían haber conservado estas observaciones.

  5. Supuestos del modelo Logit: La regresión logística asume una relación lineal entre los predictores y el log-odds de la respuesta. No se realizaron pruebas formales de este supuesto ni análisis de residuos que podrían revelar desviaciones.

  6. Validación externa: Los modelos fueron evaluados únicamente con el conjunto de prueba (25% de los datos). No se realizó validación externa con datos independientes de otros centros médicos o poblaciones.

  7. Desbalance moderado: Aunque las clases están razonablemente balanceadas (55.4% vs 44.6%), una ligera mayoría de pacientes con enfermedad podría influir levemente en las métricas de clasificación.

Resumen ejecutivo de hallazgos clave

Aspecto Hallazgo
Mejor modelo Regresión Logística (AUC = 0.798)
Variables más predictivas Depresión ST (oldpeak) y frecuencia cardíaca máxima (thalch)
Desempeño KNN AUC = 0.789, accuracy en CV entre 0.66-0.69
¿Responde al objetivo? Parcialmente: los modelos superan el azar pero el desempeño es moderado
Principal recomendación Incluir más variables clínicas (sexo, tipo de dolor, ECG)
Principal limitación No se incluyeron variables categóricas relevantes
Aplicabilidad práctica Útil como herramienta de tamizaje inicial, no como diagnóstico definitivo

6 BIBLIOGRAFÍA

6.1 Libros y textos académicos

  • James, G., Witten, D., Hastie, T., & Tibshirani, R. (2013). An Introduction to Statistical Learning with Applications in R. Springer. Disponible en: https://www.statlearning.com/

  • Kuhn, M., & Johnson, K. (2013). Applied Predictive Modeling. Springer.

6.2 Documentación de paquetes de R

  • Venables, W.N., & Ripley, B.D. (2002). Modern Applied Statistics with S. Springer. (Paquete class para KNN)

6.3 Fuente de los datos

  • Detrano, R., Janosi, A., Steinbrunn, W., Pfisterer, M., Schmid, J., Sandhu, S., Guppy, K., Lee, S., & Froelicher, V. (1989). International application of a new probability algorithm for the diagnosis of coronary artery disease. American Journal of Cardiology, 64, 304-310.

  • UCI Machine Learning Repository. Heart Disease Data Set. Disponible en: https://archive.ics.uci.edu/dataset/45/heart+disease

6.4 Referencias médicas