Código preparado por Giovanni Castro Irizarry (giovannicastro@ucla.edu)
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.
Puedes descargar este código aquí.
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`
)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í")
)
)##
## Incorrecta / No estoy seguro Correcta
## 67 92
## <NA>
## 0
##
## No Sí <NA>
## 0 159 0
##
## No Sí <NA>
## 47 112 0
##
## No Sí <NA>
## 53 106 0
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), "**"))
)| 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 | |
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), "**"))
)| 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 | ||
Se usa una regresión logística binaria porque la variable
independiente, conductas_uso, es binaria:
0 = No1 = Sí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.
##
## 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| 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 | ||
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
coefplotPuedes descargar esta gráfica en formato PDF aquí y en formato JPEG aquí.