Introducción

La insuficiencia cardíaca es una condición clínica compleja y progresiva que afecta a millones de personas en todo el mundo. Comprender los factores que influyen en la supervivencia de los pacientes con insuficiencia cardíaca es crucial para mejorar los resultados clínicos y desarrollar estrategias de intervención más efectivas.

El presente estudio se centra en el análisis del conjunto de datos “heart_failure_clinical_records_dataset”, que contiene información detallada sobre pacientes diagnosticados con insuficiencia cardíaca. Este conjunto de datos incluye una variedad de variables clínicas, tales como la edad, la presencia de anemia, los niveles de creatina fosfoquinasa, diabetes, fracción de eyección, hipertensión arterial, recuento de plaquetas, niveles de creatinina sérica y sodio sérico, sexo, tabaquismo, tiempo de seguimiento y el evento de muerte.

El objetivo principal de este análisis es explorar la relación entre estas variables y el tiempo de supervivencia de los pacientes con insuficiencia cardíaca. Específicamente, buscamos identificar los factores que están asociados con un mayor riesgo de mortalidad y determinar si existen diferencias significativas en la supervivencia entre subgrupos de pacientes, como aquellos definidos por el sexo.

Exploración de los datos:

Descripción de las variables

Instalar librerias

heart_failure_clinical_records_dataset <- read_csv("heart_failure_clinical_records_dataset.csv")
## Rows: 299 Columns: 13
## ── Column specification ────────────────────────────────────────────────────────
## Delimiter: ","
## dbl (13): age, anaemia, creatinine_phosphokinase, diabetes, ejection_fractio...
## 
## ℹ Use `spec()` to retrieve the full column specification for this data.
## ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
df=heart_failure_clinical_records_dataset

Conocer los datos

head(df)
## # A tibble: 6 × 13
##     age anaemia creatinine_phosphokinase diabetes ejection_fraction
##   <dbl>   <dbl>                    <dbl>    <dbl>             <dbl>
## 1    75       0                      582        0                20
## 2    55       0                     7861        0                38
## 3    65       0                      146        0                20
## 4    50       1                      111        0                20
## 5    65       1                      160        1                20
## 6    90       1                       47        0                40
## # ℹ 8 more variables: high_blood_pressure <dbl>, platelets <dbl>,
## #   serum_creatinine <dbl>, serum_sodium <dbl>, sex <dbl>, smoking <dbl>,
## #   time <dbl>, DEATH_EVENT <dbl>
tail(df)
## # A tibble: 6 × 13
##     age anaemia creatinine_phosphokinase diabetes ejection_fraction
##   <dbl>   <dbl>                    <dbl>    <dbl>             <dbl>
## 1    63       1                      103        1                35
## 2    62       0                       61        1                38
## 3    55       0                     1820        0                38
## 4    45       0                     2060        1                60
## 5    45       0                     2413        0                38
## 6    50       0                      196        0                45
## # ℹ 8 more variables: high_blood_pressure <dbl>, platelets <dbl>,
## #   serum_creatinine <dbl>, serum_sodium <dbl>, sex <dbl>, smoking <dbl>,
## #   time <dbl>, DEATH_EVENT <dbl>
dim(df)
## [1] 299  13
colSums(is.na(df))
##                      age                  anaemia creatinine_phosphokinase 
##                        0                        0                        0 
##                 diabetes        ejection_fraction      high_blood_pressure 
##                        0                        0                        0 
##                platelets         serum_creatinine             serum_sodium 
##                        0                        0                        0 
##                      sex                  smoking                     time 
##                        0                        0                        0 
##              DEATH_EVENT 
##                        0
attach(df)
df$DEATH_EVENT[df$DEATH_EVENT == 0]<- 2
df$DEATH_EVENT[df$DEATH_EVENT == 1]<- 1

Análisis descriptivo

datos <- df %>%
  mutate(rango_edad = cut(age, 
                          breaks = c(0, 18, 30, 45, 60, 100),  
                          labels = c("0-18", "19-30", "31-45", "46-59", "60-95"),
                          right = FALSE)) 

ggplot(datos, aes(x = rango_edad)) +
  geom_bar(fill = "skyblue", color = "black", alpha = 0.7) +
  labs(title = "Distribución de Edades en Rangos", x = "Rango de Edad", y = "Frecuencia") +
  theme_minimal()

En la gráfica anterior podemos visualizar el rango de edades de las personas que estamos estudiando.

diabetes_1 <- table(df$sex, df$diabetes)
barplot(diabetes_1,                            
        main="Sexo vs diabetes",              
        xlab="Presenta diabetes",                         
        ylab="Frecuencias",                  
        legend = rownames(diabetes_1),        
        ylim = c(0, 180),                   
        col=c("#FFB90F","#1C86EE"),  
        beside=TRUE                         
        ) 

Comparamos el tipo de variable sexo 0 con sexo 1 respecto a la variable diabetes en el caso de que no haya presentado diabetes se representa con el número 0 y en caso de que si con el número 1.

Escritura de los datos, en formato de censura

Surv(df$time,df$DEATH_EVENT)
##   [1]   4+   6+   7+   7+   8+   8+  10+  10+  10+  10+  10+  10+  11+  11+  12 
##  [16]  13+  14+  14+  15+  15+  16   20+  20+  22   23+  23+  24+  26+  26+  26+
##  [31]  27+  28+  28+  29   29+  30+  30+  30+  30   30+  31+  32+  33+  33   33+
##  [46]  35+  38+  40+  41+  42+  43+  43+  43+  44+  45+  50+  54   54   55+  59+
##  [61]  60+  60+  60   61+  63   64+  65+  65+  66+  67+  68   71   72+  72   73+
##  [76]  73+  74   74   74   74   75   76   77+  78   78+  79   79   79   79   79 
##  [91]  80   80   82   82+  83   83   83   85   85   86   87   87   87   87   87 
## [106]  88+  88   88   88   88   90+  90   90   90+  91   91   94   94   94   95+
## [121]  95   95   95   95   96+  97  100+ 104  104  105  106  107  107  107  107 
## [136] 107  107  108  108  108  109+ 109  109  110  111+ 112  112  113  113+ 115 
## [151] 115+ 117  118  119  120  120  120  120  121  121  121  121  123  126+ 129+
## [166] 130+ 134  135+ 140  145  145  146  146  146  146  146  147  147  147  147 
## [181] 148  150+ 154+ 162+ 170+ 171+ 172+ 172+ 172  174  174  174  175  180  180+
## [196] 180+ 185  186  186  186  186  186  186  187  187  187  187  187  187  187 
## [211] 188  192  192  193+ 194  195  196  196+ 197  197  198+ 200  201  201  205 
## [226] 205  205  206  207  207  207+ 208  209  209  209  209  209  210  210  211 
## [241] 212  212  212  213  213  213  214+ 214  214  214  214  215  215  215  215 
## [256] 216  220  230  230  231  233  233  235+ 237  237  240  241+ 244  244  244 
## [271] 244  244  245  245  245  245  245  246  246  246  247  250  250  250  250 
## [286] 250  250  250  256  256  257  258  258  270  270  271  278  280  285

Estimador de Kaplan - Meier para el tiempo de supervivencia

km = Surv(df$time,df$DEATH_EVENT)
km1 = survfit(km~1,data=df,type = "kaplan-meier")
km1
## Call: survfit(formula = km ~ 1, data = df, type = "kaplan-meier")
## 
##        n events median 0.95LCL 0.95UCL
## [1,] 299    203    186     148     196

El estimador de Kaplan - Meier, es un estimador no paramétrico de la función de supervivencia, con el cual podemos observar el total de individuos en el estudio, el evento, la media y los intervalos de confianza.

Gráfica de los tiempos de supervivencia

ggsurvplot(km1)

Como se observa en la gráfica a medida que aumenta el tiempo, la probabilidad de supervivencia disminuye, la cual esta desde 0 hasta 1 y el tiempo inicia en 0 hasta 300. Se observa que en el tiempo 0, la probabilidad de supervivencia es 1 y a medida que el tiempo aumenta, empieza a disminuir la probabilidad de supervivencia.

Función survfit

Utilizando la función survfit se va a estimar el comportamiento del tiempo de supervivencia dependiendo del sexo del paciente.

km2=surv_fit(Surv(df$time,df$DEATH_EVENT) ~ sex,data = df)
n events median 0.95LCL 0.95UCL
sex0 105 71 187 147 210
sex1 194 132 186 186 200

Al utilizar la función surv_fit encontramos los siguientes casos, para el primer caso el sexo 0 se tienen 105 individuos, de los cuales 71 presentaron el evento y una mediana de supervivencia de 187, con un límite de confianza inferior de 147 y el límite de confianza superior de 210. El segundo caso es el sexo 1, en el cual se observa que hay 194 individuos en el estudio, 132 presentaron el evento, con una mediana de 186 y el límite de confianza inferior de 186 y el superior de 200.

A = surv_summary(km2)
## Warning in .get_data(x, data = data): The `data` argument is not provided. Data
## will be extracted from model fit.
head(A)
##   time n.risk n.event n.censor      surv     std.err upper     lower strata sex
## 1    8    105       0        1 1.0000000 0.000000000     1 1.0000000  sex=0   0
## 2   10    104       0        1 1.0000000 0.000000000     1 1.0000000  sex=0   0
## 3   12    103       1        0 0.9902913 0.009756214     1 0.9715350  sex=0   0
## 4   15    102       0        2 0.9902913 0.009756214     1 0.9715350  sex=0   0
## 5   16    100       1        0 0.9803883 0.014006920     1 0.9538398  sex=0   0
## 6   20     99       0        1 0.9803883 0.014006920     1 0.9538398  sex=0   0

La función surv_summary nos crea un marco de datos, en el que nos permite visualizar los tiempos en que se estiman las probabilidades de supervivencia, los números de individuos que están en riesgo, los eventos que se han presentado, los números de observaciones censuradas, la estimación de la probabilidad de supervivencia, el error estandar de la probabilidad de supervivencia, los límites de intervalo de confianza y el sexo

Resumen de la información del tiempo de supervivencia

summary(km2)$table
##       records n.max n.start events    rmean se(rmean) median 0.95LCL 0.95UCL
## sex=0     105   105     105     71 168.4327  7.595082    187     147     210
## sex=1     194   194     194    132 165.6090  5.481873    186     146     200

Con la función summary(km2)$table observamos el número total de observaciones para el análisis, los individuos en riesgo al inicio del estudio, el tiempo de supervivencia promedio hasta un tiempo específico, el error estándar del tiempo de supervivencia medio restringido, el cual mide la variabilidad o incertidumbre en el tiempo medio restringido estimado, también tenemos el tiempo de supervivencia mediano, en el que se espera que el 50% de los individuos hayan experimentado el evento, finalmente tenemos los límites de confianza. La tabla que obtuvimos es complementaria a la que creamos en km2, en esta taba se adiciona el número total de las observaciones el cual corresponde a 105 para el sexo 0 y 194 para sexo 1. Se tiene que el tiempo de supervivencia promedio para el sexo 0 es 168.4327 y sexo 1 de 165.6090, con un error estándar medio de 7.595082 para sexo 0 y para sexo 1 de 5.481873.

Gráfica de kaplan - Meier de la variable sexo

  ggsurvplot(
km2, # ajuste hecho anteriormente
pval = TRUE, # p-value de la prueba log-rank
conf.int = TRUE, # intervalos de confianza puntuales
conf.int.style = "step", # cambia el estilo de las bandas de confianza
xlab = "Tiempo en días", # título del eje X
break.time.by = 50, # separación de los intervalos en el eje X
ggtheme = theme_light(), # personaliza la gráfica y tabla con un tema
risk.table = "abs_pct", # número absoluto y porcentaje en riesgo
risk.table.y.text.col = T, # color del texto en la tabla de riesgo
risk.table.y.text = FALSE, # muestra barras en lugar de nombres
ncensor.plot = TRUE, # grafica el número de censuras al tiempo t
surv.median.line = "hv", # agrega líneas de la mediana
legend.labs =
  c("sex0", "sex1"), # cambia nombres de las categorías
palette =
 c("pink", "purple"), # elige los colores
xlim = c(0, 290) # corta el eje X
  )
## Warning in geom_segment(aes(x = 0, y = max(y2), xend = max(x1), yend = max(y2)), : All aesthetics have length 1, but the data has 2 rows.
## ℹ Please consider using `annotate()` or provide this layer with data containing
##   a single row.
## All aesthetics have length 1, but the data has 2 rows.
## ℹ Please consider using `annotate()` or provide this layer with data containing
##   a single row.
## All aesthetics have length 1, but the data has 2 rows.
## ℹ Please consider using `annotate()` or provide this layer with data containing
##   a single row.
## All aesthetics have length 1, but the data has 2 rows.
## ℹ Please consider using `annotate()` or provide this layer with data containing
##   a single row.

Prueba de Long - Rank

Se utiliza la función survdiff para revisar el número de observaciones, lo observado, lo esperado, Chi-cuadrado por esperado, Chi-cuadrado por varianza, el Chi-cuadrado, los grados de libertad,

  lr=survdiff(Surv(df$time,df$DEATH_EVENT)~sex,data=df)
  lr
## Call:
## survdiff(formula = Surv(df$time, df$DEATH_EVENT) ~ sex, data = df)
## 
##         N Observed Expected (O-E)^2/E (O-E)^2/V
## sex=0 105       71     72.1   0.01593     0.026
## sex=1 194      132    130.9   0.00877     0.026
## 
##  Chisq= 0  on 1 degrees of freedom, p= 0.9
  alpha=0.05
  qchisq(p=1-alpha,df=1)
## [1] 3.841459

Se evidencia que el resultado del p=0.9, un valor considerado muy alto, lo cual nos indica que no hay evidencia estadística suficiente para rechazar la hipótesis nula

Gráfica de funciones de análisis de supervivencia

Eventos acumulados

 ggsurvplot(km2,
 risk.table.col = "strata",
 palette = c("pink","purple"),
 fun = "event")

En la gráfica anterior se presenta la probabilidad acumuda del evento, respecto al sexo 0 y sexo 1. A medida que avanza el tiempo se evidencia que la supervivencia de los grupos en el tiempo 0 a 100 ha tenido un aumento no tan significativo como el que tuvo posteriormente.

Función de riesgo acumulado

ggsurvplot(km2,
 risk.table.col = "strata",
 palette = c("pink","purple"),
 fun = "cumhaz")

Podemos observar el aumento del riesgo total acumulado para un grupo de pacientes.