library(tidyverse)
library(readxl)
library(ggplot2)
library(broom)
library(flextable)
library(knitr)
library(kableExtra)
base <- read_excel("Base_epidemiologia_completa.xlsx")

base <- base %>%
  rename(
    sexo          = Sex,
    edad_anos     = `Age (years)`,
    edad_meses    = `Age (months)`,
    peso          = `Weight (kg)`,
    talla         = `Height (cm)`,
    grupo_edad    = Grupo_edad,
    hemoglobina   = Hemoglobina,
    hematocrito   = Hematocrito,
    ingesta_hierro = Ingesta_hierro
  ) %>%
  mutate(
    sexo       = factor(sexo, levels = c("Male","Female"),
                        labels = c("Masculino","Femenino")),
    grupo_edad = factor(grupo_edad, levels = c("<5 años","≥5 años")),
    IMC        = round(peso / (talla/100)^2, 2),

    Clasificacion_HAZ = factor(case_when(
      HAZ < -3             ~ "Talla baja severa",
      HAZ >= -3 & HAZ < -2 ~ "Talla baja para la edad o retraso en talla",
      HAZ >= -2 & HAZ < -1 ~ "Riesgo de talla baja",
      HAZ >= -1            ~ "Talla adecuada para la edad",
      TRUE ~ NA_character_),
      levels = c("Talla baja severa",
                 "Talla baja para la edad o retraso en talla",
                 "Riesgo de talla baja",
                 "Talla adecuada para la edad")),

    Clasificacion_BAZ = factor(case_when(
      BAZ < -2             ~ "Delgadez",
      BAZ >= -2 & BAZ < -1 ~ "Riesgo de delgadez",
      BAZ >= -1 & BAZ <= 1 ~ "IMC adecuado para la edad",
      BAZ >  1 & BAZ <= 2  ~ "Sobrepeso",
      BAZ >  2             ~ "Obesidad",
      TRUE ~ NA_character_),
      levels = c("Delgadez","Riesgo de delgadez",
                 "IMC adecuado para la edad","Sobrepeso","Obesidad")),

    WAZ_valido = if_else(grupo_edad == "<5 años", WAZ, NA_real_),
    Clasificacion_WAZ = factor(case_when(
      WAZ_valido < -2  ~ "Bajo peso para la edad",
      WAZ_valido >= -2 ~ "Peso adecuado para la edad",
      TRUE ~ NA_character_),
      levels = c("Bajo peso para la edad","Peso adecuado para la edad"))
  )

menores5 <- base %>% filter(grupo_edad == "<5 años")
mayores5 <- base %>% filter(grupo_edad == "≥5 años")

colores_grupo <- c("<5 años" = "#4472C4", "≥5 años" = "#70AD47")

base <- base %>%
  mutate(
   
    WHZ_valido = if_else(grupo_edad == "<5 años", WHZ, NA_real_),
    Clasificacion_WHZ = factor(
      case_when(
        WHZ_valido < -3                    ~ "Emaciación severa",
        WHZ_valido >= -3 & WHZ_valido < -2 ~ "Emaciación",
        WHZ_valido >= -2 & WHZ_valido <= 1 ~ "Normal",
        WHZ_valido >  1  & WHZ_valido <= 2 ~ "Riesgo de sobrepeso",
        WHZ_valido >  2  & WHZ_valido <= 3 ~ "Sobrepeso",
        WHZ_valido >  3                    ~ "Obesidad",
        TRUE ~ NA_character_
      ),
      levels = c("Emaciación severa","Emaciación","Normal",
                 "Riesgo de sobrepeso","Sobrepeso","Obesidad")
    )
  )

1 Análisis descriptivo

1.1 Variables sociodemográficas

# Sexo
base %>%
  count(sexo) %>%
  mutate(Porcentaje = round(n/sum(n)*100, 2)) %>%
  kable(col.names = c("Sexo","n","%"), caption = "Distribución por sexo") %>%
  kable_styling(bootstrap_options = c("striped","hover","condensed"),
                full_width = FALSE)
Distribución por sexo
Sexo n %
Masculino 43 47.78
Femenino 47 52.22
# Grupo de edad
base %>%
  count(grupo_edad) %>%
  mutate(Porcentaje = round(n/sum(n)*100, 2)) %>%
  kable(col.names = c("Grupo de edad","n","%"),
        caption = "Distribución por grupo de edad") %>%
  kable_styling(bootstrap_options = c("striped","hover","condensed"),
                full_width = FALSE)
Distribución por grupo de edad
Grupo de edad n %
<5 años 45 50
≥5 años 45 50
base %>%
  count(grupo_edad, sexo) %>%
  ggplot(aes(x = grupo_edad, y = n, fill = sexo)) +
  geom_col(position = "dodge", color = "white", width = 0.6) +
  geom_text(aes(label = n), position = position_dodge(0.6),
            vjust = -0.4, fontface = "bold", size = 4) +
  scale_fill_manual(values = c("Masculino" = "#4472C4",
                               "Femenino"  = "#ED7D31")) +
  labs(title = "Distribución por sexo y grupo de edad",
       x = "Grupo de edad", y = "n", fill = "Sexo") +
  theme_bw(base_size = 12) +
  theme(legend.position = "bottom")
Distribución por sexo y grupo de edad

Distribución por sexo y grupo de edad

1.2 Variables cuantitativas

vars_desc <- base %>%
  select(edad_anos, peso, talla, IMC,
         HAZ, BAZ, hemoglobina, hematocrito, ingesta_hierro)

data.frame(
  Variable = c("Edad (años)","Peso (kg)","Talla (cm)","IMC (kg/m²)",
               "HAZ","BAZ","Hemoglobina (g/dL)","Hematocrito (%)","Ingesta hierro (mg/día)"),
  n       = sapply(vars_desc, function(x) sum(!is.na(x))),
  Media   = sapply(vars_desc, mean,   na.rm = TRUE) %>% round(2),
  DE      = sapply(vars_desc, sd,     na.rm = TRUE) %>% round(2),
  Mediana = sapply(vars_desc, median, na.rm = TRUE) %>% round(2),
  Minimo  = sapply(vars_desc, min,    na.rm = TRUE) %>% round(2),
  Maximo  = sapply(vars_desc, max,    na.rm = TRUE) %>% round(2)
) %>%
  kable(caption = "Estadística descriptiva — total muestra") %>%
  kable_styling(bootstrap_options = c("striped","hover","condensed"))
Estadística descriptiva — total muestra
Variable n Media DE Mediana Minimo Maximo
edad_anos Edad (años) 90 7.99 6.41 5.00 0.00 18.75
peso Peso (kg) 90 29.25 19.66 19.45 3.20 71.10
talla Talla (cm) 90 116.81 42.15 104.65 48.00 181.40
IMC IMC (kg/m²) 90 19.28 3.35 19.02 13.28 28.41
HAZ HAZ 90 -1.22 2.03 -0.86 -6.07 2.58
BAZ BAZ 90 1.12 2.18 0.70 -3.25 7.32
hemoglobina Hemoglobina (g/dL) 88 12.30 1.27 12.05 10.10 16.10
hematocrito Hematocrito (%) 88 35.49 4.19 34.75 26.40 49.50
ingesta_hierro Ingesta hierro (mg/día) 89 21.53 13.17 24.60 2.50 42.30

2 Objetivo 1 — Estado de crecimiento físico

2.1 Prevalencias por indicador

tabla_HAZ <- base %>%
  filter(!is.na(Clasificacion_HAZ)) %>%
  count(Clasificacion_HAZ) %>%
  mutate(Porcentaje = round(n/sum(n)*100, 2))

tabla_HAZ %>%
  kable(col.names = c("Categoría","n","%"),
        caption = "Estado nutricional — Talla/Edad (HAZ) | n = 90") %>%
  kable_styling(bootstrap_options = c("striped","hover","condensed"),
                full_width = FALSE)
Estado nutricional — Talla/Edad (HAZ) | n = 90
Categoría n %
Talla baja severa 17 18.89
Talla baja para la edad o retraso en talla 4 4.44
Riesgo de talla baja 19 21.11
Talla adecuada para la edad 50 55.56
tabla_BAZ <- base %>%
  filter(!is.na(Clasificacion_BAZ)) %>%
  count(Clasificacion_BAZ) %>%
  mutate(Porcentaje = round(n/sum(n)*100, 2))

tabla_BAZ %>%
  kable(col.names = c("Categoría","n","%"),
        caption = "Estado nutricional — IMC/Edad (BAZ) | n = 90") %>%
  kable_styling(bootstrap_options = c("striped","hover","condensed"),
                full_width = FALSE)
Estado nutricional — IMC/Edad (BAZ) | n = 90
Categoría n %
Delgadez 2 2.22
Riesgo de delgadez 7 7.78
IMC adecuado para la edad 47 52.22
Sobrepeso 9 10.00
Obesidad 25 27.78
tabla_WAZ <- base %>%
  filter(!is.na(Clasificacion_WAZ)) %>%
  count(Clasificacion_WAZ) %>%
  mutate(Porcentaje = round(n/sum(n)*100, 2))

tabla_WAZ %>%
  kable(col.names = c("Categoría","n","%"),
        caption = "Estado nutricional — Peso/Edad (WAZ) | n = 45 (solo <5 años)") %>%
  kable_styling(bootstrap_options = c("striped","hover","condensed"),
                full_width = FALSE)
Estado nutricional — Peso/Edad (WAZ) | n = 45 (solo <5 años)
Categoría n %
Bajo peso para la edad 4 8.89
Peso adecuado para la edad 41 91.11

2.2 Gráficos estado nutricional

ggplot(tabla_HAZ, aes(x = Clasificacion_HAZ, y = Porcentaje,
                      fill = Clasificacion_HAZ)) +
  geom_col(color = "white", width = 0.65) +
  geom_text(aes(label = paste0(n, " (", Porcentaje, "%)")),
            vjust = -0.4, size = 3.5) +
  scale_y_continuous(limits = c(0,70),
                     expand = expansion(mult = c(0,0.12))) +
  labs(title = "Estado nutricional — Talla/Edad (HAZ)",
       subtitle = "n = 90 | Ambos grupos de edad",
       x = NULL, y = "Porcentaje (%)") +
  theme_bw(base_size = 12) +
  theme(axis.text.x = element_text(angle = 30, hjust = 1),
        legend.position = "none")
Prevalencia por categoría — Talla/Edad (HAZ)

Prevalencia por categoría — Talla/Edad (HAZ)

ggplot(tabla_BAZ, aes(x = Clasificacion_BAZ, y = Porcentaje,
                      fill = Clasificacion_BAZ)) +
  geom_col(color = "white", width = 0.65) +
  geom_text(aes(label = paste0(n, " (", Porcentaje, "%)")),
            vjust = -0.4, size = 3.5) +
  scale_y_continuous(limits = c(0,65),
                     expand = expansion(mult = c(0,0.12))) +
  labs(title = "Estado nutricional — IMC/Edad (BAZ)",
       subtitle = "n = 90 | Ambos grupos de edad",
       x = NULL, y = "Porcentaje (%)") +
  theme_bw(base_size = 12) +
  theme(axis.text.x = element_text(angle = 30, hjust = 1),
        legend.position = "none")
Prevalencia por categoría — IMC/Edad (BAZ)

Prevalencia por categoría — IMC/Edad (BAZ)

ggplot(tabla_WAZ, aes(x = Clasificacion_WAZ, y = Porcentaje,
                      fill = Clasificacion_WAZ)) +
  geom_col(color = "white", width = 0.55) +
  geom_text(aes(label = paste0(n, " (", Porcentaje, "%)")),
            vjust = -0.4, size = 3.5) +
  scale_y_continuous(limits = c(0,110),
                     expand = expansion(mult = c(0,0.12))) +
  labs(title = "Estado nutricional — Peso/Edad (WAZ)",
       subtitle = "n = 45 | Solo menores de 5 años",
       x = NULL, y = "Porcentaje (%)") +
  theme_bw(base_size = 12) +
  theme(axis.text.x = element_text(angle = 15, hjust = 1),
        legend.position = "none")
Prevalencia por categoría — Peso/Edad (WAZ)

Prevalencia por categoría — Peso/Edad (WAZ)

tabla_HAZ_grupo <- base %>%
  filter(!is.na(Clasificacion_HAZ)) %>%
  group_by(grupo_edad, Clasificacion_HAZ) %>%
  summarise(n = n(), .groups = "drop") %>%
  group_by(grupo_edad) %>%
  mutate(Porcentaje = round(n / sum(n) * 100, 2))

ggplot(tabla_HAZ_grupo,
       aes(x = Clasificacion_HAZ, y = Porcentaje, fill = grupo_edad)) +
  geom_col(position = "dodge", color = "white", width = 0.7) +
  geom_text(aes(label = paste0(Porcentaje, "%")),
            position = position_dodge(0.7), vjust = -0.4, size = 3.2) +
  scale_fill_manual(values = c("<5 años" = "#4472C4", "≥5 años" = "#70AD47")) +
  scale_y_continuous(limits = c(0, 100),
                     expand = expansion(mult = c(0, 0.12))) +
  labs(title = "Talla/Edad (HAZ) por grupo de edad",
       x = NULL, y = "Porcentaje (%)", fill = "Grupo") +
  theme_bw(base_size = 12) +
  theme(axis.text.x = element_text(angle = 30, hjust = 1),
        legend.position = "bottom")
HAZ por grupo de edad

HAZ por grupo de edad

tabla_BAZ_grupo <- base %>%
  filter(!is.na(Clasificacion_BAZ)) %>%
  group_by(grupo_edad, Clasificacion_BAZ) %>%
  summarise(n = n(), .groups = "drop") %>%
  group_by(grupo_edad) %>%
  mutate(Porcentaje = round(n / sum(n) * 100, 2))

ggplot(tabla_BAZ_grupo,
       aes(x = Clasificacion_BAZ, y = Porcentaje, fill = grupo_edad)) +
  geom_col(position = "dodge", color = "white", width = 0.7) +
  geom_text(aes(label = paste0(Porcentaje, "%")),
            position = position_dodge(0.7), vjust = -0.4, size = 3.2) +
  scale_fill_manual(values = c("<5 años" = "#4472C4", "≥5 años" = "#70AD47")) +
  scale_y_continuous(limits = c(0, 85),
                     expand = expansion(mult = c(0, 0.12))) +
  labs(title = "IMC/Edad (BAZ) por grupo de edad",
       x = NULL, y = "Porcentaje (%)", fill = "Grupo") +
  theme_bw(base_size = 12) +
  theme(axis.text.x = element_text(angle = 30, hjust = 1),
        legend.position = "bottom")
BAZ por grupo de edad

BAZ por grupo de edad

t_haz <- base %>% filter(!is.na(Clasificacion_HAZ)) %>%
  count(Clasificacion_HAZ) %>%
  mutate(Indicador = "Talla/Edad (HAZ)",
         `%` = round(n/sum(n)*100, 2),
         `n (%)` = paste0(n," (",`%`,"%)"),
         Nota = "n total = 90 (ambos grupos)") %>%
  rename(Categoria = Clasificacion_HAZ)

t_baz <- base %>% filter(!is.na(Clasificacion_BAZ)) %>%
  count(Clasificacion_BAZ) %>%
  mutate(Indicador = "IMC/Edad (BAZ)",
         `%` = round(n/sum(n)*100, 2),
         `n (%)` = paste0(n," (",`%`,"%)"),
         Nota = "n total = 90 (ambos grupos)") %>%
  rename(Categoria = Clasificacion_BAZ)

t_waz <- base %>% filter(!is.na(Clasificacion_WAZ)) %>%
  count(Clasificacion_WAZ) %>%
  mutate(Indicador = "Peso/Edad (WAZ)",
         `%` = round(n/sum(n)*100, 2),
         `n (%)` = paste0(n," (",`%`,"%)"),
         Nota = "n = 45 (solo <5 años)") %>%
  rename(Categoria = Clasificacion_WAZ)

t_whz <- base %>% filter(!is.na(Clasificacion_WHZ)) %>%
  count(Clasificacion_WHZ) %>%
  mutate(Indicador = "Peso/Talla (WHZ)",
         `%` = round(n/sum(n)*100, 2),
         `n (%)` = paste0(n," (",`%`,"%)"),
         Nota = "n = 45 (solo <5 años)") %>%
  rename(Categoria = Clasificacion_WHZ)

# Calcular rangos dinámicamente según filas reales
r1_ini <- 1
r1_fin <- nrow(t_haz)
r2_ini <- r1_fin + 1
r2_fin <- r2_ini + nrow(t_baz) - 1
r3_ini <- r2_fin + 1
r3_fin <- r3_ini + nrow(t_waz) - 1
r4_ini <- r3_fin + 1
r4_fin <- r4_ini + nrow(t_whz) - 1

bind_rows(t_haz, t_baz, t_waz, t_whz) %>%
  select(Indicador, Categoria, n, `%`, `n (%)`, Nota) %>%
  kable(caption = "Tabla consolidada — Estado nutricional por indicador") %>%
  kable_styling(bootstrap_options = c("striped","hover","condensed")) %>%
  pack_rows("Talla/Edad (HAZ)",  r1_ini, r1_fin) %>%
  pack_rows("IMC/Edad (BAZ)",    r2_ini, r2_fin) %>%
  pack_rows("Peso/Edad (WAZ)",   r3_ini, r3_fin) %>%
  pack_rows("Peso/Talla (WHZ)",  r4_ini, r4_fin)
Tabla consolidada — Estado nutricional por indicador
Indicador Categoria n % n (%) Nota
Talla/Edad (HAZ)
Talla/Edad (HAZ) Talla baja severa 17 18.89 17 (18.89%) n total = 90 (ambos grupos)
Talla/Edad (HAZ) Talla baja para la edad o retraso en talla 4 4.44 4 (4.44%) n total = 90 (ambos grupos)
Talla/Edad (HAZ) Riesgo de talla baja 19 21.11 19 (21.11%) n total = 90 (ambos grupos)
Talla/Edad (HAZ) Talla adecuada para la edad 50 55.56 50 (55.56%) n total = 90 (ambos grupos)
IMC/Edad (BAZ)
IMC/Edad (BAZ) Delgadez 2 2.22 2 (2.22%) n total = 90 (ambos grupos)
IMC/Edad (BAZ) Riesgo de delgadez 7 7.78 7 (7.78%) n total = 90 (ambos grupos)
IMC/Edad (BAZ) IMC adecuado para la edad 47 52.22 47 (52.22%) n total = 90 (ambos grupos)
IMC/Edad (BAZ) Sobrepeso 9 10.00 9 (10%) n total = 90 (ambos grupos)
IMC/Edad (BAZ) Obesidad 25 27.78 25 (27.78%) n total = 90 (ambos grupos)
Peso/Edad (WAZ)
Peso/Edad (WAZ) Bajo peso para la edad 4 8.89 4 (8.89%) n = 45 (solo <5 años)
Peso/Edad (WAZ) Peso adecuado para la edad 41 91.11 41 (91.11%) n = 45 (solo <5 años)
Peso/Talla (WHZ)
Peso/Talla (WHZ) Normal 16 35.56 16 (35.56%) n = 45 (solo <5 años)
Peso/Talla (WHZ) Riesgo de sobrepeso 1 2.22 1 (2.22%) n = 45 (solo <5 años)
Peso/Talla (WHZ) Sobrepeso 11 24.44 11 (24.44%) n = 45 (solo <5 años)
Peso/Talla (WHZ) Obesidad 17 37.78 17 (37.78%) n = 45 (solo <5 años)


# Objetivo 2 — Ingesta de hierro ~ Hemoglobina y Hematocrito

## Pruebas de normalidad


``` r
calcular_ic_spearman <- function(r, n, conf = 0.95) {
  z    <- 0.5 * log((1 + r) / (1 - r))
  se   <- 1 / sqrt(n - 3)
  z_cv <- qnorm((1 + conf) / 2)
  round(c(tanh(z - z_cv * se), tanh(z + z_cv * se)), 3)
}

vars_norm2 <- list(
  list(var = "ingesta_hierro", label = "Ingesta de hierro"),
  list(var = "hemoglobina",    label = "Hemoglobina"),
  list(var = "hematocrito",    label = "Hematocrito")
)

map_dfr(vars_norm2, function(v) {
  x   <- base[[v$var]][!is.na(base[[v$var]])]
  res <- shapiro.test(x)
  tibble(Variable     = v$label,
         n            = length(x),
         W            = round(res$statistic, 4),
         p_valor      = round(res$p.value, 4),
         Distribucion = if_else(res$p.value >= 0.05, "Normal", "No normal"))
}) %>%
  kable(caption = "Prueba de Shapiro-Wilk — Objetivo 2") %>%
  kable_styling(bootstrap_options = c("striped","hover","condensed"),
                full_width = FALSE)
Prueba de Shapiro-Wilk — Objetivo 2
Variable n W p_valor Distribucion
Ingesta de hierro 89 0.8543 0.0000 No normal
Hemoglobina 88 0.9679 0.0278 No normal
Hematocrito 88 0.9460 0.0011 No normal
par(mfrow = c(1,3))
qqnorm(base$ingesta_hierro, main = "QQ-Plot: Ingesta de hierro")
qqline(base$ingesta_hierro, col = "red")
qqnorm(base$hemoglobina,    main = "QQ-Plot: Hemoglobina")
qqline(base$hemoglobina,    col = "red")
qqnorm(base$hematocrito,    main = "QQ-Plot: Hematocrito")
qqline(base$hematocrito,    col = "red")
QQ-plots — variables Objetivo 2

QQ-plots — variables Objetivo 2

par(mfrow = c(1,1))

2.3 Correlaciones de Spearman

cor_hb <- suppressWarnings(
  cor.test(base$ingesta_hierro, base$hemoglobina,
           method = "spearman", exact = FALSE))
cor_hto <- suppressWarnings(
  cor.test(base$ingesta_hierro, base$hematocrito,
           method = "spearman", exact = FALSE))

n_hb  <- sum(!is.na(base$ingesta_hierro) & !is.na(base$hemoglobina))
n_hto <- sum(!is.na(base$ingesta_hierro) & !is.na(base$hematocrito))

ic_hb  <- calcular_ic_spearman(as.numeric(cor_hb$estimate),  n_hb)
ic_hto <- calcular_ic_spearman(as.numeric(cor_hto$estimate), n_hto)

tibble(
  Asociacion    = c("Ingesta hierro ~ Hemoglobina",
                    "Ingesta hierro ~ Hematocrito"),
  Metodo        = "Spearman",
  n             = c(n_hb, n_hto),
  rho           = round(c(cor_hb$estimate, cor_hto$estimate), 3),
  IC_95         = c(paste0("[",ic_hb[1],"; ",ic_hb[2],"]"),
                    paste0("[",ic_hto[1],"; ",ic_hto[2],"]")),
  p_valor       = c(round(cor_hb$p.value, 4), round(cor_hto$p.value, 4)),
  Significativo = c("Sí ***","Sí ***")
) %>%
  kable(caption = "Correlaciones de Spearman — Objetivo 2") %>%
  kable_styling(bootstrap_options = c("striped","hover","condensed"))
Correlaciones de Spearman — Objetivo 2
Asociacion Metodo n rho IC_95 p_valor Significativo
Ingesta hierro ~ Hemoglobina Spearman 87 0.765 [0.66; 0.84] 0 Sí ***
Ingesta hierro ~ Hematocrito Spearman 87 0.531 [0.361; 0.667] 0 Sí ***

2.4 Regresión lineal simple

modelo_hb  <- lm(hemoglobina ~ ingesta_hierro, data = base)
modelo_hto <- lm(hematocrito ~ ingesta_hierro, data = base)

bind_rows(
  tidy(modelo_hb,  conf.int = TRUE) %>% mutate(Outcome = "Hemoglobina"),
  tidy(modelo_hto, conf.int = TRUE) %>% mutate(Outcome = "Hematocrito")
) %>%
  mutate(
    B     = round(estimate,  3),
    IC_95 = paste0("[", round(conf.low,3), "; ", round(conf.high,3), "]"),
    p     = round(p.value, 4),
    Sig   = case_when(p < 0.001 ~ "***", p < 0.01 ~ "**",
                      p < 0.05  ~ "*",   TRUE ~ "ns")
  ) %>%
  select(Outcome, Predictor = term, B, IC_95, p, Sig) %>%
  kable(caption = "Regresión lineal simple") %>%
  kable_styling(bootstrap_options = c("striped","hover","condensed"))
Regresión lineal simple
Outcome Predictor B IC_95 p Sig
Hemoglobina (Intercept) 10.702 [10.362; 11.042] 0 ***
Hemoglobina ingesta_hierro 0.074 [0.06; 0.087] 0 ***
Hematocrito (Intercept) 31.658 [30.239; 33.077] 0 ***
Hematocrito ingesta_hierro 0.178 [0.122; 0.235] 0 ***

2.5 Regresión lineal múltiple ajustada

modelo_hb_multi <- lm(
  hemoglobina ~ ingesta_hierro + edad_anos + sexo + HAZ, data = base)
modelo_hto_multi <- lm(
  hematocrito ~ ingesta_hierro + edad_anos + sexo + HAZ, data = base)

bind_rows(
  tidy(modelo_hb_multi,  conf.int = TRUE) %>%
    mutate(Outcome = paste0("Hemoglobina (R²=",
                            round(summary(modelo_hb_multi)$r.squared,3),")")),
  tidy(modelo_hto_multi, conf.int = TRUE) %>%
    mutate(Outcome = paste0("Hematocrito (R²=",
                            round(summary(modelo_hto_multi)$r.squared,3),")"))
) %>%
  mutate(
    B     = round(estimate,  3),
    IC_95 = paste0("[", round(conf.low,3), "; ", round(conf.high,3), "]"),
    p     = round(p.value, 4),
    Sig   = case_when(p < 0.001 ~ "***", p < 0.01 ~ "**",
                      p < 0.05  ~ "*",   TRUE ~ "ns")
  ) %>%
  select(Outcome, Predictor = term, B, IC_95, p, Sig) %>%
  kable(caption = "Regresión lineal múltiple ajustada (edad, sexo, HAZ)") %>%
  kable_styling(bootstrap_options = c("striped","hover","condensed"))
Regresión lineal múltiple ajustada (edad, sexo, HAZ)
Outcome Predictor B IC_95 p Sig
Hemoglobina (R²=0.629) (Intercept) 10.536 [9.939; 11.133] 0.0000 ***
Hemoglobina (R²=0.629) ingesta_hierro 0.056 [0.039; 0.073] 0.0000 ***
Hemoglobina (R²=0.629) edad_anos 0.063 [0.017; 0.108] 0.0081 **
Hemoglobina (R²=0.629) sexoFemenino 0.039 [-0.327; 0.406] 0.8310 ns
Hemoglobina (R²=0.629) HAZ -0.029 [-0.159; 0.1] 0.6540 ns
Hematocrito (R²=0.363) (Intercept) 32.441 [29.863; 35.019] 0.0000 ***
Hematocrito (R²=0.363) ingesta_hierro 0.125 [0.053; 0.197] 0.0009 ***
Hematocrito (R²=0.363) edad_anos 0.125 [-0.07; 0.319] 0.2052 ns
Hematocrito (R²=0.363) sexoFemenino -0.665 [-2.246; 0.915] 0.4047 ns
Hematocrito (R²=0.363) HAZ 0.212 [-0.349; 0.773] 0.4542 ns

2.6 Gráficos dispersión

ggplot(base %>% drop_na(ingesta_hierro, hemoglobina),
       aes(x = ingesta_hierro, y = hemoglobina)) +
  geom_point(alpha = 0.7, color = "#4472C4", size = 2.5) +
  geom_smooth(method = "lm", se = TRUE, color = "#C00000") +
  labs(title = "Ingesta de hierro vs. Hemoglobina",
       x = "Ingesta de hierro (mg/día)", y = "Hemoglobina (g/dL)") +
  theme_bw(base_size = 12)
Ingesta de hierro vs. Hemoglobina

Ingesta de hierro vs. Hemoglobina

ggplot(base %>% drop_na(ingesta_hierro, hematocrito),
       aes(x = ingesta_hierro, y = hematocrito)) +
  geom_point(alpha = 0.7, color = "#70AD47", size = 2.5) +
  geom_smooth(method = "lm", se = TRUE, color = "#C00000") +
  labs(title = "Ingesta de hierro vs. Hematocrito",
       x = "Ingesta de hierro (mg/día)", y = "Hematocrito (%)") +
  theme_bw(base_size = 12)
Ingesta de hierro vs. Hematocrito

Ingesta de hierro vs. Hematocrito

3 Objetivo 3 — Z-scores de crecimiento ~ Hemoglobina y Hematocrito

3.1 Pruebas de normalidad

vars_norm3 <- list(
  list(var = "HAZ",         label = "HAZ"),
  list(var = "BAZ",         label = "BAZ"),
  list(var = "hemoglobina", label = "Hemoglobina"),
  list(var = "hematocrito", label = "Hematocrito")
)

map_dfr(vars_norm3, function(v) {
  x   <- base[[v$var]][!is.na(base[[v$var]])]
  res <- shapiro.test(x)
  tibble(Variable     = v$label,
         n            = length(x),
         W            = round(res$statistic, 4),
         p_valor      = round(res$p.value, 4),
         Distribucion = if_else(res$p.value >= 0.05, "Normal", "No normal"))
}) %>%
  kable(caption = "Prueba de Shapiro-Wilk — Objetivo 3") %>%
  kable_styling(bootstrap_options = c("striped","hover","condensed"),
                full_width = FALSE)
Prueba de Shapiro-Wilk — Objetivo 3
Variable n W p_valor Distribucion
HAZ 90 0.9234 0.0001 No normal
BAZ 90 0.9231 0.0001 No normal
Hemoglobina 88 0.9679 0.0278 No normal
Hematocrito 88 0.9460 0.0011 No normal

3.2 Correlaciones de Spearman con IC 95%

pares <- list(
  list(x="HAZ", y="hemoglobina", xl="HAZ", yl="Hemoglobina", rho= 0.5278),
  list(x="HAZ", y="hematocrito", xl="HAZ", yl="Hematocrito", rho= 0.3796),
  list(x="BAZ", y="hemoglobina", xl="BAZ", yl="Hemoglobina", rho=-0.4600),
  list(x="BAZ", y="hematocrito", xl="BAZ", yl="Hematocrito", rho=-0.2940)
)

n_obj3 <- sum(!is.na(base$HAZ) & !is.na(base$hemoglobina))

map_dfr(pares, function(p) {
  res <- suppressWarnings(
    cor.test(base[[p$x]], base[[p$y]],
             method = "spearman", exact = FALSE))
  ic <- calcular_ic_spearman(p$rho, n_obj3)
  tibble(
    Asociacion    = paste0(p$xl, " ~ ", p$yl),
    Metodo        = "Spearman",
    n             = n_obj3,
    rho           = round(res$estimate, 3),
    IC_95         = paste0("[", ic[1], "; ", ic[2], "]"),
    p_valor       = round(res$p.value, 4),
    Significativo = if_else(res$p.value < 0.05, "Sí", "No")
  )
}) %>%
  kable(caption = "Correlaciones de Spearman — Objetivo 3") %>%
  kable_styling(bootstrap_options = c("striped","hover","condensed"))
Correlaciones de Spearman — Objetivo 3
Asociacion Metodo n rho IC_95 p_valor Significativo
HAZ ~ Hemoglobina Spearman 88 0.528 [0.358; 0.664] 0.0000
HAZ ~ Hematocrito Spearman 88 0.380 [0.185; 0.546] 0.0003
BAZ ~ Hemoglobina Spearman 88 -0.460 [-0.611; -0.277] 0.0000
BAZ ~ Hematocrito Spearman 88 -0.294 [-0.474; -0.09] 0.0054

3.3 Gráficos dispersión

ggplot(base %>% drop_na(HAZ, hemoglobina),
       aes(x = HAZ, y = hemoglobina, color = grupo_edad)) +
  geom_point(alpha = 0.7, size = 2.5) +
  geom_smooth(method = "lm", se = TRUE) +
  geom_vline(xintercept = -2, linetype = "dashed",
             color = "gray40", linewidth = 0.6) +
  scale_color_manual(values = colores_grupo) +
  labs(title = "Z-score Talla/Edad (HAZ) vs. Hemoglobina",
       x = "Z-score HAZ", y = "Hemoglobina (g/dL)", color = "Grupo") +
  theme_bw(base_size = 12) + theme(legend.position = "bottom")
HAZ vs. Hemoglobina por grupo de edad

HAZ vs. Hemoglobina por grupo de edad

ggplot(base %>% drop_na(HAZ, hematocrito),
       aes(x = HAZ, y = hematocrito, color = grupo_edad)) +
  geom_point(alpha = 0.7, size = 2.5) +
  geom_smooth(method = "lm", se = TRUE) +
  geom_vline(xintercept = -2, linetype = "dashed",
             color = "gray40", linewidth = 0.6) +
  scale_color_manual(values = colores_grupo) +
  labs(title = "Z-score Talla/Edad (HAZ) vs. Hematocrito",
       x = "Z-score HAZ", y = "Hematocrito (%)", color = "Grupo") +
  theme_bw(base_size = 12) + theme(legend.position = "bottom")
HAZ vs. Hematocrito por grupo de edad

HAZ vs. Hematocrito por grupo de edad

ggplot(base %>% drop_na(BAZ, hemoglobina),
       aes(x = BAZ, y = hemoglobina, color = grupo_edad)) +
  geom_point(alpha = 0.7, size = 2.5) +
  geom_smooth(method = "lm", se = TRUE) +
  scale_color_manual(values = colores_grupo) +
  labs(title = "Z-score IMC/Edad (BAZ) vs. Hemoglobina",
       x = "Z-score BAZ", y = "Hemoglobina (g/dL)", color = "Grupo") +
  theme_bw(base_size = 12) + theme(legend.position = "bottom")
BAZ vs. Hemoglobina por grupo de edad

BAZ vs. Hemoglobina por grupo de edad

ggplot(base %>% drop_na(BAZ, hematocrito),
       aes(x = BAZ, y = hematocrito, color = grupo_edad)) +
  geom_point(alpha = 0.7, size = 2.5) +
  geom_smooth(method = "lm", se = TRUE) +
  scale_color_manual(values = colores_grupo) +
  labs(title = "Z-score IMC/Edad (BAZ) vs. Hematocrito",
       x = "Z-score BAZ", y = "Hematocrito (%)", color = "Grupo") +
  theme_bw(base_size = 12) + theme(legend.position = "bottom")
BAZ vs. Hematocrito por grupo de edad

BAZ vs. Hematocrito por grupo de edad