0.1 Descripción de los Datos

Se trata de un conjunto de datos con el interés, por parte del compilador, de realizar un análisis y predicción de ataques cardíacos. Fue subido por Rashik Rahman hace 3 meses al Kaggle para que se realice un modelo para la clasificación de ataques cardíacos.

0.3 Objetivo

Describir los estados “probabilidad baja de ataque cardiaco” y “probabilidad alta de ataque cardiaco”, además también determinar las condiciones de cambiar de estados.

0.4 Preguntas iniciales:

¿Existe alguna relación entre el sexo y el dolor de pecho después del ejercicio. ¿Existe alguna relación entre el azúcar en la sangre en ayunas y el dolor de pecho después del ejercicio? ¿Existe alguna relación entre las variables numéricas? ¿Existe alguna diferencia notoria entre las edades de las personas, según su probabilidad de ataque cardiaco? ¿Existe alguna angina particular según la probabilidad de ataque cardiaco?

0.5 Descripción de las Variables

Edad: edad del paciente.

Sexo: sexo del paciente(1: hombre, 0: mujer.)

exng: angina inducida por el ejercicio (1 = sí; 0 = no) significa que hay dolor en el pecho después del ejercicio?

ca: número de vasos principales (0-3).

cp: tipo de dolor de pecho tipo de dolor de pecho.

  • Valor 1: angina típica
  • Valor 2: angina atípica
  • Valor 3: dolor no anginoso
  • Valor 4: asintomático

trtbps: presión arterial en reposo (en mm Hg).

chol: colesterol en mg / dl obtenido a través del sensor de IMC.

fbs: (azúcar en sangre en ayunas> 120 mg / dl) (1 = verdadero; 0 = falso).

rest_ecg: resultados electrocardiógrafos en reposo

  • Valor 0: normal
  • Valor 1: tener anomalía de la onda ST-T (inversiones de la onda T y / o elevación o depresión del ST> 0,05 mV)
  • Valor 2: muestra hipertrofia ventricular izquierda probable o definitiva según los criterios de Estes.

oldpeak - Depresión del ST inducida por el ejercicio en relación con el reposo.

thalach: frecuencia cardíaca máxima alcanzada. thal-2 = normal; 1 = defecto fijo; 3 = defecto reversible.

output: 0 = menos probabilidad de ataque cardíaco, 1 = más probabilidad de ataque cardíaco.

0.6 Lectura de los Datos

library(readr)
heart <- read_csv("C:/Users/Andres1/Downloads/Trabajo B1M/data/heart.csv")

head(heart,5)
## # A tibble: 5 x 14
##     age   sex    cp trtbps  chol   fbs restecg thalachh  exng oldpeak   slp
##   <dbl> <dbl> <dbl>  <dbl> <dbl> <dbl>   <dbl>    <dbl> <dbl>   <dbl> <dbl>
## 1    63     1     3    145   233     1       0      150     0     2.3     0
## 2    37     1     2    130   250     0       1      187     0     3.5     0
## 3    41     0     1    130   204     0       0      172     0     1.4     2
## 4    56     1     1    120   236     0       1      178     0     0.8     2
## 5    57     0     0    120   354     0       1      163     1     0.6     2
## # ... with 3 more variables: caa <dbl>, thall <dbl>, output <dbl>

0.7 Estudio de Valores Perdidos

sum(is.na(heart))
## [1] 0

Con lo cual no hay valores faltantes.

0.8 Estudio de Valores Atípicos

boxplot(scale(heart), xlab ="Variables",ylab = "Rango de Valores", col="blue", main="Diagrama de Caja Conjunto para Variables Escaladas")

Con lo cual se ha detectado valores atípicos en las siguientes variables trtbps, chol,fbs,thalachh,oldpeak,caa y thall.

x <- cbind(heart$trtbps,heart$chol,heart$fbs,heart$thalachh,heart$oldpeak,heart$caa,heart$thall);
colnames(x) <- c("trtbps", "chol","fbs","thalachh","oldpeak","caa", "thall")
boxplot(scale(x), xlab ="Variables",
        ylab = "Rango de Valores", col="blue", main="Diagrama de Caja Conjunto para Variables Escaladas"
        )

Para verificar que son realmente atípicos se va a realizar la prueba de Tukey, a cada variable:

library(rapportools)
x <- cbind(heart$trtbps,heart$chol,heart$fbs,heart$thalachh,heart$oldpeak,heart$caa,heart$thall);
colnames(x) <- c("trtbps", "chol","fbs","thalachh","oldpeak","caa", "thall")
nombres <- colnames(x);

matriz_nom <- rep(1,7);
for(i in 1:7)
{
m <- x[,i];
q1 <- quantile(m,0.25);
q3 <- quantile(m,0.75);
  p <- q3-q1;
  ati_tukey <- (m<(q1-1.5*p) | m>(q3+1.5*p));
matriz_nom[i] <- sum(ati_tukey);
}
matriz_nom <- rbind(nombres,matriz_nom)
matriz_nom
##            [,1]     [,2]   [,3]  [,4]       [,5]      [,6]  [,7]   
## nombres    "trtbps" "chol" "fbs" "thalachh" "oldpeak" "caa" "thall"
## matriz_nom "9"      "5"    "45"  "1"        "5"       "25"  "2"

Finalmente se puede comprobar que todas las variables en cuestión tienen atípicos según la prueba de Tukey, de manera que se va a reemplazar los atípicos por la media. Recuérdese que el método de Tukey usa la distancia intercuartílica (DIQ = cuartil 3 menos cuartil 1) y todo punto que se encuentre por debajo del cuartil uno -DIQ es atípico, lo mismo para todo punto que este por encima del cuartil 3+DIQ.

x <- cbind(heart$trtbps,heart$chol,heart$fbs,heart$thalachh,heart$oldpeak,heart$caa,heart$thall);
colnames(x) <- c("trtbps", "chol","fbs","thalachh","oldpeak","caa", "thall")
y <- x;

nombres <- colnames(x);
matriz_nom <- rep(1,7);
for(i in 1:7)
{
m <- x[,i];
q1 <- quantile(m,0.25);
q3 <- quantile(m,0.75);
  p <- q3-q1;
  ati_tukey <- (m<(q1-1.5*p) | m>(q3+1.5*p));
for(j in 1:length(ati_tukey))
{
  med <- mean(x[,i]);
  if(ati_tukey[j]==TRUE)
  {
    y[j,i] <- med;
  }
}
}
boxplot(scale(y), xlab ="Variables",
        ylab = "Rango de Valores", col="blue", main="Diagrama de Caja Conjunto de Variables Escaladas"
        )

Con lo cual ya no tenemos datos atípicos. Finalmente la base de datos queda como:

x <- cbind(heart$trtbps,heart$chol,heart$fbs,heart$thalachh,heart$oldpeak,heart$caa,heart$thall);
colnames(x) <- c("trtbps", "chol","fbs","thalachh","oldpeak","caa", "thall")
y <- x;
heart2 <- cbind(heart[,c(-4,-5,-6,-8,-10,-12,-13)],y)
head(heart2,5)
##   age sex cp restecg exng slp output trtbps chol fbs thalachh oldpeak caa thall
## 1  63   1  3       0    0   0      1    145  233   1      150     2.3   0     1
## 2  37   1  2       1    0   0      1    130  250   0      187     3.5   0     2
## 3  41   0  1       0    0   2      1    130  204   0      172     1.4   0     2
## 4  56   1  1       1    0   2      1    120  236   0      178     0.8   0     2
## 5  57   0  0       1    1   2      1    120  354   0      163     0.6   0     2

0.9 Análisis Descriptivo

De manera que se va a empezar el análisis con la correlación entre las variables:

library(tidyverse)
library(corrplot)
heart2p <- heart2[,c(-14,-13,-6)];
corrplot(cor(heart2p))

Debido a que “cp” es una variable categórica no existe una relación lineal tangible entre las variables.

A continuación se va a dividir los datos en dos partes según la probabilidad de ataque cardiaco:

library(tidyverse)
heart2p <- heart2[,c(-14,-13,-6)];
heartProbBaja <- heart2p[heart2p[,6]==0, ];
heartProbAlta <- heart2p[heart2p[,6]==1, ];

Comparación de Histogramas para la variable Edad:

par(mfrow=c(1,3))
hist(heart2p$age,main="Histograma de la Edad",col="red",
     xlab = " Edad",ylab = " Frecuencia")
hist(heartProbBaja$age,main="Hist: Edad, Baja Probabilidad",col="red",
     xlab = " Edad",ylab = " Frecuencia")
hist(heartProbAlta$age,main="Hist: Edad, Alta Probabilidad",col="red",
     xlab = " Edad",ylab = " Frecuencia")

Se puede notar que existe mayor cantidad de personas con alta probabilidad de ataque cardiaco en personas con edad entre 40 y 45 años. En las demás edades parece no existir una diferencia apreciable.

Sexo del paciente:

par(mfrow=c(1,3))
plot(table(heart2p$sex),main="Sexo",col="blue",
     xlab="Sexo",ylab="Número de personas",type = "h")
plot(table(heartProbBaja$sex),main="Sexo: Prob. baja",col="blue",
     xlab="Sexo",ylab="Número de personas",type = "h")
plot(table(heartProbAlta$sex),main="Sexo: Prob. alta",col="blue",
     xlab="Sexo",ylab="Número de personas",type = "h")

Existe porcentualmente una menor cantidad de mujeres con baja probabilidad de ataque cardiaco en comparación con los hombres.

Comparación de la angina (dolor en el pecho):

par(mfrow=c(1,3))
plot(table(heart2p$cp),main="Tipo de Dolor de Pecho",col="blue",
     xlab="Tipos de angina",ylab="Número de personas",type = "h")
plot(table(heartProbBaja$cp),main="Dolor de Pecho: Prob. baja",col="blue",
     xlab="Tipos de angina",ylab="Número de personas",type = "h")
plot(table(heartProbAlta$cp),main="Dolor de Pecho: Prob. alta",col="blue",
     xlab="Tipos de angina",ylab="Número de personas",type = "h")

Podemos observar una clara característica para cada grupo, en especial para el grupo con baja probabilidad. El tipo de angina para las personas con baja probabilidad es de tipo 1, el cual es un dolor de pecho muy común y para las de alta probabilidad es de tipo 3, el cual se clasifica como dolor no anginoso.

Comparación de “fbs” o azúcar en la sangre en ayunas:

par(mfrow=c(1,3))
plot(table(heart2p$fbs),main="Azucar en la Sangre en Ayunas",col="blue",
     xlab="fbs",ylab="Número de personas",type = "h")
plot(table(heartProbBaja$fbs),main="Prob. baja",col="blue",
     xlab="fbs",ylab="Número de personas",type = "h")
plot(table(heartProbAlta$fbs),main="Prob. alta",col="blue",
     xlab="fbs",ylab="Número de personas",type = "h")

Esta variable parece ser irrelevante en la probabilidad de ataque cardiaco.

Comparación de “rest_ecg”, resultados electrocardiógrafos en reposo:

par(mfrow=c(1,3))
plot(table(heart2p$restecg),main="Resultados elec. en reposo",col="blue",
     xlab="rest_ecg",ylab="Número de personas",type = "h")
plot(table(heartProbBaja$restecg),main="Prob. baja",col="blue",
     xlab="rest_ecg",ylab="Número de personas",type = "h")
plot(table(heartProbAlta$restecg),main="Prob. alta",col="blue",
     xlab="rest_ecg",ylab="Número de personas",type = "h")

Se ve que en personas con probabilidad alta de ataque cardiaco, el patrón normal deja de ser el dominante y cambia para mostrar un electrocardiograma con una anomalía en las ondas ST-T, dichas ondas reflejan la recuperación eléctrica de las células.

Ahora se va a observar, fbs (azúcar en la sangre) vs sexo:

par(mfrow=c(1,3))
plot(table(heart2p$fbs,heart2p$sex),main="Azucar en la Sangre vs Sexo",col="green",
     xlab="fbs",ylab="Número de personas",type = "h")
plot(table(heartProbBaja$fbs,heartProbBaja$sex),main="Prob. baja",col="green",
     xlab="fbs",ylab="Número de personas",type = "h")
plot(table(heartProbAlta$fbs,heartProbAlta$sex),main="Prob. alta",col="green",
     xlab="fbs",ylab="Número de personas",type = "h")

Se puede establecer que en las personas con baja probabilidad de ataque cardiaco, los hombres poseen considerablemente mayor cantidad de azúcar en la sangre que las mujeres.

De manera que, se va a realizar una prueba Ji-Cuadrado, para ver si existe independencia entre los sexos en el nivel de azúcar en la sangre;

Para las personas con baja probabilidad de ataque cardiaco:

library(stats)
chisq.test(table(heartProbBaja$fbs,heartProbBaja$sex))
## Warning in chisq.test(table(heartProbBaja$fbs, heartProbBaja$sex)): Chi-squared
## approximation may be incorrect
## 
##  Pearson's Chi-squared test with Yates' continuity correction
## 
## data:  table(heartProbBaja$fbs, heartProbBaja$sex)
## X-squared = 1.0546, df = 1, p-value = 0.3044

Al haber probabilidad de que la aproximación sea incorrecta se va a usar el test exacto de Fischer:

fisher.test(table(heartProbBaja$fbs,heartProbBaja$sex))
## 
##  Fisher's Exact Test for Count Data
## 
## data:  table(heartProbBaja$fbs, heartProbBaja$sex)
## p-value = 0.2189
## alternative hypothesis: true odds ratio is not equal to 1
## 95 percent confidence interval:
##  0.1550137 1.7477711
## sample estimates:
## odds ratio 
##  0.4927461

Entonces al ser el p, muy alto, para las personas con baja probabilidad de ataque cardiaco, el sexo no infiere en la cantidad de azúcar en la sangre.

Para las personas con alta probabilidad de ataque cardiaco:

chisq.test(table(heartProbAlta$fbs,heartProbAlta$sex))
## 
##  Pearson's Chi-squared test with Yates' continuity correction
## 
## data:  table(heartProbAlta$fbs, heartProbAlta$sex)
## X-squared = 2.5688, df = 1, p-value = 0.109

Debido a que el p-valor es mayor a 0.05 no se rechaza la hipótesis nula de independencia, entonces se puede afirmar que el dolor de pecho varía según el sexo.

Ahora se va a observar el tipo de angina vs sexo:

par(mfrow=c(1,3))
plot(table(heart2p$cp,heart2p$sex),main="Tipo de Dolor de Pecho vs Sexo",col="green",
     xlab="angina",ylab="Número de personas",type = "h")
plot(table(heartProbBaja$cp,heartProbBaja$sex),main="Prob. baja",col="green",
     xlab="angina",ylab="Número de personas",type = "h")
plot(table(heartProbAlta$cp,heartProbAlta$sex),main="Prob. alta",col="green",
     xlab="angina",ylab="Número de personas",type = "h")

Con lo cual se tiene que, en la probabilidad baja, los hombres mayoritariamente poseen angina tipo 1.

Entonces se va a realizar un test ji cuadrado para ver la independencia del dolor de pecho y el sexo de la persona;

Para persona con probabilidad baja:

chisq.test(table(heartProbBaja$cp,heartProbBaja$sex))
## Warning in chisq.test(table(heartProbBaja$cp, heartProbBaja$sex)): Chi-squared
## approximation may be incorrect
## 
##  Pearson's Chi-squared test
## 
## data:  table(heartProbBaja$cp, heartProbBaja$sex)
## X-squared = 3.9429, df = 3, p-value = 0.2677

De manera que se aplica nuevamente el test exacto de Fisher:

fisher.test(table(heartProbBaja$cp,heartProbBaja$sex))
## 
##  Fisher's Exact Test for Count Data
## 
## data:  table(heartProbBaja$cp, heartProbBaja$sex)
## p-value = 0.3033
## alternative hypothesis: two.sided

Entonces al ser el p, muy alto, para las personas con baja probabilidad de ataque cardiaco, el sexo no infiere en el dolor de pecho.

Para personas con alta probabilidad:

chisq.test(table(heartProbAlta$cp,heartProbAlta$sex))
## 
##  Pearson's Chi-squared test
## 
## data:  table(heartProbAlta$cp, heartProbAlta$sex)
## X-squared = 3.6066, df = 3, p-value = 0.3072

Debido a que el p-valor es mayor a 0.05 no se rechaza la hipótesis nula de independencia, entonces se puede afirmar que el dolor de pecho varía según el sexo.

Ahora se va a observar el tipo de restecg (resultados electrocardiógrafos en reposo) vs sexo:

par(mfrow=c(1,3))
plot(table(heart2p$restecg,heart2p$sex),main="Resultados elec. en reposo",col="green",
     xlab="rest_ecg",ylab="Número de personas",type = "h")
plot(table(heartProbBaja$restecg,heartProbBaja$sex),main="Prob. baja",col="green",
     xlab="rest_ecg",ylab="Número de personas",type = "h")
plot(table(heartProbAlta$restecg,heartProbAlta$sex),main="Prob. alta",col="green",
     xlab="rest_ecg",ylab="Número de personas",type = "h")

En la probabilidad baja, los hombres nuevamente son mayoría para resultado de electrocardiograma en reposo de tipo normal y anómala de la onda ST-T.

Entonces se procede a realizar el test Ji-Cuadrado;

Para las personas con baja probabilidad:

chisq.test(table(heartProbBaja$restecg,heartProbBaja$sex))
## Warning in chisq.test(table(heartProbBaja$restecg, heartProbBaja$sex)): Chi-
## squared approximation may be incorrect
## 
##  Pearson's Chi-squared test
## 
## data:  table(heartProbBaja$restecg, heartProbBaja$sex)
## X-squared = 5.1862, df = 2, p-value = 0.07479

Por lo cual se procede a usar el test exacto de Fisher:

fisher.test(table(heartProbBaja$restecg,heartProbBaja$sex))
## 
##  Fisher's Exact Test for Count Data
## 
## data:  table(heartProbBaja$restecg, heartProbBaja$sex)
## p-value = 0.1217
## alternative hypothesis: two.sided

Entonces al ser p-valor, alto, para las personas con baja probabilidad de ataque cardiaco, el sexo no infiere en el electrocardiograma en reposo.

Para las personas con alta probabilidad:

chisq.test(table(heartProbAlta$restecg,heartProbAlta$sex))
## Warning in chisq.test(table(heartProbAlta$restecg, heartProbAlta$sex)): Chi-
## squared approximation may be incorrect
## 
##  Pearson's Chi-squared test
## 
## data:  table(heartProbAlta$restecg, heartProbAlta$sex)
## X-squared = 1.5484, df = 2, p-value = 0.4611

Por lo cual se procede a usar el test exacto de Fisher:

fisher.test(table(heartProbAlta$restecg,heartProbAlta$sex))
## 
##  Fisher's Exact Test for Count Data
## 
## data:  table(heartProbAlta$restecg, heartProbAlta$sex)
## p-value = 0.5167
## alternative hypothesis: two.sided

Entonces al ser el p, muy alto, para las personas con alta probabilidad de ataque cardiaco, el sexo no infiere en el electrocardiograma en reposo.

Se va a ver si el tipo de dolor de pecho tiene alguna relación con el nivel de azúcar en la sangre, para las personas con probabilidad baja:

chisq.test(table(heartProbBaja$cp,heartProbBaja$fbs))
## Warning in chisq.test(table(heartProbBaja$cp, heartProbBaja$fbs)): Chi-squared
## approximation may be incorrect
## 
##  Pearson's Chi-squared test
## 
## data:  table(heartProbBaja$cp, heartProbBaja$fbs)
## X-squared = 0.1908, df = 3, p-value = 0.9791

Por lo cual se va a utilizar el test exacto de Fisher:

fisher.test(table(heartProbBaja$cp,heartProbBaja$fbs))
## 
##  Fisher's Exact Test for Count Data
## 
## data:  table(heartProbBaja$cp, heartProbBaja$fbs)
## p-value = 1
## alternative hypothesis: two.sided

El cual nos muestra que se acepta la independencia, esto es que para las personas con probabilidad baja, el tipo de dolor de pecho no depende de la cantidad de azúcar en la sangre.

Se va a ver si el tipo de dolor de pecho tiene alguna relación con el nivel de azúcar en la sangre, para las personas con probabilidad alta:

chisq.test(table(heartProbAlta$cp,heartProbAlta$fbs))
## Warning in chisq.test(table(heartProbAlta$cp, heartProbAlta$fbs)): Chi-squared
## approximation may be incorrect
## 
##  Pearson's Chi-squared test
## 
## data:  table(heartProbAlta$cp, heartProbAlta$fbs)
## X-squared = 8.756, df = 3, p-value = 0.03272

De manera que se va a usar el test exacto de Fisher:

fisher.test(table(heartProbAlta$cp,heartProbAlta$fbs))
## 
##  Fisher's Exact Test for Count Data
## 
## data:  table(heartProbAlta$cp, heartProbAlta$fbs)
## p-value = 0.0193
## alternative hypothesis: two.sided

Con lo cual se rechaza la hipótesis nula, es decir, para las personas con probabilidad alta de ataque cardiaco, el dolor de pecho no se relaciona con la cantidad de azúcar en la sangre.

0.10 Conclusiones:

  • El tipo de angina para las personas con baja probabilidad es de tipo 1, el cual es un dolor de pecho muy común y para las de alta probabilidad es de tipo 3, el cual se clasifica como dolor no anginoso.
  • En personas con probabilidad alta de ataque cardiaco, el patrón normal deja de ser el dominante y cambia para mostrar un electrocardiograma con una anomalía en las ondas ST-T, dichas ondas reflejan la recuperación eléctrica de las células.
  • Para las personas con baja probabilidad de ataque cardiaco, el sexo no infiere en la cantidad de azúcar en la sangre.
  • Para las personas con probabilidad alta se puede afirmar que el dolor de pecho varía según el sexo.
  • Para las personas con baja probabilidad de ataque cardiaco, el sexo no infiere en el dolor de pecho, esto cambia cuando aumenta la probabilidad.
  • Para las personas con alta y baja probabilidad, el sexo no interfiere en el electrocardiograma en reposo.
  • Para las personas con probabilidad alta y baja de ataque cardiaco, el dolor de pecho no se relaciona con la cantidad de azúcar en la sangre.

0.11 Bibliografía:

Everitt, B., & Hothorn, T. (2011). An introduction to applied multivariate analysis with R. Springer Science & Business Media.

Abedin, J., & Das, K. K. (2015). Data manipulation with R. Packt Publishing Ltd.