análisis_Dra.Ana_PEMEX

Limpieza y Codificación de Variables Demográficas

Carga y limpieza inicial de la base de datos

# 1. Cargar la base de datos desde Excel
Turbo_base_de_datos_de_Anna_ahora_si_sale_por_que_sale_la_tesis_version_1_1 <- read_excel("C:/Users/fidel/OneDrive - UNIVERSIDAD AUTONOMA DE SINALOA/MDATOS/Mdatos Dra Pemex nuevo/Turbo base de datos de Anna, ahora si sale por que sale la tesis (version 1) 1.xlsx")
New names:
• `` -> `...25`
df <- Turbo_base_de_datos_de_Anna_ahora_si_sale_por_que_sale_la_tesis_version_1_1
# 2. Eliminar la primera fila (cabecera descriptiva)
df <- df[-1, ]

# 3. Normalizar nombres de columnas para facilidad de uso
df <- clean_names(df)
#View(df)
# 4. Conversión y recodificación de variables principales

# Edad
df$edad <- as.numeric(df$edad)


# Sexo: 1 = Femenino, 2 = Masculino
df$sexo <- dplyr::case_when(
  trimws(df$sexo) == "1" ~ "Femenino",
  trimws(df$sexo) == "2" ~ "Masculino",
  trimws(df$sexo) == "3" ~ "Masculino",
  TRUE ~ NA_character_
)

# Uso de Metformina: 1 = Sí, 0/2 = No
df$uso_de_metformina <- dplyr::case_when(
  trimws(df$uso_de_metformina) == "1" ~ "Sí",
  trimws(df$uso_de_metformina) %in% c("0", "2") ~ "No",
  TRUE ~ NA_character_
)

# Uso de aspirina: 1 = Sí, 0/2 = No
df$uso_de_aspirina <- dplyr::case_when(
  trimws(df$uso_de_aspirina) == "1" ~ "Sí",
  trimws(df$uso_de_aspirina) %in% c("0", "2") ~ "No",
  TRUE ~ NA_character_
)

# Mortalidad 30 días: 1 = Fallecido, 0 = Sobreviviente
df$murio_antes_de_30_dias <- dplyr::case_when(
  trimws(df$murio_antes_de_30_dias) == "1" ~ "Fallecido",
  trimws(df$murio_antes_de_30_dias) == "0" ~ "Sobreviviente",
  trimws(df$murio_antes_de_30_dias) %in% c("0", "2") ~ "Sobreviviente",
  TRUE ~ NA_character_
)

# Diabetes
df$diabetes <- dplyr::case_when(
  trimws(df$diabetes) == "1" ~ "Sí",
  trimws(df$diabetes) == "0" ~ "No",
  trimws(df$diabetes) == "2" ~ "No",
  TRUE ~ NA_character_
)


# recodificación de la variable es 'hbac':
df$hbac <- as.numeric(ifelse(df$hbac == "X" | trimws(df$hbac) == "", NA, df$hbac))
Warning: NAs introducidos por coerción
#Recodificación de la variable sepsis
df$origen_de_la_sepsis <- dplyr::case_when(
  trimws(df$origen_de_la_sepsis) == "1" ~ "Urinario",
  trimws(df$origen_de_la_sepsis) == "2" ~ "Pulmonar",
  trimws(df$origen_de_la_sepsis) == "3" ~ "Tejidos",
  trimws(df$origen_de_la_sepsis) == "4" ~ "Abdominal",
  trimws(df$origen_de_la_sepsis) == "5" ~ "Protesis",
  trimws(df$origen_de_la_sepsis) == "6" ~ "Sitio Qx",
  trimws(df$origen_de_la_sepsis) == "7" ~ "Otico",
  TRUE ~ NA_character_
)

# Uso de aspirina: 1 = Sí, 0/2 = No
df$choque <- dplyr::case_when(
  trimws(df$choque) == "1" ~ "Sí",
  trimws(df$choque) %in% c("0", "2") ~ "No",
  TRUE ~ NA_character_
)
#arreglo días de hospitalización
df$dias_de_hospitalizacion <- as.numeric(df$dias_de_hospitalizacion)

#recodificar la variable cultivo y que los valores que sean guion ("-") o espacios en blanco se transformen en NA
df$cultivo <- ifelse(trimws(df$cultivo) == "-" | trimws(df$cultivo) == "", NA, trimws(df$cultivo))

# Opcional: Filtrar solo pacientes con edad válida
#df <- df %>% filter(!is.na(edad))

#limpieza variables númericas
# Lista de variables a limpiar
vars_numericas <- c("leucos", "neu", "lin", "hb", "ade", "plq", "glu", "crea")

# Limpieza: convertir a numérico y los vacíos a NA
for (var in vars_numericas) {
  df[[var]] <- as.numeric(ifelse(trimws(df[[var]]) == "", NA, df[[var]]))
}
Warning: NAs introducidos por coerción
Warning: NAs introducidos por coerción
Warning: NAs introducidos por coerción
Warning: NAs introducidos por coerción
# Opcional: resumen para verificar que todo esté correcto
summary(df[, vars_numericas])
     leucos            neu             lin                hb      
 Min.   : 0.000   Min.   : 0.00   Min.   :  0.000   Min.   : 0.0  
 1st Qu.: 8.557   1st Qu.: 7.10   1st Qu.:  0.590   1st Qu.:10.1  
 Median :13.995   Median :11.84   Median :  0.980   Median :12.4  
 Mean   :14.753   Mean   :12.74   Mean   :  2.494   Mean   :12.3  
 3rd Qu.:19.587   3rd Qu.:17.40   3rd Qu.:  1.640   3rd Qu.:14.5  
 Max.   :55.480   Max.   :54.51   Max.   :200.000   Max.   :19.3  
                  NA's   :1       NA's   :1         NA's   :1     
      ade              plq             glu             crea        
 Min.   :  0.00   Min.   :  0.0   Min.   :  0.0   Min.   :  0.000  
 1st Qu.: 13.70   1st Qu.:150.0   1st Qu.:105.0   1st Qu.:  0.900  
 Median : 15.00   Median :217.0   Median :140.0   Median :  1.480  
 Mean   : 17.92   Mean   :236.9   Mean   :166.6   Mean   :  4.063  
 3rd Qu.: 17.00   3rd Qu.:309.0   3rd Qu.:187.0   3rd Qu.:  2.290  
 Max.   :174.10   Max.   :795.0   Max.   :799.0   Max.   :169.000  
 NA's   :1        NA's   :1       NA's   :3       NA's   :1        
df$lra <- dplyr::case_when(
  trimws(df$lra) == "1" ~ "Sí",
  trimws(df$lra) == "2" ~ "No",
    trimws(df$lra) %in% c("0", "2") ~ "No",
  TRUE ~ NA_character_
)

df$kdigo <- dplyr::case_when(
  trimws(df$kdigo) == "1" ~ "I",
  trimws(df$kdigo) == "2" ~ "II",
  trimws(df$kdigo) == "3" ~ "III",
  trimws(df$kdigo) == "0" | trimws(df$kdigo) == "" ~ NA_character_,  # O puedes poner "Sin Lesión"
  TRUE ~ NA_character_
)


# Vista preliminar de la base procesada
summary(df)
     numero          ficha           dias_de_hospitalizacion
 Min.   :  1.00   Length:190         Min.   : 1.000         
 1st Qu.: 48.25   Class :character   1st Qu.: 3.000         
 Median : 95.50   Mode  :character   Median : 7.000         
 Mean   :111.98                      Mean   : 9.253         
 3rd Qu.:188.75                      3rd Qu.:11.000         
 Max.   :254.00                      Max.   :56.000         
                                                            
 murio_antes_de_30_dias      edad            sexo             diabetes        
 Length:190             Min.   : 31.00   Length:190         Length:190        
 Class :character       1st Qu.: 71.25   Class :character   Class :character  
 Mode  :character       Median : 80.00   Mode  :character   Mode  :character  
                        Mean   : 77.23                                        
                        3rd Qu.: 86.75                                        
                        Max.   :102.00                                        
                                                                              
      hbac        uso_de_metformina  uso_de_aspirina    origen_de_la_sepsis
 Min.   : 0.000   Length:190         Length:190         Length:190         
 1st Qu.: 5.975   Class :character   Class :character   Class :character   
 Median : 6.750   Mode  :character   Mode  :character   Mode  :character   
 Mean   : 6.419                                                            
 3rd Qu.: 7.875                                                            
 Max.   :12.500                                                            
 NA's   :136                                                               
    choque            cultivo            lactato              leucos      
 Length:190         Length:190         Length:190         Min.   : 0.000  
 Class :character   Class :character   Class :character   1st Qu.: 8.557  
 Mode  :character   Mode  :character   Mode  :character   Median :13.995  
                                                          Mean   :14.753  
                                                          3rd Qu.:19.587  
                                                          Max.   :55.480  
                                                                          
      neu             lin                hb            ade        
 Min.   : 0.00   Min.   :  0.000   Min.   : 0.0   Min.   :  0.00  
 1st Qu.: 7.10   1st Qu.:  0.590   1st Qu.:10.1   1st Qu.: 13.70  
 Median :11.84   Median :  0.980   Median :12.4   Median : 15.00  
 Mean   :12.74   Mean   :  2.494   Mean   :12.3   Mean   : 17.92  
 3rd Qu.:17.40   3rd Qu.:  1.640   3rd Qu.:14.5   3rd Qu.: 17.00  
 Max.   :54.51   Max.   :200.000   Max.   :19.3   Max.   :174.10  
 NA's   :1       NA's   :1         NA's   :1      NA's   :1       
      plq             glu             crea             lra           
 Min.   :  0.0   Min.   :  0.0   Min.   :  0.000   Length:190        
 1st Qu.:150.0   1st Qu.:105.0   1st Qu.:  0.900   Class :character  
 Median :217.0   Median :140.0   Median :  1.480   Mode  :character  
 Mean   :236.9   Mean   :166.6   Mean   :  4.063                     
 3rd Qu.:309.0   3rd Qu.:187.0   3rd Qu.:  2.290                     
 Max.   :795.0   Max.   :799.0   Max.   :169.000                     
 NA's   :1       NA's   :3       NA's   :1                           
    kdigo               x25           
 Length:190         Length:190        
 Class :character   Class :character  
 Mode  :character   Mode  :character  
                                      
                                      
                                      
                                      
str(df
    )
tibble [190 × 25] (S3: tbl_df/tbl/data.frame)
 $ numero                 : num [1:190] 6 7 16 17 21 26 30 35 40 44 ...
 $ ficha                  : chr [1:190] "077240-08" "076558-00" "231380-08" "200041-00" ...
 $ dias_de_hospitalizacion: num [1:190] 9 10 3 7 20 2 2 18 4 4 ...
 $ murio_antes_de_30_dias : chr [1:190] "Fallecido" "Sobreviviente" "Sobreviviente" "Fallecido" ...
 $ edad                   : num [1:190] 73 79 74 77 52 86 84 80 72 82 ...
 $ sexo                   : chr [1:190] "Femenino" "Masculino" "Femenino" "Femenino" ...
 $ diabetes               : chr [1:190] "Sí" "Sí" "Sí" "Sí" ...
 $ hbac                   : num [1:190] NA NA 7.4 NA NA NA NA NA 6.7 6.3 ...
 $ uso_de_metformina      : chr [1:190] "Sí" "Sí" "Sí" "Sí" ...
 $ uso_de_aspirina        : chr [1:190] "Sí" "No" "No" "No" ...
 $ origen_de_la_sepsis    : chr [1:190] "Tejidos" "Urinario" "Abdominal" NA ...
 $ choque                 : chr [1:190] "No" "No" "No" "No" ...
 $ cultivo                : chr [1:190] NA NA NA NA ...
 $ lactato                : chr [1:190] NA NA "19.86" NA ...
 $ leucos                 : num [1:190] 7.95 20 17.54 22.81 12.4 ...
 $ neu                    : num [1:190] 5.61 17.3 1.4 20.85 10.98 ...
 $ lin                    : num [1:190] 1.72 1.9 14.6 0.87 0.65 0.4 1.97 1.31 0.6 1.3 ...
 $ hb                     : num [1:190] 8.5 5.6 10.7 8.8 14.8 10.1 8.7 11.1 12.8 13.1 ...
 $ ade                    : num [1:190] 14.3 14.8 15.1 14.4 16.6 16.3 19.1 13.8 17.4 16.5 ...
 $ plq                    : num [1:190] 294 347 335 235 161 159 343 291 156 260 ...
 $ glu                    : num [1:190] 132 412 186 106 164 344 166 291 266 154 ...
 $ crea                   : num [1:190] 0.85 2.29 0.89 0.49 1.77 1.16 1.39 1.97 2.05 0.87 ...
 $ lra                    : chr [1:190] "No" "Sí" "No" "No" ...
 $ kdigo                  : chr [1:190] NA "III" NA NA ...
 $ x25                    : chr [1:190] "PROC 1.33" NA NA "3.28" ...

Análisis de Variables demógraficas

#tabla sexo general
df %>% select(sexo) %>% tbl_summary()
Characteristic N = 1901
sexo
    Femenino 125 (66%)
    Masculino 65 (34%)
1 n (%)
# Promedio de edad general
df %>% select(edad) %>% tbl_summary()
Characteristic N = 1901
edad 80 (71, 87)
1 Median (Q1, Q3)
# Paleta de colores pastel formal (usaremos manualmente para consistencia)
paleta_pastel <- c("#C2DFFF", "#E6B0AA") # azul pastel y rosa pastel, por ejemplo

# Gráfica de pastel de sexo
sexo_data <- df %>%
  count(sexo) %>%
  mutate(perc = n / sum(n),
         label = paste0(sexo, " (", percent(perc), ")"))

ggplot(sexo_data, aes(x = "", y = n, fill = sexo)) +
  geom_col(width = 1, color = "white") +
  coord_polar(theta = "y") +
  scale_fill_manual(values = paleta_pastel) +
  labs(title = "Distribución de Sexo", fill = "Sexo") +
  geom_text(aes(label = label), position = position_stack(vjust = 0.5), color = "black", size = 5) +
  theme_void() +
  theme(legend.position = "bottom",
        plot.title = element_text(hjust = 0.5, size = 18),
        legend.title = element_text(size = 14),
        legend.text = element_text(size = 12))

# Boxplot de edad por sexo
ggplot(df, aes(x = sexo, y = edad, fill = sexo)) +
  geom_boxplot(alpha = 0.85, color = "gray40", outlier.color = "gray40") +
  scale_fill_manual(values = paleta_pastel) +
  labs(
    title = "Distribución de la Edad por Sexo",
    x = "Sexo",
    y = "Edad (años)"
  ) +
  theme_minimal(base_size = 15) +
  theme(
    plot.title = element_text(hjust = 0.5, size = 18),
    axis.title = element_text(size = 14),
    axis.text = element_text(size = 12),
    legend.position = "none"
  )

#tabla edad x sexo

df %>% select(edad, sexo) %>% tbl_summary(by= sexo) %>% add_p()
Characteristic Femenino
N = 1251
Masculino
N = 651
p-value2
edad 81 (72, 86) 79 (71, 88) 0.9
1 Median (Q1, Q3)
2 Wilcoxon rank sum test

análisis de variables clínicas general

df %>% 
  select(diabetes, hbac, uso_de_metformina, uso_de_aspirina, origen_de_la_sepsis, choque) %>%  tbl_summary(missing = "no")
Characteristic N = 1901
diabetes
    No 73 (38%)
    Sí 117 (62%)
hbac 6.8 (5.9, 7.9)
uso_de_metformina
    No 95 (50%)
    Sí 95 (50%)
uso_de_aspirina
    No 163 (87%)
    Sí 25 (13%)
origen_de_la_sepsis
    Abdominal 19 (11%)
    Otico 2 (1.1%)
    Protesis 3 (1.7%)
    Pulmonar 49 (28%)
    Sitio Qx 2 (1.1%)
    Tejidos 16 (9.1%)
    Urinario 84 (48%)
choque
    No 86 (46%)
    Sí 102 (54%)
1 n (%); Median (Q1, Q3)

grafica de sitio infeccion:

# Paquetes requeridos
library(ggplot2)
library(dplyr)
library(scales)

# Suponiendo que tu dataframe se llama df y la variable es "origen_de_la_sepsis"
# Paleta pastel consistente con lo anterior
paleta_sepsis <- c("#C2DFFF", "#E6B0AA", "#B2DFDB", "#FAD7A0", "#D7BDE2", "#F5CBA7", "#A3E4D7")

# Preparar los datos
sepsis_data <- df %>%
  count(origen_de_la_sepsis) %>%
  mutate(perc = n / sum(n),
         label = paste0(n, " (", percent(perc, accuracy = 1), ")"))

# Ordenar por frecuencia descendente
sepsis_data <- sepsis_data %>%
  arrange(desc(n)) %>%
  mutate(origen_de_la_sepsis = factor(origen_de_la_sepsis, levels = origen_de_la_sepsis)) %>%  drop_na()

# Crear el gráfico
ggplot(sepsis_data, aes(x = origen_de_la_sepsis, y = n, fill = origen_de_la_sepsis)) +
  geom_col(width = 0.75, show.legend = FALSE, color = "gray30") +
  scale_fill_manual(values = paleta_sepsis) +
  geom_text(aes(label = label), vjust = -0.2, size = 5, fontface = "bold") +
  labs(
    title = "Distribución del origen de la sepsis",
    x = "Origen de la sepsis",
    y = "Número de casos"
  ) +
  theme_minimal(base_size = 16) +
  theme(
    axis.text.x = element_text(angle = 20, hjust = 1, size = 14),
    axis.title = element_text(size = 15, face = "bold"),
    plot.title = element_text(hjust = 0.5, size = 18, face = "bold")
  )

Grafica metformina

#
df %>% select(uso_de_metformina) %>% tbl_summary()
Characteristic N = 1901
uso_de_metformina
    No 95 (50%)
    Sí 95 (50%)
1 n (%)
# Paleta pastel ya definida
paleta_pastel_metformina <- c("#C2DFFF", "#E6B0AA") # azul pastel, rosa pastel

# Preparar datos de uso de metformina
metformina_data <- df %>%
  count(uso_de_metformina) %>%
  mutate(perc = n / sum(n),
         label = paste0(uso_de_metformina, " (", percent(perc), ")"))

# Gráfico de pastel
ggplot(metformina_data, aes(x = "", y = n, fill = uso_de_metformina)) +
  geom_col(width = 1, color = "white") +
  coord_polar(theta = "y") +
  scale_fill_manual(values = paleta_pastel_metformina) +
  labs(
    title = "Distribución del Uso de Metformina",
    fill = "Uso de Metformina"
  ) +
  geom_text(aes(label = label),
            position = position_stack(vjust = 0.5),
            color = "black",
            size = 5) +
  theme_void() +
  theme(
    legend.position = "bottom",
    plot.title = element_text(hjust = 0.5, size = 18),
    legend.title = element_text(size = 14),
    legend.text = element_text(size = 12)
  )

Superivenciageneral

df %>% select(dias_de_hospitalizacion, murio_antes_de_30_dias) %>% tbl_summary()
Characteristic N = 1901
dias_de_hospitalizacion 7 (3, 11)
murio_antes_de_30_dias
    Fallecido 116 (61%)
    Sobreviviente 74 (39%)
1 Median (Q1, Q3); n (%)

grafica mortalidad

library(ggplot2)
library(dplyr)
library(scales)

# Paleta pastel (puedes ajustar los colores si lo deseas)
paleta_mortalidad <- c("#C2DFFF", "#E6B0AA") # Azul pastel y rosa pastel

# Calcular frecuencias y etiquetas
mortalidad_data <- df %>%
  count(murio_antes_de_30_dias) %>%
  mutate(perc = n / sum(n),
         label = paste0(murio_antes_de_30_dias, " (", percent(perc), ")"))

# Gráfico de barras
ggplot(mortalidad_data, aes(x = murio_antes_de_30_dias, y = n, fill = murio_antes_de_30_dias)) +
  geom_col(width = 0.7, color = "white") +
  scale_fill_manual(values = paleta_mortalidad) +
  labs(
    title = "Distribución de la mortalidad a 30 días",
    x = "Mortalidad a 30 días",
    y = "Número de pacientes"
  ) +
  geom_text(aes(label = label), vjust = -0.4, size = 8, color = "black") +
  theme_minimal(base_size = 20) +
  theme(
    plot.title = element_text(hjust = 0.5, size = 21),
    axis.title = element_text(size = 20),
    axis.text = element_text(size = 20),
    legend.position = "none"
  )

tabla chi cuadrad

df %>% select (uso_de_metformina, murio_antes_de_30_dias) %>% 
  tbl_summary(by=murio_antes_de_30_dias, missing = "no") %>% add_p()
Characteristic Fallecido
N = 1161
Sobreviviente
N = 741
p-value2
uso_de_metformina

<0.001
    No 78 (67%) 17 (23%)
    Sí 38 (33%) 57 (77%)
1 n (%)
2 Pearson’s Chi-squared test

Variables de laboratorio General

vars_numericas <- c("lactato", "leucos", "neu", "lin", "hb", "ade", "plq", "glu", "crea")

# Convierte todas a numérico, si no lo son
df[vars_numericas] <- lapply(df[vars_numericas], function(x) as.numeric(as.character(x)))
Warning in FUN(X[[i]], ...): NAs introducidos por coerción
# Ahora sí, reorganiza a formato largo
library(tidyr)
library(dplyr)

df_long <- df %>%
  select(all_of(vars_numericas)) %>%
  pivot_longer(cols = everything(), names_to = "Variable", values_to = "Valor") %>%
  filter(!is.na(Valor))

# Boxplots facetados
ggplot(df_long, aes(x = "", y = Valor, fill = Variable)) +
  geom_boxplot(width = 0.5, alpha = 0.92, color = "gray40", outlier.color = "gray40", show.legend = FALSE) +
  scale_fill_manual(values = rep("#C2DFFF", length(vars_numericas))) +
  labs(
    title = "Distribución de variables clínicas generales",
    x = NULL,
    y = "Valor"
  ) +
  theme_minimal(base_size = 15) +
  theme(
    plot.title = element_text(hjust = 0.5, size = 18),
    axis.title = element_text(size = 14),
    axis.text.x = element_blank(),    # Oculta etiquetas eje X
    axis.ticks.x = element_blank(),   # Oculta ticks eje X
    strip.text = element_text(size = 13)
  ) +
  facet_wrap(~ Variable, scales = "free_y")

library(ggplot2)
library(tidyr)
library(dplyr)

# Nos aseguramos de que las variables agrupadoras estén como factor para mejor visualización
df$uso_de_metformina <- factor(df$uso_de_metformina, levels = c("No", "Sí"))
df$murio_antes_de_30_dias <- factor(df$murio_antes_de_30_dias, levels = c("Sobreviviente", "Fallecido"))

# Reestructuración a formato largo
df_long_grouped <- df %>%
  select(all_of(vars_numericas), uso_de_metformina, murio_antes_de_30_dias) %>%
  pivot_longer(cols = all_of(vars_numericas), names_to = "Variable", values_to = "Valor") %>%
  filter(!is.na(Valor), !is.na(uso_de_metformina), !is.na(murio_antes_de_30_dias))

# Paleta pastel para los grupos
paleta_metf <- c("#C2DFFF", "#E6B0AA")  # No, Sí

library(ggplot2)
library(tidyr)
library(dplyr)
library(ggpubr)

# Nos aseguramos de que las variables agrupadoras sean factor
df$uso_de_metformina <- factor(df$uso_de_metformina, levels = c("No", "Sí"))
df$murio_antes_de_30_dias <- factor(df$murio_antes_de_30_dias, levels = c("Sobreviviente", "Fallecido"))

# Seleccionamos y transformamos a largo
df_long_grouped <- df %>%
  select(all_of(vars_numericas), uso_de_metformina, murio_antes_de_30_dias) %>%
  pivot_longer(cols = all_of(vars_numericas), names_to = "Variable", values_to = "Valor") %>%
  filter(!is.na(Valor), !is.na(uso_de_metformina), !is.na(murio_antes_de_30_dias))

# Paleta pastel
paleta_metf <- c("#C2DFFF", "#E6B0AA")

# Preparar la lista de comparaciones para los asteriscos
comparisons <- list(c("Sobreviviente", "Fallecido"))

ggplot(df_long_grouped, aes(x = murio_antes_de_30_dias, y = Valor, fill = murio_antes_de_30_dias)) +
  geom_boxplot(width = 0.6, alpha = 0.92, color = "gray40", outlier.color = "gray40") +
  scale_fill_manual(values = paleta_metf) +
  labs(
    title = "Distribución de variables clínicas por mortalidad y uso de metformina",
    x = "Supervivencia a 30 días",
    y = "Valor"
  ) +
  stat_compare_means(
    method = "wilcox.test",
    label = "p.signif",
    hide.ns = TRUE,            # Oculta "ns" (no significativos)
    group.by = "panel",        # Compara por panel (subfaceta)
    label.y.npc = "top",       # Coloca el asterisco arriba del boxplot
    size = 6
  ) +
  theme_minimal(base_size = 15) +
  theme(
    plot.title = element_text(hjust = 0.5, size = 17),
    axis.title = element_text(size = 13),
    axis.text = element_text(size = 11),
    legend.position = "none",
    strip.text = element_text(size = 13),
    axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1, size=13)
  ) +
  facet_grid(uso_de_metformina ~ Variable, scales = "free_y")
Warning in stat_compare_means(method = "wilcox.test", label = "p.signif", :
Ignoring unknown parameters: `group.by`

library(ggplot2)
library(ggpubr)

# Etiquetas personalizadas para metformina
levels(df_long_grouped$uso_de_metformina) <- c("Metformina: No", "Metformina: Sí")

ggplot(df_long_grouped, aes(x = murio_antes_de_30_dias, y = Valor, fill = murio_antes_de_30_dias)) +
  geom_boxplot(width = 0.6, alpha = 0.92, color = "gray40", outlier.color = "gray40") +
  scale_fill_manual(values = paleta_metf) +
  labs(
    title = "Distribución de variables clínicas por mortalidad y uso de metformina",
    x = "Supervivencia a 30 días",
    y = "Valor"
  ) +
  stat_compare_means(
    method = "wilcox.test",
    label = "p.signif",      # muestra *, **, *** según p
    hide.ns = TRUE,          # oculta los "ns"
    group.by = "panel",      # comparación por cada facet
    label.y.npc = "top",     # coloca asterisco arriba del boxplot
    size = 8                 # tamaño grande para visibilidad
  ) +
  theme_minimal(base_size = 20) +
  theme(
    plot.title = element_text(hjust = 0.5, size = 24),
    axis.title = element_text(size = 18),
    axis.text = element_text(size = 15),
    axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1, size=17),
    legend.position = "none",
    strip.text = element_text(size = 21)
  ) +
  facet_grid(uso_de_metformina ~ Variable, scales = "free_y")
Warning in stat_compare_means(method = "wilcox.test", label = "p.signif", :
Ignoring unknown parameters: `group.by`

df %>%  select(murio_antes_de_30_dias,lactato, leucos, neu, lin, hb, ade, plq, glu, crea) %>% 
  tbl_summary(by=murio_antes_de_30_dias, missing = "no") %>% add_p() %>% add_overall
Characteristic Overall
N = 1901
Sobreviviente
N = 741
Fallecido
N = 1161
p-value2
lactato 2.8 (1.8, 6.6) 2.6 (1.8, 3.9) 3.4 (1.8, 6.8) 0.5
leucos 14 (9, 20) 15 (11, 21) 13 (8, 19) 0.028
neu 12 (7, 17) 13 (9, 18) 11 (6, 17) 0.046
lin 0.98 (0.59, 1.64) 1.03 (0.60, 1.67) 0.95 (0.54, 1.62) 0.3
hb 12.40 (10.10, 14.50) 13.10 (10.60, 15.00) 11.90 (9.80, 14.25) 0.028
ade 15.0 (13.7, 17.0) 14.6 (13.4, 15.9) 15.6 (13.8, 17.4) 0.053
plq 217 (150, 309) 240 (181, 313) 209 (127, 295) 0.013
glu 140 (105, 188) 155 (126, 207) 125 (100, 173) <0.001
crea 1.48 (0.90, 2.29) 1.33 (0.90, 2.16) 1.60 (0.88, 2.49) 0.6
1 Median (Q1, Q3)
2 Wilcoxon rank sum test

análisis cruzados del uso variables, demógraficas, clínicas laboratorios de metformina y mortalidad

# Antes de crear la tabla, asegúrate de que hbac es numérica
df <- df %>%
  mutate(hbac = as.numeric(hbac))

df <- df %>%
  mutate(
    hbac = trimws(hbac), # elimina espacios extra
    hbac = na_if(hbac, "N/A"),
    hbac = na_if(hbac, "NA"),
    hbac = na_if(hbac, "--"),
    hbac = na_if(hbac, "ND"),
    hbac = na_if(hbac, ""),
    hbac = as.numeric(hbac)
  )

summary(df$hbac)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.    NA's 
  0.000   5.975   6.750   6.419   7.875  12.500     136 
table(is.na(df$hbac))

FALSE  TRUE 
   54   136 
df %>%
  mutate(hbac = as.numeric(hbac)) %>%
  select(uso_de_metformina, murio_antes_de_30_dias, edad, sexo, diabetes, hbac, uso_de_aspirina, choque, origen_de_la_sepsis) %>%
  tbl_strata(
    strata = uso_de_metformina,
    .tbl_fun = ~ .x %>%
      tbl_summary(
        by = murio_antes_de_30_dias,
        missing = "no",
        statistic = list(
          all_continuous() ~ "{median} ({p25}, {p75})"
        ),
        type = list(
          hbac ~ "continuous"
        ),
        digits = all_continuous() ~ 2
      ) %>%
      add_p()
  ) %>%
  as_gt()
The following warnings were returned during `as_gt()`:
! For variable `hbac` (`murio_antes_de_30_dias`) and "estimate", "statistic",
  "p.value", "conf.low", and "conf.high" statistics: cannot compute exact
  p-value with ties
! For variable `hbac` (`murio_antes_de_30_dias`) and "estimate", "statistic",
  "p.value", "conf.low", and "conf.high" statistics: cannot compute exact
  confidence intervals with ties
The following warnings were returned during `as_gt()`:
! For variable `hbac` (`murio_antes_de_30_dias`) and "estimate", "statistic",
  "p.value", "conf.low", and "conf.high" statistics: cannot compute exact
  p-value with ties
! For variable `hbac` (`murio_antes_de_30_dias`) and "estimate", "statistic",
  "p.value", "conf.low", and "conf.high" statistics: cannot compute exact
  confidence intervals with ties
Characteristic
No
Sobreviviente
N = 171
Fallecido
N = 781
p-value2 Sobreviviente
N = 571
Fallecido
N = 381
p-value2
edad 83.00 (74.00, 87.00) 83.00 (76.00, 88.00) 0.7 74.00 (66.00, 82.00) 79.00 (72.00, 86.00) 0.022
sexo

0.4

0.7
    Femenino 9 (53%) 49 (63%)
41 (72%) 26 (68%)
    Masculino 8 (47%) 29 (37%)
16 (28%) 12 (32%)
diabetes

0.4

0.081
    No 14 (82%) 54 (69%)
5 (8.8%) 0 (0%)
    Sí 3 (18%) 24 (31%)
52 (91%) 38 (100%)
hbac 10.00 (10.00, 10.00) 6.20 (5.70, 7.70) 0.2 7.00 (5.90, 7.90) 6.65 (5.80, 7.90) 0.8
uso_de_aspirina

>0.9

>0.9
    No 15 (88%) 64 (83%)
50 (89%) 34 (89%)
    Sí 2 (12%) 13 (17%)
6 (11%) 4 (11%)
choque

0.006

0.009
    No 13 (76%) 31 (40%)
31 (56%) 11 (29%)
    Sí 4 (24%) 47 (60%)
24 (44%) 27 (71%)
origen_de_la_sepsis

0.3

>0.9
    Abdominal 1 (6.7%) 9 (13%)
5 (9.1%) 4 (12%)
    Protesis 0 (0%) 1 (1.4%)
1 (1.8%) 1 (2.9%)
    Pulmonar 4 (27%) 29 (41%)
9 (16%) 7 (21%)
    Sitio Qx 1 (6.7%) 0 (0%)
1 (1.8%) 0 (0%)
    Tejidos 1 (6.7%) 6 (8.5%)
6 (11%) 3 (8.8%)
    Urinario 8 (53%) 26 (37%)
32 (58%) 18 (53%)
    Otico


1 (1.8%) 1 (2.9%)
1 Median (Q1, Q3); n (%)
2 Wilcoxon rank sum test; Pearson’s Chi-squared test; Fisher’s exact test
df %>%
  select(uso_de_metformina, murio_antes_de_30_dias, lactato, leucos, neu, lin, hb, ade, plq, glu, crea) %>%
  tbl_strata(
    strata = uso_de_metformina,
    .tbl_fun = ~ .x %>%
      tbl_summary(
        by = murio_antes_de_30_dias,
        missing = "no",
        statistic = all_continuous() ~ "{median} ({p25}, {p75})"
      ) %>%
      add_p()
  ) %>%
  as_gt()
The following warnings were returned during `as_gt()`:
! For variable `lactato` (`murio_antes_de_30_dias`) and "estimate",
  "statistic", "p.value", "conf.low", and "conf.high" statistics: cannot
  compute exact p-value with ties
! For variable `lactato` (`murio_antes_de_30_dias`) and "estimate",
  "statistic", "p.value", "conf.low", and "conf.high" statistics: cannot
  compute exact confidence intervals with ties
The following warnings were returned during `as_gt()`:
! For variable `lactato` (`murio_antes_de_30_dias`) and "estimate",
  "statistic", "p.value", "conf.low", and "conf.high" statistics: cannot
  compute exact p-value with ties
! For variable `lactato` (`murio_antes_de_30_dias`) and "estimate",
  "statistic", "p.value", "conf.low", and "conf.high" statistics: cannot
  compute exact confidence intervals with ties
Characteristic
No
Sobreviviente
N = 171
Fallecido
N = 781
p-value2 Sobreviviente
N = 571
Fallecido
N = 381
p-value2
lactato 2.8 (2.5, 3.9) 2.3 (1.8, 6.9) 0.9 2.5 (1.8, 5.2) 3.7 (1.8, 6.6) 0.2
leucos 17 (12, 19) 13 (8, 20) 0.2 15 (11, 22) 10 (7, 19) 0.037
neu 14 (10, 18) 11 (6, 17) 0.2 13 (9, 17) 9 (5, 17) 0.085
lin 1.21 (0.72, 1.59) 1.00 (0.54, 1.60) 0.6 1.02 (0.60, 1.75) 0.90 (0.54, 1.68) 0.4
hb 15.00 (13.50, 17.00) 12.05 (9.70, 14.20) 0.002 12.40 (10.50, 14.60) 11.50 (10.10, 14.50) 0.3
ade 14.6 (13.4, 15.7) 15.3 (13.9, 17.4) 0.2 14.75 (13.55, 16.10) 16.05 (13.70, 17.30) 0.094
plq 244 (204, 311) 209 (124, 289) 0.066 235 (173, 322) 200 (133, 337) 0.2
glu 126 (110, 168) 112 (95, 141) 0.13 175 (133, 239) 164 (115, 243) 0.7
crea 1.18 (0.83, 1.78) 1.50 (0.88, 2.33) 0.4 1.56 (0.92, 2.17) 1.60 (0.99, 2.62) 0.6
1 Median (Q1, Q3)
2 Wilcoxon rank sum test

Análisis de Mortalidad a 30 días

# Paquetes necesarios
library(survival)
library(survminer)

Adjuntando el paquete: 'survminer'
The following object is masked from 'package:survival':

    myeloma
# Definir la variable de evento (1 = fallecido, 0 = sobreviviente)
df$evento <- ifelse(df$murio_antes_de_30_dias == "Fallecido", 1, 0)
df$tiempo <- df$dias_de_hospitalizacion # O la variable de días hasta evento/censura

# 1. Curva Kaplan-Meier por uso de metformina
fit_km_metf <- survfit(Surv(tiempo, evento) ~ uso_de_metformina, data = df)
ggsurvplot(fit_km_metf, data = df, risk.table = TRUE, pval = TRUE,
           palette = c("#C2DFFF", "#E6B0AA"),
           xlab = "Días de hospitalización", ylab = "Supervivencia acumulada",
           legend.title = "Metformina", legend.labs = c("No", "Sí"))

# 2. Modelo de Cox multivariado
cox_model <- coxph(Surv(tiempo, evento) ~ uso_de_metformina + edad + sexo + diabetes + choque, data = df)
summary(cox_model)
Call:
coxph(formula = Surv(tiempo, evento) ~ uso_de_metformina + edad + 
    sexo + diabetes + choque, data = df)

  n= 188, number of events= 116 
   (2 observations deleted due to missingness)

                         coef exp(coef)  se(coef)      z Pr(>|z|)    
uso_de_metforminaSí -0.917738  0.399422  0.230927 -3.974 7.06e-05 ***
edad                 0.033306  1.033867  0.008626  3.861 0.000113 ***
sexoMasculino       -0.019664  0.980529  0.194879 -0.101 0.919629    
diabetesSí          -0.011860  0.988210  0.223520 -0.053 0.957684    
choqueSí             0.640152  1.896768  0.200041  3.200 0.001374 ** 
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

                    exp(coef) exp(-coef) lower .95 upper .95
uso_de_metforminaSí    0.3994     2.5036    0.2540    0.6281
edad                   1.0339     0.9672    1.0165    1.0515
sexoMasculino          0.9805     1.0199    0.6692    1.4366
diabetesSí             0.9882     1.0119    0.6377    1.5315
choqueSí               1.8968     0.5272    1.2816    2.8073

Concordance= 0.689  (se = 0.026 )
Likelihood ratio test= 51.61  on 5 df,   p=6e-10
Wald test            = 44.26  on 5 df,   p=2e-08
Score (logrank) test = 46.57  on 5 df,   p=7e-09
# Para visualizar el HR de cada variable:
exp(cbind(HR = coef(cox_model), confint(cox_model)))
                           HR     2.5 %    97.5 %
uso_de_metforminaSí 0.3994217 0.2540192 0.6280536
edad                1.0338667 1.0165343 1.0514946
sexoMasculino       0.9805285 0.6692357 1.4366181
diabetesSí          0.9882101 0.6376588 1.5314761
choqueSí            1.8967684 1.2815617 2.8073018

Regresión de Cox

# Paquetes requeridos
library(survival)
library(gtsummary)
library(dplyr)

# Asegúrate que las variables están correctamente codificadas:
# Evento: 1 = Fallecido, 0 = Sobreviviente
df <- df %>%
  mutate(
    evento = ifelse(murio_antes_de_30_dias == "Fallecido", 1, 0),
    tiempo = as.numeric(dias_de_hospitalizacion),
    uso_de_metformina = factor(uso_de_metformina, levels = c("No", "Sí")),
    sexo = factor(sexo, levels = c("Femenino", "Masculino")),
    diabetes = factor(diabetes, levels = c("No", "Sí")),
    choque = factor(choque, levels = c("No", "Sí"))
  )

# Ajustar el modelo de Cox
cox_model <- coxph(
  Surv(tiempo, evento) ~ uso_de_metformina + edad + sexo + diabetes + choque,
  data = df
)

# Tabla resumen con gtsummary
tabla_cox <- tbl_regression(
  cox_model,
  exponentiate = TRUE, # Muestra HR en vez de coeficientes logarítmicos
  label = list(
    uso_de_metformina = "Uso de metformina",
    edad = "Edad (años)",
    sexo = "Sexo masculino",
    diabetes = "Diabetes mellitus",
    choque = "Choque séptico"
  )
) %>%
  add_global_p() %>%
  bold_labels()

# Mostrar la tabla
tabla_cox
Characteristic HR1 95% CI1 p-value
Uso de metformina

<0.001
    No
    Sí 0.40 0.25, 0.63
Edad (años) 1.03 1.02, 1.05 <0.001
Sexo masculino

>0.9
    Femenino
    Masculino 0.98 0.67, 1.44
Diabetes mellitus

>0.9
    No
    Sí 0.99 0.64, 1.53
Choque séptico

0.001
    No
    Sí 1.90 1.28, 2.81
1 HR = Hazard Ratio, CI = Confidence Interval

Análisis multivariado para factores asociados a mortalidad

Justificación:
El análisis bivariado identifica asociaciones, pero para controlar el efecto de posibles variables de confusión y establecer la independencia del uso de metformina y otros factores pronósticos sobre la mortalidad a 30 días, es fundamental un modelo multivariado (logístico o de supervivencia).

Modelo de regresión logística multivariada

Variable dependiente (mortalidad)

# Recodificar variable de mortalidad
df$mortalidad_binaria <- ifelse(df$murio_antes_de_30_dias == "Fallecido", 1,
                               ifelse(df$murio_antes_de_30_dias == "Sobreviviente", 0, NA))
df$mortalidad_binaria <- as.factor(df$mortalidad_binaria)
table(df$mortalidad_binaria, useNA="always")

   0    1 <NA> 
  74  116    0 

2. Codifica las variables categóricas

df$uso_de_metformina <- factor(df$uso_de_metformina, levels = c("No", "Sí"))
df$sexo <- factor(df$sexo, levels = c("Femenino", "Masculino"))
df$diabetes <- factor(df$diabetes, levels = c("No", "Sí"))
df$choque <- factor(df$choque, levels = c("No", "Sí"))

3. Elimina los casos NA en la variable dependiente y las principales predictoras

df_model <- df %>%
  filter(!is.na(mortalidad_binaria),
         !is.na(uso_de_metformina),
         !is.na(edad),
         !is.na(sexo),
         !is.na(diabetes),
         !is.na(choque))
modelo <- glm(mortalidad_binaria ~ uso_de_metformina + edad + sexo + diabetes + choque,
              data = df_model, family = binomial)

summary(modelo)

Call:
glm(formula = mortalidad_binaria ~ uso_de_metformina + edad + 
    sexo + diabetes + choque, family = binomial, data = df_model)

Coefficients:
                    Estimate Std. Error z value Pr(>|z|)    
(Intercept)         -2.61452    1.31594  -1.987 0.046943 *  
uso_de_metforminaSí -2.83366    0.67707  -4.185 2.85e-05 ***
edad                 0.04175    0.01536   2.718 0.006566 ** 
sexoMasculino       -0.13530    0.37571  -0.360 0.718751    
diabetesSí           1.18953    0.68591   1.734 0.082875 .  
choqueSí             1.45269    0.38301   3.793 0.000149 ***
---
Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 250.23  on 187  degrees of freedom
Residual deviance: 189.34  on 182  degrees of freedom
AIC: 201.34

Number of Fisher Scoring iterations: 5
exp(cbind(OR = coef(modelo), confint(modelo)))
Waiting for profiling to be done...
                            OR      2.5 %     97.5 %
(Intercept)         0.07320259 0.00508974  0.9082113
uso_de_metforminaSí 0.05879700 0.01262473  0.1934886
edad                1.04263198 1.01252282  1.0756618
sexoMasculino       0.87345039 0.41645315  1.8289058
diabetesSí          3.28555147 0.96394536 15.3881188
choqueSí            4.27460232 2.06320568  9.3298758