1 Felicidades!

Felicidades por llegar a esta etapa en la que estás a punto de graduarte. Aquí encontrarás un análisis de los datos de tu investigación sobre conocimiento, percepción y conductas de uso de antibióticos en Puerto Rico.

Este análisis incluye el proceso completo de limpieza, recodificación, análisis descriptivo, análisis bivariado, regresión logística multivariada y visualización de resultados. La idea es que tengas un documento organizado, reproducible y fácil de revisar mientras preparas la versión final de tu trabajo.

2 Descargar este código

Puedes descargar este código aquí.

3 Paquetes

library(tidyverse)
library(readxl)
library(gtsummary)
library(gt)
library(broom)

4 Cargar datos

data_raw <- read_excel("Data limpia 5-7.xlsx", sheet = "Base de Datos Limpia")

5 Renombrar variables

data <- data_raw %>%
  rename(
    id                     = record_id,
    edad                   = Edad,
    nivel_educativo        = `Nivel Educativo`,
    region                 = `Región`,
    genero                 = Genero,
    exp_previas            = `Experiencias_Previas_1_4 _ 9`,
    conoc_mecanismo        = `Conocimiento_mecanismo_acción_antibioticos_2`,
    conoc_resistencia      = `Conocimiento _resistencia_8`,
    percepcion_resistencia = Percepción_resistencia_10,
    conductas_uso          = Conductas_uso_3_5,
    orientacion_medico     = `Orientación_Médico_6_7`
  )

6 Recodificación de variables

data <- data %>%
  mutate(
    exp_previas = case_when(
      exp_previas == 1 ~ 1,
      exp_previas %in% c(0, 2) ~ 0,
      TRUE ~ NA_real_
    ),
    
    conductas_uso = case_when(
      conductas_uso == 1 ~ 1,
      conductas_uso %in% c(0, 2) ~ 0,
      TRUE ~ NA_real_
    ),
    
    orientacion_medico = case_when(
      orientacion_medico == 1 ~ 1,
      orientacion_medico %in% c(0, 2) ~ 0,
      TRUE ~ NA_real_
    ),
    
    # Conocimiento sobre mecanismo de acción de antibióticos recodificado:
    # - Correcta = 1: reconoce que los antibióticos NO matan virus
    # - Incorrecta / No estoy seguro = 0
    
    conoc_mecanismo_correcto = case_when(
      conoc_mecanismo == 0 ~ 1,
      conoc_mecanismo %in% c(1, 2) ~ 0,
      TRUE ~ NA_real_
    ),
    
    conoc_mecanismo_correcto_f = factor(
      conoc_mecanismo_correcto,
      levels = c(0, 1),
      labels = c("Incorrecta / No estoy seguro", "Correcta")
    ),
    
    # Conocimiento sobre resistencia antimicrobiana
    
    conoc_resistencia_f = factor(
      conoc_resistencia,
      levels = c(1, 2, 3),
      labels = c(
        "Incorrecta",
        "Parcialmente correcta",
        "Correcta"
      )
    ),
    
    percepcion_f = factor(
      percepcion_resistencia,
      levels = c(1, 2, 3),
      labels = c(
        "Nada preocupado (1-4)",
        "Algo preocupado (5-7)",
        "Extremadamente preocupado (8-10)"
      )
    ),
    
    # Edad
    
    edad_f = factor(
      edad,
      levels = 1:6,
      labels = c(
        "21-29", "30-39", "40-49",
        "50-59", "60-69", "70+"
      )
    ),
    
    # Género
    
    genero_f = factor(
      genero,
      levels = c(1, 2),
      labels = c("Masculino", "Femenino")
    ),
    
    # Educación
    # El dataset tiene 3 niveles agregados:
    # 1 = Educación secundaria o menor
    # 2 = Postsecundaria no universitaria
    # 3 = Universitaria o avanzada
    #
    # Lo recodifiqué como variable dicotómica:
    # 1-2 = Menos de bachillerato
    # 3   = Bachillerato o más
    
    nivel_educativo_f = factor(
      nivel_educativo,
      levels = 1:3,
      labels = c(
        "Educación secundaria o menor",
        "Postsecundaria no universitaria",
        "Universitaria o avanzada"
      )
    ),
    
    educ_dicotica = factor(
      case_when(
        nivel_educativo %in% c(1, 2) ~ "Menos de bachillerato",
        nivel_educativo == 3 ~ "Bachillerato o más",
        TRUE ~ NA_character_
      ),
      levels = c("Menos de bachillerato", "Bachillerato o más")
    ),
    
    # Región
    
    region_f = factor(
      region,
      levels = 1:7,
      labels = c(
        "Arecibo", "Bayamón", "Caguas",
        "Fajardo", "Metro", "Mayagüez", "Ponce"
      )
    ),
    
    # Factores binarios para tablas
    
    exp_previas_f = factor(
      exp_previas,
      levels = c(0, 1),
      labels = c("No", "Sí")
    ),
    
    conductas_uso_f = factor(
      conductas_uso,
      levels = c(0, 1),
      labels = c("No", "Sí")
    ),
    
    orientacion_medico_f = factor(
      orientacion_medico,
      levels = c(0, 1),
      labels = c("No", "Sí")
    )
  )

7 Verificaciones

table(data$conoc_mecanismo_correcto_f, useNA = "always")
## 
## Incorrecta / No estoy seguro                     Correcta 
##                           67                           92 
##                         <NA> 
##                            0
table(data$exp_previas_f, useNA = "always")
## 
##   No   Sí <NA> 
##    0  159    0
table(data$conductas_uso_f, useNA = "always")
## 
##   No   Sí <NA> 
##   47  112    0
table(data$orientacion_medico_f, useNA = "always")
## 
##   No   Sí <NA> 
##   53  106    0

8 Tabla 1: Análisis univariado descriptivo

tabla_univariada <- data %>%
  select(
    edad_f,
    genero_f,
    educ_dicotica,
    nivel_educativo_f,
    region_f,
    conoc_mecanismo_correcto_f,
    conoc_resistencia_f,
    percepcion_f,
    exp_previas_f,
    conductas_uso_f,
    orientacion_medico_f
  ) %>%
  tbl_summary(
    label = list(
      edad_f                      ~ "Edad",
      genero_f                    ~ "Género",
      educ_dicotica               ~ "Educación dicotómica",
      nivel_educativo_f           ~ "Nivel educativo",
      region_f                    ~ "Región de residencia",
      conoc_mecanismo_correcto_f  ~ "Conocimiento correcto: antibióticos no matan virus",
      conoc_resistencia_f         ~ "Conocimiento sobre resistencia antimicrobiana",
      percepcion_f                ~ "Preocupación por resistencia antimicrobiana",
      exp_previas_f               ~ "Experiencias previas con antibióticos",
      conductas_uso_f             ~ "Conductas de uso de antibióticos",
      orientacion_medico_f        ~ "Orientación médica recibida"
    ),
    missing = "no"
  ) %>%
  bold_labels() %>%
  modify_header(
    label ~ "**Variables**",
    stat_0 ~ "**n (%)**"
  ) %>%
  modify_footnote(
    all_stat_cols() ~ NA
  ) %>%
  modify_caption("**Tabla 1. Análisis univariado descriptivo**")

tabla_univariada %>%
  as_gt() %>%
  gt::tab_source_note(
    gt::md(paste0("**_N_ = ", nrow(data), "**"))
  )
Tabla 1. Análisis univariado descriptivo
Variables n (%)
Edad
    21-29 38 (24%)
    30-39 32 (20%)
    40-49 29 (18%)
    50-59 41 (26%)
    60-69 11 (6.9%)
    70+ 8 (5.0%)
Género
    Masculino 39 (25%)
    Femenino 120 (75%)
Educación dicotómica
    Menos de bachillerato 89 (56%)
    Bachillerato o más 70 (44%)
Nivel educativo
    Educación secundaria o menor 3 (1.9%)
    Postsecundaria no universitaria 86 (54%)
    Universitaria o avanzada 70 (44%)
Región de residencia
    Arecibo 50 (31%)
    Bayamón 15 (9.4%)
    Caguas 7 (4.4%)
    Fajardo 6 (3.8%)
    Metro 63 (40%)
    Mayagüez 4 (2.5%)
    Ponce 14 (8.8%)
Conocimiento correcto: antibióticos no matan virus
    Incorrecta / No estoy seguro 67 (42%)
    Correcta 92 (58%)
Conocimiento sobre resistencia antimicrobiana
    Incorrecta 34 (21%)
    Parcialmente correcta 33 (21%)
    Correcta 92 (58%)
Preocupación por resistencia antimicrobiana
    Nada preocupado (1-4) 40 (25%)
    Algo preocupado (5-7) 80 (50%)
    Extremadamente preocupado (8-10) 39 (25%)
Experiencias previas con antibióticos
    No 0 (0%)
    Sí 159 (100%)
Conductas de uso de antibióticos
    No 47 (30%)
    Sí 112 (70%)
Orientación médica recibida
    No 53 (33%)
    Sí 106 (67%)
N = 159

9 Tabla 2: Análisis bivariado

La variable independiente es conductas de uso de antibióticos. La tabla compara las características de los participantes según si reportaron o no conductas de uso de antibióticos.

tabla_bivariada <- data %>%
  select(
    conductas_uso_f,
    conoc_mecanismo_correcto_f,
    conoc_resistencia_f,
    percepcion_f,
    edad_f,
    genero_f,
    educ_dicotica,
    region_f,
    orientacion_medico_f
  ) %>%
  tbl_summary(
    by = conductas_uso_f,
    label = list(
      conoc_mecanismo_correcto_f  ~ "Conocimiento correcto: antibióticos no matan virus",
      conoc_resistencia_f         ~ "Conocimiento sobre resistencia antimicrobiana",
      percepcion_f                ~ "Preocupación por resistencia antimicrobiana",
      edad_f                      ~ "Edad",
      genero_f                    ~ "Género",
      educ_dicotica               ~ "Educación",
      region_f                    ~ "Región de residencia",
      orientacion_medico_f        ~ "Orientación médica recibida"
    ),
    missing = "no"
  ) %>%
  bold_labels() %>%
  modify_header(
    label ~ "**Variable**",
    stat_1 ~ "**No conductas de uso**",
    stat_2 ~ "**Sí conductas de uso**"
  ) %>%
  modify_footnote(
    all_stat_cols() ~ NA
  ) %>%
  modify_caption("**Tabla 2. Análisis bivariado según conductas de uso de antibióticos**")

tabla_bivariada %>%
  as_gt() %>%
  gt::tab_source_note(
    gt::md(paste0("**_N_ = ", nrow(data), "**"))
  )
Tabla 2. Análisis bivariado según conductas de uso de antibióticos
Variable No conductas de uso Sí conductas de uso
Conocimiento correcto: antibióticos no matan virus

    Incorrecta / No estoy seguro 19 (40%) 48 (43%)
    Correcta 28 (60%) 64 (57%)
Conocimiento sobre resistencia antimicrobiana

    Incorrecta 12 (26%) 22 (20%)
    Parcialmente correcta 9 (19%) 24 (21%)
    Correcta 26 (55%) 66 (59%)
Preocupación por resistencia antimicrobiana

    Nada preocupado (1-4) 9 (19%) 31 (28%)
    Algo preocupado (5-7) 25 (53%) 55 (49%)
    Extremadamente preocupado (8-10) 13 (28%) 26 (23%)
Edad

    21-29 11 (23%) 27 (24%)
    30-39 10 (21%) 22 (20%)
    40-49 7 (15%) 22 (20%)
    50-59 11 (23%) 30 (27%)
    60-69 5 (11%) 6 (5.4%)
    70+ 3 (6.4%) 5 (4.5%)
Género

    Masculino 11 (23%) 28 (25%)
    Femenino 36 (77%) 84 (75%)
Educación

    Menos de bachillerato 26 (55%) 63 (56%)
    Bachillerato o más 21 (45%) 49 (44%)
Región de residencia

    Arecibo 16 (34%) 34 (30%)
    Bayamón 6 (13%) 9 (8.0%)
    Caguas 3 (6.4%) 4 (3.6%)
    Fajardo 0 (0%) 6 (5.4%)
    Metro 19 (40%) 44 (39%)
    Mayagüez 0 (0%) 4 (3.6%)
    Ponce 3 (6.4%) 11 (9.8%)
Orientación médica recibida

    No 20 (43%) 33 (29%)
    Sí 27 (57%) 79 (71%)
N = 159

10 Tabla 3: Análisis multivariado

Se usa una regresión logística binaria porque la variable independiente, conductas_uso, es binaria:

Por eso no se usa una regresión lineal OLS. El modelo estima la asociación entre conocimiento, percepción y características sociodemográficas con la probabilidad de reportar conductas de uso de antibióticos.

Antes de correr el modelo multivariado, revisé la distribución de conductas_uso por región Fajardo y Mayagüez tienen cero casos en la categoría “No”, lo que produce separación perfecta en la regresión logística. Por eso, la variable región se presenta en las Tablas 1 y 2, pero se excluye del modelo multivariado para evitar estimaciones inestables.

table(data$region_f, data$conductas_uso_f)
##           
##            No Sí
##   Arecibo  16 34
##   Bayamón   6  9
##   Caguas    3  4
##   Fajardo   0  6
##   Metro    19 44
##   Mayagüez  0  4
##   Ponce     3 11
modelo_logit <- glm(
  conductas_uso ~
    conoc_mecanismo_correcto_f +
    conoc_resistencia_f +
    percepcion_f +
    edad_f +
    genero_f +
    educ_dicotica +
    orientacion_medico_f,
  family = binomial(link = "logit"),
  data = data
)

summary(modelo_logit)
## 
## Call:
## glm(formula = conductas_uso ~ conoc_mecanismo_correcto_f + conoc_resistencia_f + 
##     percepcion_f + edad_f + genero_f + educ_dicotica + orientacion_medico_f, 
##     family = binomial(link = "logit"), data = data)
## 
## Coefficients:
##                                              Estimate Std. Error z value
## (Intercept)                                   0.96834    0.63299   1.530
## conoc_mecanismo_correcto_fCorrecta           -0.25226    0.39514  -0.638
## conoc_resistencia_fParcialmente correcta      0.61737    0.58385   1.057
## conoc_resistencia_fCorrecta                   0.55140    0.48637   1.134
## percepcion_fAlgo preocupado (5-7)            -0.50566    0.47951  -1.055
## percepcion_fExtremadamente preocupado (8-10) -0.57128    0.56413  -1.013
## edad_f30-39                                  -0.35451    0.55349  -0.641
## edad_f40-49                                   0.16611    0.60767   0.273
## edad_f50-59                                   0.02196    0.53668   0.041
## edad_f60-69                                  -0.75723    0.72846  -1.040
## edad_f70+                                    -0.66046    0.88884  -0.743
## genero_fFemenino                             -0.20045    0.42930  -0.467
## educ_dicoticaBachillerato o más              -0.18604    0.40302  -0.462
## orientacion_medico_fSí                        0.59087    0.38692   1.527
##                                              Pr(>|z|)
## (Intercept)                                     0.126
## conoc_mecanismo_correcto_fCorrecta              0.523
## conoc_resistencia_fParcialmente correcta        0.290
## conoc_resistencia_fCorrecta                     0.257
## percepcion_fAlgo preocupado (5-7)               0.292
## percepcion_fExtremadamente preocupado (8-10)    0.311
## edad_f30-39                                     0.522
## edad_f40-49                                     0.785
## edad_f50-59                                     0.967
## edad_f60-69                                     0.299
## edad_f70+                                       0.457
## genero_fFemenino                                0.641
## educ_dicoticaBachillerato o más                 0.644
## orientacion_medico_fSí                          0.127
## 
## (Dispersion parameter for binomial family taken to be 1)
## 
##     Null deviance: 193.05  on 158  degrees of freedom
## Residual deviance: 185.38  on 145  degrees of freedom
## AIC: 213.38
## 
## Number of Fisher Scoring iterations: 4

La Tabla 3 presenta los resultados como odds ratios (OR), con errores estándar y p-values. La variable región no se incluye en este modelo debido a separación perfecta en algunas categorías regionales.

# Para que los p-values en la tabla 3 se muestren con dos espacios decimales
p_fmt <- function(x) {gtsummary::style_number(x, digits = 2)}
tabla_multivariada <- broom::tidy(modelo_logit) %>%
  filter(term != "(Intercept)") %>%
  mutate(OR = exp(estimate),
    term = case_when(term == "conoc_mecanismo_correcto_fCorrecta" ~ "Conocimiento correcto: Correcta",
      term == "conoc_resistencia_fParcialmente correcta" ~ "Conocimiento resistencia: Parcialmente correcta",
      term == "conoc_resistencia_fCorrecta" ~ "Conocimiento resistencia: Correcta",
      term == "percepcion_fAlgo preocupado (5-7)" ~ "Preocupación RAM: Algo preocupado (5-7)",
      term == "percepcion_fExtremadamente preocupado (8-10)" ~ 
        "Preocupación RAM: Extremadamente preocupado (8-10)",
      term == "edad_f30-39" ~ "Edad: 30-39",
      term == "edad_f40-49" ~ "Edad: 40-49",
      term == "edad_f50-59" ~ "Edad: 50-59",
      term == "edad_f60-69" ~ "Edad: 60-69",
      term == "edad_f70+"   ~ "Edad: 70+",
      term == "genero_fFemenino" ~ "Género: Femenino",
      term == "educ_dicoticaBachillerato o más" ~ "Educación: Bachillerato o más",
      term == "orientacion_medico_fSí" ~ "Orientación médica recibida: Sí",
      TRUE ~ term), OR_SE = paste0(gtsummary::style_number(OR, digits = 2),
      "<br>(", gtsummary::style_number(std.error, digits = 2),
 ")"
    ),
p.value = p_fmt(p.value)
  ) %>%
  select(`Variables dependientes` = term, `Odds Ratios (Standard Errors)` = OR_SE, `p-value` = p.value) %>%
  gt() %>%
  fmt_markdown(columns = `Odds Ratios (Standard Errors)`) %>%
  tab_caption("Tabla 3. Regresión logística multivariada: conductas de uso de antibióticos") %>%
  tab_source_note(gt::md(paste0("**_N_ = ", nobs(modelo_logit), "**")))

tabla_multivariada
Tabla 3. Regresión logística multivariada: conductas de uso de antibióticos
Variables dependientes Odds Ratios (Standard Errors) p-value
Conocimiento correcto: Correcta 0.78
(0.40)
0.52
Conocimiento resistencia: Parcialmente correcta 1.85
(0.58)
0.29
Conocimiento resistencia: Correcta 1.74
(0.49)
0.26
Preocupación RAM: Algo preocupado (5-7) 0.60
(0.48)
0.29
Preocupación RAM: Extremadamente preocupado (8-10) 0.56
(0.56)
0.31
Edad: 30-39 0.70
(0.55)
0.52
Edad: 40-49 1.18
(0.61)
0.78
Edad: 50-59 1.02
(0.54)
0.97
Edad: 60-69 0.47
(0.73)
0.30
Edad: 70+ 0.52
(0.89)
0.46
Género: Femenino 0.82
(0.43)
0.64
Educación: Bachillerato o más 0.83
(0.40)
0.64
Orientación médica recibida: Sí 1.81
(0.39)
0.13
N = 159

11 Gráfica de coeficientes

La siguiente gráfica muestra los resultados del modelo multivariado como odds ratios (OR). La línea vertical en OR = 1 representa ausencia de asociación. Valores mayores de 1 indican mayor probabilidad de reportar conductas de uso de antibióticos; valores menores de 1 indican menor probabilidad.

coefplot_data <- broom::tidy(modelo_logit, conf.int = TRUE, exponentiate = TRUE) %>%
  filter(term != "(Intercept)") %>%
  mutate(
    term = case_when(
      term == "conoc_mecanismo_correcto_fCorrecta" ~ "Conocimiento correcto: Correcta",
      term == "conoc_resistencia_fParcialmente correcta" ~ "Conocimiento resistencia: Parcialmente correcta",
      term == "conoc_resistencia_fCorrecta" ~ "Conocimiento resistencia: Correcta",
      term == "percepcion_fAlgo preocupado (5-7)" ~ "Preocupación RAM: Algo preocupado (5-7)",
      term == "percepcion_fExtremadamente preocupado (8-10)" ~ 
        "Preocupación RAM: Extremadamente preocupado (8-10)",
      term == "edad_f30-39" ~ "Edad: 30-39",
      term == "edad_f40-49" ~ "Edad: 40-49",
      term == "edad_f50-59" ~ "Edad: 50-59",
      term == "edad_f60-69" ~ "Edad: 60-69",
      term == "edad_f70+"   ~ "Edad: 70+",
      term == "genero_fFemenino" ~ "Género: Femenino",
      term == "educ_dicoticaBachillerato o más" ~ "Educación: Bachillerato o más",
      term == "orientacion_medico_fSí" ~ "Orientación médica recibida: Sí",
      TRUE ~ term),
    # Orden manual: igual que Tabla 3
    term = factor(term, levels = rev(c(
        "Conocimiento correcto: Correcta",
        "Conocimiento resistencia: Parcialmente correcta",
        "Conocimiento resistencia: Correcta",
        "Preocupación RAM: Algo preocupado (5-7)",
        "Preocupación RAM: Extremadamente preocupado (8-10)",
        "Edad: 30-39",
        "Edad: 40-49",
        "Edad: 50-59",
        "Edad: 60-69",
        "Edad: 70+",
        "Género: Femenino",
        "Educación: Bachillerato o más",
        "Orientación médica recibida: Sí"
      ))
    )
  )
coefplot <- ggplot(coefplot_data, aes(x = estimate, y = term)) +
  geom_vline(xintercept = 1, linetype = "dashed") +
  geom_point(size = 2.5) +
  geom_errorbarh(aes(xmin = conf.low, xmax = conf.high), height = 0.2) +
  scale_x_log10() +
  labs(subtitle = "Odds ratios con intervalos de confianza al 95%",
    x = "Odds Ratio (escala logarítmica)",
    y = NULL
  ) +
  theme_minimal() +
  theme(
    plot.title = element_text(face = "bold"),
    axis.text.y = element_text(size = 9)
  )

## Figura 1. Resultados del modelo multivariado

coefplot

Puedes descargar esta gráfica en formato PDF aquí y en formato JPEG aquí.