Exploración de datos y visualización en R
Sesión III - Práctico
1 Introducción
En el siguiente práctico aplicaremos las técnicas y conceptos que hemos desarrollado en las sesiones I y II teórico-prácticas del taller de visualización y análisis en R, aplicados a estádistica. Para este práctico utilizaremos el set de datos para el análisis de ataque cardíaco llamado heart. El set de datos contiene información sobre 303 pacientes -hombres (207) y mujeres (96)- entre 29 y 77 años, junto a análisis fisiologicos orientados al diagnóstico y estudio de un ataque cardíaco. Realizaremos un análisis exploratorio de datos o EDA para generar preguntas y obtener algunas conclusiones desde nuestro set de datos. Con esa finalidad, al igual que en la sesión II, dividiremos el análisis en dos, según si las estrategias para la visualización y análisis se encuentran más orientadas en la estadística descriptiva (comprender nuestro set de datos) o en la inferencia estadística (testear hipótesis).
2 Análisis exploratorio de datos o EDA
¿Qué es un análisis exploratorio de datos?
Recordemos en que consiste un análisis exploratorio de datos. El análisis exploratorio de datos o “EDA” (por sus siglas en inglés Exploratory Data Analysis), es como se conoce -en estadística- el proceso por el cual un investigador inspecciona un set de datos con la finalidad de generar preguntas, procesar y adquirir conocimiento (procesa datos, genera resultados), y refina o genera nuevas preguntas.
¿Cúal es el proceso iterativo?
- Generar preguntas basandose en los datos.
- Obtener resultados (procesa datos, gráficos, modelos, etc.).
- Refinar preguntas y/o generar nuevas preguntas.
Consideraciones durante el EDA
Recordemos que si bien el nombre puede generar la impresión de un proceso estandarizado, en la práctica no hay reglas que limiten los análisis o técnicas utilizadas para generar el proceso iterativo. Sin embargo, existen análisis que se vuelven recurrentes durante el proceso.
John Tukey
2.1 Requisitos de nuestro análisis
Acá podrás encontrar todas las librerías que utilizaremos en nuestro análisis. Recuerda que es necesario que se encuentren instaladas en tú sesión de R y que al comenzar el análsis le digas a R que tiene que cargar esas librerías en la memoría y así permitir el uso de sus funciones.
# El primer paso será cargar las librerías que usaremos en el análisis.
# En caso de que no las hayas instalado aún, primero deberas descomentar
# "eliminar el # a la izquierda de source(...)" y correr el siguiente comando:
#source("https://tamayoleivaj.github.io/Dataviz_R_PUCV_2021/Dataviz_R_PUCV_2021.R")
library(tidyverse)
library(RColorBrewer)
library(gtsummary)
library(Hmisc)
library(corrplot)
library(ggpubr)
library(patchwork)
2.2 El set de datos heart
Como mencionamos anteriormente en nuestra sesión III utilizaremos el set de datos para el análisis de ataque cardíaco llamado heart. En este set encontraremos información sobre 303 pacientes -hombres (207) y mujeres (96)- con edades entre los 29 y 77 años. Sin embargo, el set de datos heart también cuenta con información asociada a cada paciente, como el dolor de angina un tipo de dolor de pecho ocasionado por una disminución de la irrigación sanguínea al corazón. Además del tipo de angina, tendremos que investigar como otras variables contenidas en el set de datos pueden ser utilizadas para estudio de un ataque cardíaco. A continuación se describe como cargar el set de datos en tú sesión de R y una descripción de la información contenida en el set de datos heart.
2.2.1 Cargar el set de datos
A continuación podrán descargar el set de datos heart en dos formatos -csv comma-separated values y/o rds R data serialized-. El formato csv es un formato de texto plano donde los datos se encuentran separados en columnas mediante comas “,”, mientras que el formato rds es propio de R y tiene las ventajas de a) estar comprímido (“gzip”) y b) tener mayor compatibilidad, lo que permitirá realizar el práctico independiente del sistema operativo en su computador o su configuración local.
¿Cómo cargar los datos en mi sesión de R?
Opción A) Si descargas el “heart.csv” la función que debes ocupar es la siguiente:
Opción B) Si descargas el “heart.rds” la función que debes ocupar es la siguiente:
2.2.2 Información sobre el set de datos
- age : Edad del paciente
- sex : Sexo del paciente (Mujer; Hombre)
- cp : Tipo de dolor de pecho (angina)
- Value 0: asintomático
- Value 1: angina típica
- Value 2: angina atípica
- Value 3: dolor no anginoso
- Value 0: asintomático
- trtbps : Presión arterial en reposo (en mm Hg al ingreso en el hospital)
- chol : Colesterol en mg/dl obtenido a través del sensor de IMC
- fbs : (azúcar en sangre en ayunas >120 mg/dl) (1 = true; 0 = false)
- restecg : Resultados electrocardiográficos en reposo.
- Value 0: Normal
- Value 1: Anomalía de la onda ST-T (inversiones de la onda T y / o elevación o depresión del ST de> 0,05 mV)
- Value 2: Muestra hipertrofia ventricular izquierda probable o definitiva según los criterios de Estes.
- Value 0: Normal
- thalach : Frecuencia cardíaca máxima alcanzada.
- exng : Angina inducida por ejercicio (1 = si; 0 = no).
- oldpeak : Depresión del ST inducida por el ejercicio en relación con el reposo.
- slp : Pendiente del segmento ST de ejercicio máximo.
- Value 0: descendente
- Value 1: plano
- Value 2: ascendente
- Value 0: descendente
- caa : Número de vasos principales (0-4) coloreados por fluoroscopia.
- thall: Frecuencia cardíaca ritmo.
- Value 1: defecto fijo
- Value 2: normal
- Value 3: defecto reversible
- Value 1: defecto fijo
- output : 0 = menos probabilidad de ataque cardíaco. 1 = más probabilidad de ataque cardíaco
Sobre la base de las variables contenidas en el set de datos heart, ya podríamos dirigir el análisis hacia aquellas variables que son intuitivamente más relevante en el diagnóstico de un ataque al corazón. Podríamos generar algunas de las siguientes preguntas:
- ¿Cuáles son las variables más importantes de nuestro análisis?
- ¿Cómo se relaciona la edad (age) del paciente con un ataque al corazón?
- ¿Cómo se relaciona el sexo (sex) del paciente con un ataque al corazón?
- ¿Cómo se relaciona el colesterol (chol) del paciente con un ataque al corazón?
- ¿Cómo se relaciona la presión arterial en reposo (trtbps) o la frecuencia cardíaca máxima alcanzada (thalach) del paciente con un ataque al corazón?
3 Estadística descriptiva
3.1 Tablas de resumen
Pero antes de resolver estas preguntas, lo primero que haremos será realizar un pequeño análisis descriptivo de los valores contenidos en las variables continuas del set de datos heart. Las variables serán seleccionadas con la función select(...)
.
age trtbps chol fbs
Min. :29.00 Min. : 94.0 Min. :126.0 Min. :0.0000
1st Qu.:47.50 1st Qu.:120.0 1st Qu.:211.0 1st Qu.:0.0000
Median :55.00 Median :130.0 Median :240.0 Median :0.0000
Mean :54.37 Mean :131.6 Mean :246.3 Mean :0.1485
3rd Qu.:61.00 3rd Qu.:140.0 3rd Qu.:274.5 3rd Qu.:0.0000
Max. :77.00 Max. :200.0 Max. :564.0 Max. :1.0000
thalachh oldpeak caa
Min. : 71.0 Min. :0.00 Min. :0.0000
1st Qu.:133.5 1st Qu.:0.00 1st Qu.:0.0000
Median :153.0 Median :0.80 Median :0.0000
Mean :149.6 Mean :1.04 Mean :0.7294
3rd Qu.:166.0 3rd Qu.:1.60 3rd Qu.:1.0000
Max. :202.0 Max. :6.20 Max. :4.0000
A continuación usaremos las funciones del paquete {gtsummary} para generar una tabla descriptiva con mayor detalle. Para facilitar la interpretación de los datos, los nombres de las variables serán modificadas en la tabla con la opción label = list(...)
.
heart %>%
select(age, sex, trtbps, chol, thalachh, oldpeak, caa) %>%
tbl_summary(
by = sex,
label = list(age ~ "Edad del paciente",
trtbps ~ "Presión arterial en reposo (en mm Hg)",
chol ~ "Colesterol en mg/dl",
thalachh ~ "Frecuencia cardíaca máxima alcanzada",
oldpeak ~ "Depresión del ST",
caa ~ "Número de vasos principales (0-4)"),
type = all_continuous() ~ "continuous2",
statistic = all_continuous() ~ c("{mean} ({sd})","{p25} - {p75}","{min} - {max}")
)
Characteristic | Hombre, N = 207 | Mujer, N = 96 |
---|---|---|
Edad del paciente | ||
Mean (SD) | 54 (9) | 56 (9) |
IQR | 47 - 60 | 50 - 63 |
Range | 29 - 77 | 34 - 76 |
Presión arterial en reposo (en mm Hg) | ||
Mean (SD) | 131 (17) | 133 (19) |
IQR | 120 - 140 | 120 - 140 |
Range | 94 - 192 | 94 - 200 |
Colesterol en mg/dl | ||
Mean (SD) | 239 (43) | 261 (65) |
IQR | 208 - 268 | 215 - 297 |
Range | 126 - 353 | 141 - 564 |
Frecuencia cardíaca máxima alcanzada | ||
Mean (SD) | 149 (24) | 151 (20) |
IQR | 132 - 168 | 141 - 165 |
Range | 71 - 202 | 96 - 192 |
Depresión del ST | ||
Mean (SD) | 1.12 (1.17) | 0.88 (1.12) |
IQR | 0.00 - 1.80 | 0.00 - 1.40 |
Range | 0.00 - 5.60 | 0.00 - 6.20 |
Número de vasos principales (0-4) | ||
0 | 111 (54%) | 64 (67%) |
1 | 50 (24%) | 15 (16%) |
2 | 25 (12%) | 13 (14%) |
3 | 16 (7.7%) | 4 (4.2%) |
4 | 5 (2.4%) | 0 (0%) |
3.2 Visualizando distribuciones
A continuación usaremos las funciones del paquete {ggplot2} para generar gráficos descriptivos de las variables continuas del set de datos heart.
ggplot(data = heart,
aes(x = age, fill = as.character(output))) +
geom_density(alpha=0.5) +
scale_fill_manual(label = c("0"="Menor","1"="Mayor"),
values = c("0"="#0072B2","1"="#D55E00")) +
theme_classic() +
labs(title = "Edad de los Pacientes",
x="Edad",
fill="Ataque Cardíaco \n(Probabilidad)")
alpha=...
ajusta la transparencia del color, en la función anterior el valor fue ajustado al 50% (0.5). Recordemos que el factor output (probabilidad de ataque cardíaco) corresponde a una escala discreta representada por “0” (menor) y “1” (mayor), para remplazar la leyenda hemos ocupado scale_fill_manual(label =c(...))
, además hemos asignado manualmente un color a cada nivel con la opción values =c(...)
en la función scale_fill_manual(...)
. En tanto la función labs(...)
permite asignar nuevas leyendas a las variables mapeadas y a los objetos de la estética general del gráfico como el título, mientras que con la expresión \n
en la leyenda podemos generar un salto de línea en el texto.Nota
Las personas de mediana edad (40 a 60 años) tienen una mayor probabilidad de sufrir un ataque cardíaco (según la proporción y el set de datos).
Conclusiones
ggplot(data = heart,
aes(x = trtbps, fill = as.character(output))) +
geom_density(alpha=0.5) +
scale_fill_manual(label = c("0"="Menor","1"="Mayor"),
values = c("0"="#0072B2","1"="#D55E00")) +
theme_classic() +
labs(title = "Presión arterial en reposo de los Pacientes",
x="Presión arterial en reposo (en mm Hg)",
fill="Ataque Cardíaco \n(Probabilidad)")
No se observa una tendencía clara de la presión arterial en reposo con la probabilidad de sufrir un ataque cardíaco (según la proporción y el set de datos).
Conclusiones
ggplot(data = heart,
aes(x = chol, fill = as.character(output))) +
geom_density(alpha=0.5) +
scale_fill_manual(label = c("0"="Menor","1"="Mayor"),
values = c("0"="#0072B2","1"="#D55E00")) +
theme_classic() +
labs(title = "Colesterol de los Pacientes",
x="Colesterol en mg/dl",
fill="Ataque Cardíaco \n(Probabilidad)")
Las personas con Colesterol > 200 tienen una mayor probabilidad de sufrir un ataque cardíaco (según la proporción y el set de datos).
Conclusiones
ggplot(data = heart,
aes(x = thalachh, fill = as.character(output))) +
geom_density(alpha=0.5) +
scale_fill_manual(label = c("0"="Menor","1"="Mayor"),
values = c("0"="#0072B2","1"="#D55E00")) +
theme_classic() +
labs(title = "Frecuencia cardíaca máxima alcanzada de los Pacientes",
x="Frecuencia cardíaca máxima alcanzada",
fill="Ataque Cardíaco \n(Probabilidad)")
Las personas con una frecuencia cardíaca máxima alcanzada >150 tienen una mayor probabilidad de sufrir un ataque cardíaco (según la proporción y el set de datos).
Conclusiones
ggplot(data = heart,
aes(x = oldpeak, fill = as.character(output))) +
geom_density(alpha=0.5) +
scale_fill_manual(label = c("0"="Menor","1"="Mayor"),
values = c("0"="#0072B2","1"="#D55E00")) +
theme_classic() +
labs(title = "Depresión del ST inducida por el ejercicio \nen relación con el reposo de los Pacientes",
x="Depresión del ST",
fill="Ataque Cardíaco \n(Probabilidad)")
ggplot(data = heart,
aes(x = caa, fill = as.character(output))) +
geom_density(alpha=0.5) +
scale_fill_manual(label = c("0"="Menor","1"="Mayor"),
values = c("0"="#0072B2","1"="#D55E00")) +
theme_classic() +
labs(title = "Número de vasos principales de los Pacientes",
x="Número de vasos principales (0-4)",
fill="Ataque Cardíaco \n(Probabilidad)")
Conclusiones
3.3 Visualizando Variables Categóricas
A continuación revisaremos cómo se distribuyen las variables categóricas del set de datos heart.
ggplot(data = heart,
aes(x = sex, fill = as.character(output))) +
geom_bar(alpha=0.7, position = "fill") +
scale_y_continuous(labels = scales::percent) +
scale_fill_manual(label = c("0"="Menor","1"="Mayor"),
values = c("0"="#0072B2","1"="#D55E00")) +
theme_classic() +
labs(title = "Sexo de los Pacientes",
x=NULL,
fill="Ataque Cardíaco \n(Probabilidad)")
position = "fill"
en la capa o objeto geom geom_bar(...)
. Adicionalmente, con la función scale_y_continuous(labels = scales::percent)
podemos modificar la escala y cambiarla desde proporción a porcentajes, lo que facilitará la interpretación y mejora la estética del gráfico. Nota
Las mujeres tienen más probabilidades de tener problemas cardíacos que los hombres (según la proporción y el set de datos).
Conclusiones
ggplot(data = heart %>%
mutate(cp = recode(cp, "0"="Asintomático","1"="Típica","2"="Atípica","3"="No Anginoso")),
aes(x = cp, fill = as.character(output))) +
geom_bar(alpha=0.7, position = "fill") +
scale_y_continuous(labels = scales::percent) +
scale_fill_manual(label = c("0"="Menor","1"="Mayor"),
values = c("0"="#0072B2","1"="#D55E00")) +
theme_classic() +
labs(title = "Tipo de dolor de pecho (angina) de los Pacientes",
x=NULL,
fill="Ataque Cardíaco \n(Probabilidad)")
mutate(...)
podemos modificar (o crear) una columna, mientras que con la función recode(...)
podemos reasignar los valores dentro de una determinada columna. En este caso es necesario generar una modificación, puesto que los valores se encuentran como un código númerico, lo que dificulta la interpretación de los resultados. Nota
Conclusiones
ggplot(data = heart %>%
mutate(restecg = recode(restecg, "0"="Normal","1"="Anomalía (ST-T)","2"="Muestra hipertrofia")),
aes(x = restecg, fill = as.character(output))) +
geom_bar(alpha=0.7, position = "fill") +
scale_y_continuous(labels = scales::percent) +
scale_fill_manual(label = c("0"="Menor","1"="Mayor"),
values = c("0"="#0072B2","1"="#D55E00")) +
theme_classic() +
labs(title = "Resultados electrocardiográficos en reposo de los Pacientes",
x=NULL,
fill="Ataque Cardíaco \n(Probabilidad)")
Conclusiones
ggplot(data = heart %>%
mutate(exng = recode(exng, "0"="No","1"="Si")),
aes(x = exng, fill = as.character(output))) +
geom_bar(alpha=0.7, position = "fill") +
scale_y_continuous(labels = scales::percent) +
scale_fill_manual(label = c("0"="Menor","1"="Mayor"),
values = c("0"="#0072B2","1"="#D55E00")) +
theme_classic() +
labs(title = "Angina inducida por ejercicio en Pacientes",
x=NULL,
fill="Ataque Cardíaco \n(Probabilidad)")
Conclusiones
ggplot(data = heart %>%
mutate(slp = recode(slp, "0"="Descendente","1"="Plano","2"="Ascendente")),
aes(x = slp, fill = as.character(output))) +
geom_bar(alpha=0.7, position = "fill") +
scale_y_continuous(labels = scales::percent) +
scale_fill_manual(label = c("0"="Menor","1"="Mayor"),
values = c("0"="#0072B2","1"="#D55E00")) +
theme_classic() +
labs(title = "Pendiente del segmento ST de ejercicio máximo de los Pacientes",
x=NULL,
fill="Ataque Cardíaco \n(Probabilidad)")
Conclusiones
ggplot(data = heart %>%
filter(thall != 0) %>%
mutate(thall = recode(thall, "1"="Defecto fijo","2"="Normal","3"="Defecto reversible")),
aes(x = thall, fill = as.character(output))) +
geom_bar(alpha=0.7, position = "fill") +
scale_y_continuous(labels = scales::percent) +
scale_fill_manual(label = c("0"="Menor","1"="Mayor"),
values = c("0"="#0072B2","1"="#D55E00")) +
theme_classic() +
labs(title = "Frecuencia cardíaca ritmo de los Pacientes",
x=NULL,
fill="Ataque Cardíaco \n(Probabilidad)")
filter(...)
podemos eliminar o seleccionar los valores de interes dentro de una determinada columna. En este caso es necesario eliminar las observaciones con valor “0” en la columna “thall”, puesto que corresponden a dos pacientes sin la observación. Para realizar este filtro, le hemos indicado a la función que retenga los valores distintos a “0” escribiendo el símbolo de desigualdad !=
. Nota
Conclusiones
3.4 Visualizando Variables Agrupadas
Sobre la base de las variables contenidas en el set de datos heart, que ya hemos análisado de forma independiente, podríamos dirigir el análisis hacia aquellas interacciones entre variables que son relevante en el diagnóstico de un ataque al corazón. Podríamos generar algunas nuevas preguntas:
- ¿Cuáles son las variables más importantes de nuestro análisis?
- ¿Cómo se relaciona la edad (age) y el sexo (sex) del paciente con un ataque al corazón?
- ¿Cómo se relaciona el sexo (sex) y el colesterol (chol) del paciente con un ataque al corazón?
- ¿Cómo se relaciona el sexo (sex) y la presión arterial en reposo (trtbps) del paciente con un ataque al corazón?
- ¿Cómo se relaciona el sexo (sex) y la frecuencia cardíaca máxima alcanzada (thalach) del paciente con un ataque al corazón?
ggplot(data = heart,
aes(x = sex,
y = age,
fill = as.character(output))) +
geom_boxplot(outlier.shape = NA) +
scale_fill_manual(label = c("0"="Menor","1"="Mayor"),
values = c("0"="#0072B2","1"="#D55E00")) +
theme_classic() +
labs(title = "Edad por sexo de los Pacientes",
y="Edad",
x=NULL,
fill="Ataque Cardíaco \n(Probabilidad)")
En pacientes hombres y mujeres más jovenes se observan mayores problemas cardíacos (según el set de datos).
Conclusiones
ggplot(data = heart,
aes(x = sex,
y = chol,
fill = as.character(output))) +
geom_boxplot(outlier.shape = NA) +
scale_fill_manual(label = c("0"="Menor","1"="Mayor"),
values = c("0"="#0072B2","1"="#D55E00")) +
theme_classic() +
labs(title = "Colesterol por sexo de los Pacientes",
y="Colesterol (mg/dl)",
x=NULL,
fill="Ataque Cardíaco \n(Probabilidad)")
En Hombres y mujeres menores valores de colesterol se observan en pacientes con problemas cardíacos (según el set de datos).
Conclusiones
ggplot(data = heart,
aes(x = sex,
y = trtbps,
fill = as.character(output))) +
geom_boxplot(outlier.shape = NA) +
scale_fill_manual(label = c("0"="Menor","1"="Mayor"),
values = c("0"="#0072B2","1"="#D55E00")) +
theme_classic() +
labs(title = "Presión arterial en reposo por sexo de los Pacientes",
y="Presión arterial en reposo (en mm Hg)",
x=NULL,
fill="Ataque Cardíaco \n(Probabilidad)")
En pacientes mujeres con menos problemas cardíacos se observa una mayor presión arterial en reposo (en mm Hg) (según el set de datos).
Conclusiones
ggplot(data = heart,
aes(x = sex,
y = thalachh,
fill = as.character(output))) +
geom_boxplot(outlier.shape = NA) +
scale_fill_manual(label = c("0"="Menor","1"="Mayor"),
values = c("0"="#0072B2","1"="#D55E00")) +
theme_classic() +
labs(title = "Frecuencia cardíaca máxima por sexo de los Pacientes",
y="Frecuencia cardíaca máxima alcanzada",
x=NULL,
fill="Ataque Cardíaco \n(Probabilidad)")
En Hombres y mujeres una mayor frecuencia cardíaca máxima alcanzada se asocia con problemas cardíacos (según el set de datos).
Conclusiones
4 Inferencia Estadística
En base a los resultados obtenidos en la etapa anterior del análisis, la descriptión estadística de las variables contenidas en el set de datos heart, hemos observados la relación entre las principales variables del set de datos. Anteriormente, observamos que factores como la edad, sexo, colesterol, número de vasos principales, presión arterial en reposo, y frecuencia cardíaca máxima de los pacientes se asocian con un mayor riesgo de sufrir problemas cardíaco. Sin embargo, todas las asociaciónes que hemos observado carecen de un sustento estadístico que demuestre que las observaciones no corresponde a un evento aleatorio. Para asegurarnos de las validez en las interpretaciones realizadas anteriormente a continuación realizaremos algunos análisis estadísticos que nos ayuden a confirmar los resultados previos. El primer análisis consiste en una correlación entre parejas de factores.
4.1 Correlación
¿Qué es la correlación?
La correlación es una medida estadística que nos informa sobre la asociación entre dos variables. Describe cómo se comporta una variable frente a algún cambio en la variable asociada.
Interpretación
Si las variables aumentan o disminuyen juntas, entonces tendrán una correlación positiva. Si las variables son opuestas (una aumenta y la otra disminuye), entonces la correlación será negativa entre ellas. Si varían de forma independiente, la correlación entre ellos será cercana a cero.
- Las correlaciones son la medida de dependencia lineal entre dos variables, solo se pueden aplicar entre pares.
- Son sensibles al número de muestras. Si el número de muestras es pequeños (<20 ~ 30) el análisis pierde poder estadístico (óptimo ≥ 100)
Advertencia
¿Cómo calcular la correlación entre pares?
[1] -0.2384001
Nota
La edad se asocia de manera negativa y débil con problemas cardíacos.
Conclusiones
A continuación con la ayuda de los paquetes {corrplot} y {Hmisc} para gráficar múltiples correlaciones entre pares de factores.
# Seleccionar variables numéricas y modificar las variable "sex" a numérica
heart.n <- heart %>%
mutate(sex = case_when(sex == "Mujer" ~ 0,
sex == "Hombre" ~ 1)) %>%
select_if(is.numeric) %>% as.matrix()
# Calcular la correlación
cor<-rcorr(heart.n, type="spearman") #"pearson"
# Ajustar valor de p (múltiples comparaciones)
cor$P.adj<-p.adjust(cor$P, method = "fdr")
dim(cor$P.adj) <- dim(cor$P)
# Gráfico de las correlaciones
corrplot(cor$r,
method="circle",
type="upper",
col=brewer.pal(n=8, name="PuOr"),
tl.cex = 1.5,
tl.col="black",
tl.srt = 90,
p.mat = cor$P.adj,
sig.level = 0.05,
insig = "blank",
pch.cex = 1.0,
pch.col = "white",
cl.cex = 1.2,
cl.align.text = "l",
cl.offset = 0.5,
diag = FALSE,
title ="Asociación con Problemas Cardíacos",
mar = c(1.5, 1.5, 1.5, 1.5))
sig.level = 0.05
en la función corrplot(...)
, solo se mostrarán en el gráfico aquellas correlaciones que sean significativas (p < 0.05). Nota
Conclusiones
4.2 Modelos lineales
El segundo análisis consiste en el estudio de las relaciones lineales entre factores en el set de datos heart.
¿Qué es una regresión lineal?
Una regresión lineal es un modelo (ecuación) estadístico que se usa para analizar la relación entre una variable de respuesta (comunmente llamada Y) y una o más variables y sus interacciones (comunmente llamada X o variables explicativas). La regresión lineal asume una relación lineal entre la variable de respuesta y las variables explicativas. Esto significa que puede ajustar una línea entre las dos (o más variables).
Un modelo básico es:
\[ Y = A + B * X \]
Donde A corresponde al intersecto (donde empiezas a medir cuando X es cero) y B a la pendiente (el cambio de Y con respecto a X).
La idea del modelamiento es generar un modelo ajustado de la mejor forma a nustras variables, encontrando el A y B que mejor se adapten a nuestro set de datos.
Call:
lm(formula = thalachh ~ output, data = heart)
Residuals:
Min 1Q Median 3Q Max
-68.101 -12.784 2.899 14.533 55.899
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 139.101 1.771 78.55 < 2e-16 ***
output 19.365 2.400 8.07 1.7e-14 ***
---
Signif. codes: 0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
Residual standard error: 20.8 on 301 degrees of freedom
Multiple R-squared: 0.1779, Adjusted R-squared: 0.1751
F-statistic: 65.12 on 1 and 301 DF, p-value: 1.697e-14
Conclusiones
facet_grid(fila ~ columna)
que nos permitirá generar una cuadrícula que facilitará la interpretación y/o análisis de grupos específicos. Nota
heart %>% mutate(exng = case_when(exng == 0 ~ "No",
exng == 1 ~ "Si"),
slp = case_when(slp == 0 ~ "Descendente" ,
slp == 1 ~ "Plano",
slp == 2 ~ "Ascendente")) %>%
ggplot(aes(x = thalachh, y = oldpeak, color = as.character(output))) +
geom_smooth(method = lm) +
scale_color_manual(label = c("0"="Menor","1"="Mayor"),
values = c("0"="#0072B2","1"="#D55E00")) +
stat_regline_equation(aes(label = paste(..eq.label..,
..adj.rr.label..,
sep = "~~~~"))) +
theme_classic() +
theme(legend.position = "bottom") +
facet_grid(exng ~ slp) +
labs(title = "Asociación con Problemas Cardíacos",
y="Depresión del ST inducida por el ejercicio \nen relación con el reposo",
x="Frecuencia cardíaca máxima alcanzada",
color="Ataque Cardíaco \n(Probabilidad)")
theme(...)
somo capaces de modificar factores estéticos del gráfico, en el caso anterior hemos modificado la posición original de la leyenda de color con la opción legend.position = "bottom"
colocándola en la base del gráfico y no a la derecha como se ubica por defecto. Nota
heart %>% mutate(exng = case_when(exng == 0 ~ "No",
exng == 1 ~ "Si"),
cp = case_when(cp == 0 ~ "Asintomático" ,
cp == 1 ~ "Angina típica",
cp == 2 ~ "Angina atípica",
cp == 3 ~ "Dolor no anginoso")) %>%
ggplot(aes(x = thalachh, y = oldpeak, color = as.character(output))) +
geom_point() +
geom_smooth(method = lm) +
scale_color_manual(label = c("0"="Menor","1"="Mayor"),
values = c("0"="#0072B2","1"="#D55E00")) +
stat_regline_equation(aes(label = paste(..eq.label..,
..adj.rr.label..,
sep = "~~~~"))) +
theme_classic() +
theme(legend.position = "bottom") +
facet_grid(cp ~ exng) +
labs(title = "Asociación con Problemas Cardíacos",
y="Depresión del ST inducida por el ejercicio \nen relación con el reposo",
x="Frecuencia cardíaca máxima alcanzada",
color="Ataque Cardíaco \n(Probabilidad)")
Conclusiones
4.3 Análisis de varianza
El tercer análisis consiste en el estudio de las varianza entre factores agrupados en el set de datos heart.
¿Qué es un análisis de varianza?
Son una colección de análisis que permiten examinar si las medias de los grupos (poblaciones, muestras) difieren entre sí. Existen métodos que difieren en el número de grupos que pueden comparar. Además existen métodos parametricos (requieren que se cumplan los supuestos) y no parámetricos (no requieren que se cumplan todos los supuestos) que son más o menos robustos frente al incumplimiento de algunos de los tres supuestos en los datos.
Supuestos de los análisis paramétricos
- Independencia (los elementos de un grupo no están relacionados con los del otro grupo)
- Normalidad (los elementos de una muestra tienen distribución normal)
- Homocedasticidad (las variaciones de los grupos son iguales)
Debido a los supuestos de los análisis paramétricosprímero debemos analizar la distribución de nuestras variables y su homocedasticidad.
4.3.1 Análisis de Normalidad
4.3.1.1 Shapiro-Wilk (SW) test
Interpretación
p-value > alfa: No rechazar H0 (normal)
p-value < alfa: Rechazar H0 (no normal)
alfa hipotético 5% (0,05)
Shapiro-Wilk normality test
data: heart$age
W = 0.98637, p-value = 0.005798
ggdensity(data=heart, x = "age", fill = "lightgreen") +
stat_overlay_normal_density(color = "darkblue", linetype = "dashed")
Shapiro-Wilk normality test
data: heart$chol
W = 0.94688, p-value = 5.365e-09
ggdensity(data=heart, x = "chol", fill = "lightgreen") +
stat_overlay_normal_density(color = "darkblue", linetype = "dashed")
Shapiro-Wilk normality test
data: heart$thalachh
W = 0.97632, p-value = 6.621e-05
ggdensity(data=heart, x = "thalachh", fill = "lightgreen") +
stat_overlay_normal_density(color = "darkblue", linetype = "dashed")
Conclusiones
4.3.2 Análisis de Homocedasticidad
4.3.2.1 Fligner-Killeen test
Para probar homocedasticidad en k grupos de muestras, donde k puede ser mayor a dos. Más robusto contra las desviaciones de la normalidad o cuando hay problemas relacionados con valores atípicos (outliers).
Interpretación
p-value > alfa: No rechazar H0 (normal)
p-value < alfa: Rechazar H0 (no normal)
alfa hipotético 5% (0,05)
Fligner-Killeen test of homogeneity of variances
data: age by interaction(sex, output)
Fligner-Killeen:med chi-squared = 14.436, df = 3, p-value = 0.002368
Fligner-Killeen test of homogeneity of variances
data: chol by interaction(sex, output)
Fligner-Killeen:med chi-squared = 14.581, df = 3, p-value = 0.002212
Fligner-Killeen test of homogeneity of variances
data: thalachh by interaction(sex, output)
Fligner-Killeen:med chi-squared = 6.9642, df = 3, p-value = 0.07305
Conclusiones
Nota
4.3.3 Kruskal-Wallis test
Kruskal-Wallis test es una prueba estadística y no paramétrica que se utiliza para comparar las medias de más de dos grupos.
Interpretación
p-value < alfa: rechazar H0 (hay diferencias)
p-value > alfa: No Rechazar H0 (no hay diferencias)
alfa hipotético 5% (0,05)
ggplot(data = heart %>% filter(output == "1"),
aes(x = sex,
y = age,
fill = sex)) +
geom_boxplot(outlier.shape = NA) +
stat_compare_means(label.y = 85) +
stat_compare_means(aes(label = ..p.signif..),
method = "wilcox.test") +
theme_classic() +
labs(title = "Edad por sexo de los Pacientes \nde mayor riesgo de problema cardíaco",
y="Edad",
x=NULL,
fill="Sexo del Paciente")
heart %>% filter(output == "1")
dentro de la función ggplot(...)
. Nota
ggplot(data = heart,
aes(x = sex,
y = age,
fill = as.character(output))) +
geom_boxplot(outlier.shape = NA) +
stat_compare_means() +
stat_compare_means(aes(label = ..p.signif..),
method = "wilcox.test",
ref.group = ".all.") +
scale_fill_manual(label = c("0"="Menor","1"="Mayor"),
values = c("0"="#0072B2","1"="#D55E00")) +
theme_classic() +
labs(title = "Edad por sexo de los Pacientes",
y="Edad",
x=NULL,
fill="Ataque Cardíaco \n(Probabilidad)")
ggplot(data = heart,
aes(x = sex,
y = chol,
fill = as.character(output))) +
geom_boxplot(outlier.shape = NA) +
stat_compare_means() +
stat_compare_means(aes(label = ..p.signif..),
method = "wilcox.test",
ref.group = ".all.") +
scale_fill_manual(label = c("0"="Menor","1"="Mayor"),
values = c("0"="#0072B2","1"="#D55E00")) +
theme_classic() +
labs(title = "Colesterol por sexo de los Pacientes",
y="Colesterol (mg/dl)",
x=NULL,
fill="Ataque Cardíaco \n(Probabilidad)")
ggplot(data = heart,
aes(x = sex,
y = thalachh,
fill = as.character(output))) +
geom_boxplot(outlier.shape = NA) +
stat_compare_means() +
stat_compare_means(aes(label = ..p.signif..),
method = "wilcox.test",
ref.group = ".all.") +
scale_fill_manual(label = c("0"="Menor","1"="Mayor"),
values = c("0"="#0072B2","1"="#D55E00")) +
theme_classic() +
labs(title = "Frecuencia cardíaca máxima por sexo de los Pacientes",
y="Frecuencia cardíaca máxima alcanzada",
x=NULL,
fill="Ataque Cardíaco \n(Probabilidad)")
4.3.4 ANOVA
ANOVA es una prueba estadística y paramétrica que se utiliza para comparar las medias de más de dos grupos.
Interpretación
p-value < alfa: rechazar H0 (hay diferencias)
p-value > alfa: No Rechazar H0 (no hay diferencias)
alfa hipotético 5% (0,05)
heart <- heart %>%
mutate(thalachh_sqrt = sqrt(max(thalachh+1)-thalachh))
shapiro.test(heart$thalachh_sqrt)
Shapiro-Wilk normality test
data: heart$thalachh_sqrt
W = 0.99407, p-value = 0.2844
ggdensity(data=heart, x = "thalachh_sqrt", fill = "lightgreen") +
stat_overlay_normal_density(color = "darkblue", linetype = "dashed")
Nota
ggplot(data = heart,
aes(x = sex,
y = thalachh_sqrt,
fill = as.character(output))) +
geom_boxplot(outlier.shape = NA) +
stat_compare_means(method = "anova") +
stat_compare_means(aes(label = ..p.signif..),
method = "t.test",
ref.group = ".all.") +
scale_fill_manual(label = c("0"="Menor","1"="Mayor"),
values = c("0"="#0072B2","1"="#D55E00")) +
theme_classic() +
labs(title = "Frecuencia cardíaca máxima por sexo de los Pacientes",
y="Frecuencia cardíaca máxima alcanzada \n(transformación de raíz cuadrada)",
x=NULL,
fill="Ataque Cardíaco \n(Probabilidad)")
Nota
5 Conclusiones
Las mujeres tienen más probabilidades de tener problemas cardíacos que los hombres (según la proporción), y muestran una diferencia significativa en el análisis de varianza entre pacientes de alto riesgo.
Las personas de mediana edad (40 a 60 años) tienen una mayor probabilidad de sufrir un ataque cardíaco en ambos sexos.
Los pacientes hombres que tienen una probabilidad mayor de sufrir un ataque cardíaco muestran niveles menores de colesterol que los pacientes con menor probabilidad.
Las personas (hombres y mujeres) con una frecuencia cardíaca máxima alcanzada > 150 tienen una mayor probabilidad de sufrir un ataque cardíaco.
La frecuencia cardíaca máxima y la depresión del ST inducida por el ejercicio se asocian fuertemente en los pacientes que presentan dolor de pecho tipo “angina típica” (positivamente asociados) y “dolor no anginoso” (negativamente asociados) en el grupo de pacientes con una mayor probabilidad de sufrir problemas cardíacos y que muestran angina inducida por ejercicio.
6 Gráfico compuestos con {Patchwork}
pA <-
ggplot(data = heart,
aes(x = sex, fill = as.character(output))) +
geom_bar(position = "fill") +
scale_y_continuous(labels = scales::percent) +
scale_fill_manual(label = c("0"="Menor","1"="Mayor"),
values = c("0"="#0072B2","1"="#D55E00")) +
theme_classic() +
labs(title = "Sexo de los Pacientes",
x=NULL,
fill="Ataque Cardíaco \n(Probabilidad)")
pB <-
ggplot(data = heart %>% filter(output == "1"),
aes(x = sex,
y = age,
fill = sex)) +
geom_boxplot(outlier.shape = NA) +
stat_compare_means(label.y = 85) +
stat_compare_means(aes(label = ..p.signif..),
method = "wilcox.test") +
theme_classic() +
labs(title = "Edad por sexo de los Pacientes \nde mayor riesgo de problema cardíaco",
y="Edad",
x=NULL,
fill="Sexo del Paciente")
# Gráfico compuesto
pA / pB +
plot_annotation(tag_levels = 'A') +
plot_layout(guides = "collect")
pA <-
y pB <-
antes del comando que nos permite generar un gráfico, de esta forma le diremos a R que el primer gráfico se guarde como un objeto llamado pA y el segundo como un objeto llamado pB. Luego llamaremos los objetos pA y pB, asignandole un orden espacial, por ejemplo pA + pB
asignará un gráfico lado a lado con el otro, si quísieramos que un gráfico estuviera sobre el otro podríamos utilizar la siguiente estructura pA / pB
. Adicionalmente, sí tuviéramos más objetos gráficos podríamos combinarlos de igual forma, un ejemplo con cuatro gráficos podría ser pA + pB + pC + pD
(lado a lado en una línea de 4), (pA + pB) / (pC + pD)
(dos filas de 2 y 2 columnas) o (pA + pB + pC) / pD
(una filas superior de 3 y 1 figura amplia en la segunda fila). Con la función plot_annotation(tag_levels = 'A')
le dirémos a la función que adicione una letra a cada gráfico lo que facilita la interpretación de un gráfico compuesto. Finalmente con la función plot_layout(guides = "collect")
le diremos a la función que agrupe todas las leyendas en una posición única general (izquierda en el ejemplo). Nota