Estos son los paquetes con los que estaremos trabajando

#instalar paquetes
install.packages("tidyverse")
## Installing package into '/cloud/lib/x86_64-pc-linux-gnu-library/4.3'
## (as 'lib' is unspecified)
install.packages("lubridate")
## Installing package into '/cloud/lib/x86_64-pc-linux-gnu-library/4.3'
## (as 'lib' is unspecified)
install.packages("readxl")
## Installing package into '/cloud/lib/x86_64-pc-linux-gnu-library/4.3'
## (as 'lib' is unspecified)
install.packages("gtsummary")
## Installing package into '/cloud/lib/x86_64-pc-linux-gnu-library/4.3'
## (as 'lib' is unspecified)
# Carga de librerías
library(tidyverse)
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr     1.1.3     ✔ readr     2.1.4
## ✔ forcats   1.0.0     ✔ stringr   1.5.0
## ✔ ggplot2   3.4.4     ✔ tibble    3.2.1
## ✔ lubridate 1.9.3     ✔ tidyr     1.3.0
## ✔ purrr     1.0.2
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag()    masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(lubridate)
library(readxl)
library(gtsummary)

Abrimos la base de datos:

# leer el archivo de Excel
df <- read_excel("Retiros_datos.xlsx")

1. determinamos días transcurridos entre fechas

# Convirtiendo las columnas a formato fecha
df <- df %>%
  mutate(`F. APLIC.` = as.Date(`F. APLIC.`),
         FECHA = as.Date(FECHA))
# Calculando los días que transcurrieron
df <- df %>%
  mutate(dias_transcurridos = as.numeric(difftime(FECHA, `F. APLIC.`, units = "days")))

2. Renombrar la columna “GESTAS”

# Renombrando valores en la columna GESTAS
df <- df %>%
  mutate(GESTAS = case_when(
    GESTAS == 0 ~ "nuligesta",
    GESTAS == 1 ~ "primigesta",
    GESTAS >= 2 ~ "multigesta",
    TRUE ~ as.character(GESTAS)  # En caso de que haya otros valores no especificados
  ))

3. Ganancia de peso

# Calculando la ganancia de peso
df <- df %>%
  mutate(ganancia_peso = PESO2 - PESO)

4. Categorizar los motivos

# Categorizando los motivos
df <- df %>%
  mutate(motivo_categoria = case_when(
    MOTIVOS %in% c("RECAMBIO", "CADUCIDA", "DESEO DE EMBARAZO", "OTROS MOTIVOS", "HISTERECTOMIA", "CAMBIO DE METODO", "CADUCIDAD") ~ "NO EFECTO SECUNDARIO",
    TRUE ~ "EFECTO SECUNDARIO"
  ))

5. Codificación de efectos secundarios

# Codificando la columna motivo_categoria
df <- df %>%
  mutate(codigo_efecto_secundario = ifelse(motivo_categoria == "EFECTO SECUNDARIO", 1, 0))

# Mostrando las primeras filas del dataframe procesado
head(df)
## # A tibble: 6 × 21
##     AÑO `NOMBRE DEL PACIENTE`  `F. APLIC.` GESTAS  PESO MENARCA  IVSA FRECUENCIA
##   <dbl> <chr>                  <date>      <chr>  <dbl>   <dbl> <dbl> <chr>     
## 1  2018 ACOSTA HEREDIA CAREM … 2018-01-16  multi…  68.7      14    17 NORMAL    
## 2  2018 ALVAREZ VALENZUELA DI… 2018-01-25  primi…  79.4      12    22 NORMAL    
## 3  2018 GUILLEN OBESO MARGARI… 2018-01-29  primi…  63.3       9    18 PROLONGADO
## 4  2018 VERDUGO VITAL CRISTAL… 2018-02-01  nulig…  68        12    18 NORMAL    
## 5  2018 RAMIREZ LOPEZ MARCELA  2018-02-08  nulig…  57.6      12    16 NORMAL    
## 6  2018 HERRERA MENDOZA GEMMA… 2018-02-14  multi…  59.5      12    15 NORMAL    
## # ℹ 13 more variables: CANTIDAD <chr>, CEFALEA <chr>, MAREOS <chr>,
## #   NAUSEA <chr>, MASTALGIA <chr>, FECHA <date>, MOTIVOS <chr>, PESO2 <dbl>,
## #   EDAD <dbl>, dias_transcurridos <dbl>, ganancia_peso <dbl>,
## #   motivo_categoria <chr>, codigo_efecto_secundario <dbl>
colnames(df)
##  [1] "AÑO"                      "NOMBRE DEL PACIENTE"     
##  [3] "F. APLIC."                "GESTAS"                  
##  [5] "PESO"                     "MENARCA"                 
##  [7] "IVSA"                     "FRECUENCIA"              
##  [9] "CANTIDAD"                 "CEFALEA"                 
## [11] "MAREOS"                   "NAUSEA"                  
## [13] "MASTALGIA"                "FECHA"                   
## [15] "MOTIVOS"                  "PESO2"                   
## [17] "EDAD"                     "dias_transcurridos"      
## [19] "ganancia_peso"            "motivo_categoria"        
## [21] "codigo_efecto_secundario"

Análisis exploratorio

df %>% select(GESTAS,EDAD, PESO,PESO2,ganancia_peso,MENARCA,IVSA,CEFALEA,MAREOS,NAUSEA,MASTALGIA,MOTIVOS,motivo_categoria) %>% tbl_summary() 
Characteristic N = 931
GESTAS
    multigesta 29 (31%)
    nuligesta 22 (24%)
    primigesta 42 (45%)
EDAD 27 (24, 30)
PESO 63 (55, 69)
PESO2 66 (59, 71)
    Unknown 26
ganancia_peso 1.6 (0.0, 5.2)
    Unknown 26
MENARCA
    9 1 (1.1%)
    10 5 (5.4%)
    11 11 (12%)
    12 28 (30%)
    13 14 (15%)
    14 22 (24%)
    15 8 (8.6%)
    16 3 (3.2%)
    17 1 (1.1%)
IVSA 18.00 (17.00, 19.00)
CEFALEA
    NO 88 (95%)
    SI 5 (5.4%)
MAREOS
    NO 89 (96%)
    SI 4 (4.3%)
NAUSEA
    NO 93 (100%)
MASTALGIA
    NO 86 (92%)
    SI 7 (7.5%)
MOTIVOS
    ANSIEDAD Y DEPRESION 2 (2.2%)
    AUMENTO DE PESO 2 (2.2%)
    CADUCIDAD 26 (28%)
    CAMBIO DE METODO 1 (1.1%)
    CEFALEA INTENSA 18 (19%)
    DESEO DE EMBARAZO 13 (14%)
    HISTERECTOMIA 1 (1.1%)
    OTROS MOTIVOS 3 (3.2%)
    RECAMBIO 15 (16%)
    TRANSTORNO MENSTRUAL 10 (11%)
    TRANSTORNO MESTRUAL 2 (2.2%)
motivo_categoria
    EFECTO SECUNDARIO 34 (37%)
    NO EFECTO SECUNDARIO 59 (63%)
1 n (%); Median (IQR)
# Calculando frecuencias y porcentajes
motivo_counts <- df %>%
  count(motivo_categoria) %>%
  mutate(percent = n / sum(n) * 100)

# Uniendo los valores de frecuencia y porcentaje en una sola etiqueta
motivo_counts <- motivo_counts %>%
  mutate(label = paste(n, "(", sprintf("%.1f", percent), "%)", sep = ""))

# Generando la gráfica
ggplot(motivo_counts, aes(x = motivo_categoria, y = n, fill = motivo_categoria)) +
  geom_bar(stat = "identity") +
  geom_text(aes(label = label), vjust = -0.3, size = 3.5) +
  labs(title = "Frecuencia y Porcentaje por Categoría de Motivo",
       x = "Categoría de Motivo",
       y = "Frecuencia") +
  theme_minimal() +
  theme(legend.title = element_blank())  # Oculta la leyenda de título si es necesario

# Creando los grupos de edad
df <- df %>%
  mutate(grupo_edad = case_when(
    EDAD < 25 ~ "< 25 AÑOS",
    EDAD >= 25 & EDAD <= 35 ~ "25 A 35 AÑOS",
    EDAD > 35 ~ "> 35 AÑOS",
    TRUE ~ "EDAD NO ESPECIFICADA"  # Para cualquier edad que no esté definida en los rangos
  ))

glimpse(df$grupo_edad)
##  chr [1:93] "25 A 35 AÑOS" "25 A 35 AÑOS" "< 25 AÑOS" "25 A 35 AÑOS" ...
unique(df$grupo_edad)
## [1] "25 A 35 AÑOS" "< 25 AÑOS"    "> 35 AÑOS"
str(df)
## tibble [93 × 22] (S3: tbl_df/tbl/data.frame)
##  $ AÑO                     : num [1:93] 2018 2018 2018 2018 2018 ...
##  $ NOMBRE DEL PACIENTE     : chr [1:93] "ACOSTA HEREDIA CAREM SUJEY" "ALVAREZ VALENZUELA DIGNORA GPE." "GUILLEN OBESO MARGARITA" "VERDUGO VITAL CRISTAL VIANEY" ...
##  $ F. APLIC.               : Date[1:93], format: "2018-01-16" "2018-01-25" ...
##  $ GESTAS                  : chr [1:93] "multigesta" "primigesta" "primigesta" "nuligesta" ...
##  $ PESO                    : num [1:93] 68.7 79.4 63.3 68 57.6 59.5 69.1 65 55.1 63.8 ...
##  $ MENARCA                 : num [1:93] 14 12 9 12 12 12 13 12 14 14 ...
##  $ IVSA                    : num [1:93] 17 22 18 18 16 15 20 15 23 18 ...
##  $ FRECUENCIA              : chr [1:93] "NORMAL" "NORMAL" "PROLONGADO" "NORMAL" ...
##  $ CANTIDAD                : chr [1:93] "ESCASA" "ABUNDANTES" "ESCASA" "ESCASA" ...
##  $ CEFALEA                 : chr [1:93] "NO" "NO" "NO" "NO" ...
##  $ MAREOS                  : chr [1:93] "NO" "NO" "NO" "NO" ...
##  $ NAUSEA                  : chr [1:93] "NO" "NO" "NO" "NO" ...
##  $ MASTALGIA               : chr [1:93] "NO" "NO" "NO" "NO" ...
##  $ FECHA                   : Date[1:93], format: "2018-01-16" "2019-01-10" ...
##  $ MOTIVOS                 : chr [1:93] "RECAMBIO" "TRANSTORNO MENSTRUAL" "AUMENTO DE PESO" "RECAMBIO" ...
##  $ PESO2                   : num [1:93] 70 76.2 76.4 NA NA 61.1 69 NA NA NA ...
##  $ EDAD                    : num [1:93] 33 27 21 27 29 32 27 27 42 29 ...
##  $ dias_transcurridos      : num [1:93] 0 350 576 0 159 ...
##  $ ganancia_peso           : num [1:93] 1.3 -3.2 13.1 NA NA ...
##  $ motivo_categoria        : chr [1:93] "NO EFECTO SECUNDARIO" "EFECTO SECUNDARIO" "EFECTO SECUNDARIO" "NO EFECTO SECUNDARIO" ...
##  $ codigo_efecto_secundario: num [1:93] 0 1 1 0 0 1 0 0 0 1 ...
##  $ grupo_edad              : chr [1:93] "25 A 35 AÑOS" "25 A 35 AÑOS" "< 25 AÑOS" "25 A 35 AÑOS" ...
# Calculando frecuencias y porcentajes
grupo_edadcounts <- df %>%
  count(grupo_edad) %>%
  mutate(percent = n / sum(n) * 100)

# Uniendo los valores de frecuencia y porcentaje en una sola etiqueta
grupo_edadcounts <- grupo_edadcounts %>%
  mutate(label = paste(n, "(", sprintf("%.1f", percent), "%)", sep = ""))

# Convirtiendo la columna 'grupo_edad' a un factor con niveles ordenados
df$grupo_edad <- factor(df$grupo_edad, levels = c("< 25 AÑOS", "25 A 35 AÑOS", "> 35 AÑOS"))

# Generando la gráfica
ggplot(grupo_edadcounts, aes(x = grupo_edad, y = n, fill = grupo_edad)) +
  geom_bar(stat = "identity") +
  geom_text(aes(label = label), vjust = -0.3, size = 3.5) +
  labs(title = "Frecuencia y Porcentaje por grupo de edad",
       x = "Grupos de edad",
       y = "Frecuencia") +
  theme_minimal() +
  theme(legend.title = element_blank())  # Oculta la leyenda de título si es necesario

df %>% select(grupo_edad, GESTAS, CEFALEA, MAREOS, NAUSEA, MASTALGIA, motivo_categoria, MOTIVOS) %>% tbl_summary(by=grupo_edad) %>% add_p() %>% add_overall()
## There was an error in 'add_p()/add_difference()' for variable 'NAUSEA', p-value omitted:
## Error in stats::chisq.test(x = c("NO", "NO", "NO", "NO", "NO", "NO", "NO", : 'x' and 'y' must have at least 2 levels
## There was an error in 'add_p()/add_difference()' for variable 'MOTIVOS', p-value omitted:
## Error in stats::fisher.test(c("RECAMBIO", "TRANSTORNO MENSTRUAL", "AUMENTO DE PESO", : FEXACT error 7(location). LDSTP=18630 is too small for this problem,
##   (pastp=11.0031, ipn_0:=ipoin[itp=65]=4591, stp[ipn_0]=14.2989).
## Increase workspace or consider using 'simulate.p.value=TRUE'
Characteristic Overall, N = 931 < 25 AÑOS, N = 241 25 A 35 AÑOS, N = 581 > 35 AÑOS, N = 111 p-value2
GESTAS



<0.001
    multigesta 29 (31%) 2 (8.3%) 20 (34%) 7 (64%)
    nuligesta 22 (24%) 10 (42%) 8 (14%) 4 (36%)
    primigesta 42 (45%) 12 (50%) 30 (52%) 0 (0%)
CEFALEA



0.8
    NO 88 (95%) 22 (92%) 55 (95%) 11 (100%)
    SI 5 (5.4%) 2 (8.3%) 3 (5.2%) 0 (0%)
MAREOS



0.7
    NO 89 (96%) 22 (92%) 56 (97%) 11 (100%)
    SI 4 (4.3%) 2 (8.3%) 2 (3.4%) 0 (0%)
NAUSEA




    NO 93 (100%) 24 (100%) 58 (100%) 11 (100%)
MASTALGIA



>0.9
    NO 86 (92%) 22 (92%) 54 (93%) 10 (91%)
    SI 7 (7.5%) 2 (8.3%) 4 (6.9%) 1 (9.1%)
motivo_categoria



>0.9
    EFECTO SECUNDARIO 34 (37%) 9 (38%) 21 (36%) 4 (36%)
    NO EFECTO SECUNDARIO 59 (63%) 15 (63%) 37 (64%) 7 (64%)
MOTIVOS




    ANSIEDAD Y DEPRESION 2 (2.2%) 0 (0%) 2 (3.4%) 0 (0%)
    AUMENTO DE PESO 2 (2.2%) 2 (8.3%) 0 (0%) 0 (0%)
    CADUCIDAD 26 (28%) 9 (38%) 15 (26%) 2 (18%)
    CAMBIO DE METODO 1 (1.1%) 0 (0%) 1 (1.7%) 0 (0%)
    CEFALEA INTENSA 18 (19%) 5 (21%) 13 (22%) 0 (0%)
    DESEO DE EMBARAZO 13 (14%) 3 (13%) 10 (17%) 0 (0%)
    HISTERECTOMIA 1 (1.1%) 0 (0%) 0 (0%) 1 (9.1%)
    OTROS MOTIVOS 3 (3.2%) 0 (0%) 2 (3.4%) 1 (9.1%)
    RECAMBIO 15 (16%) 3 (13%) 9 (16%) 3 (27%)
    TRANSTORNO MENSTRUAL 10 (11%) 2 (8.3%) 5 (8.6%) 3 (27%)
    TRANSTORNO MESTRUAL 2 (2.2%) 0 (0%) 1 (1.7%) 1 (9.1%)
1 n (%)
2 Fisher’s exact test
# Cargando las librerías necesarias
library(survival)
#install.packages("survminer")
library(survminer)
## Loading required package: ggpubr
## 
## Attaching package: 'survminer'
## The following object is masked from 'package:survival':
## 
##     myeloma
# Ajustando el modelo de Kaplan-Meier
km_fit <- survfit(Surv(dias_transcurridos, codigo_efecto_secundario) ~ grupo_edad, data = df)

# Calculando el riesgo acumulado
risks <- summary(km_fit, times = c(1:max(df$dias_transcurridos)), censored = TRUE)

# Creando la gráfica del riesgo acumulado
ggsurvplot(km_fit, 
           fun = "cumhaz",                    # Cambiando la función de supervivencia por la de riesgo acumulado
           data = df,
           pval = FALSE,
           risk.table = FALSE,
           conf.int = FALSE,
           palette = "Dark2",
           title = "Curva de Riesgo Acumulado de Efectos Adversos según Grupo de Edad",
           xlab = "Días hasta el retiro",
           ylab = "Riesgo Acumulado de Efectos Adversos",
           risk.table.height = 0.2,           # Ajustando la altura de la tabla de riesgo
           surv.median.line = "none",         # No mostrar la línea de la mediana
           break.time.by = 100)               # Intervalos para la tabla de riesgo

# `codigo_efecto_secundario` debería ser un factor donde 1 indica un evento (efecto adverso) y 0 censura.
# Asegurándonos de que GESTAS es un factor
df$GESTAS <- factor(df$GESTAS, levels = c("nuligesta", "primigesta", "multigesta"))

# Ajustando el modelo de Kaplan-Meier por número de gestas
km_fit_gestas <- survfit(Surv(dias_transcurridos, codigo_efecto_secundario) ~ GESTAS, data = df)

# Creando la gráfica del riesgo acumulado por número de gestas
ggsurvplot(km_fit_gestas, 
           fun = "cumhaz",                    # Función de riesgo acumulado
           data = df,
           pval = FALSE,
           risk.table = FALSE,
           conf.int = FALSE,
           palette = "Dark2",
           title = "Curva de Riesgo Acumulado de Efectos Adversos según Número de Gestas",
           xlab = "Días hasta el retiro",
           ylab = "Riesgo Acumulado de Efectos Adversos",
           risk.table.height = 0.2,           # Ajuste de la altura de la tabla de riesgo
           surv.median.line = "none",         # No mostrar la línea de la mediana
           break.time.by = 100)               # Intervalos para la tabla de riesgo