Este archivo reproduce el análisis estadístico utilizado para caracterizar los puntajes del CAPL-2 en escolares colombianos y comparar los resultados entre las seis subregiones del país: Caribe, Pacífico, Centro-Oriente, Centro sur-Amazonía, Eje cafetero-Antioquia y Llanos-Orinoquía.
El análisis incluye: caracterización sociodemográfica, disponibilidad de datos por dominio, descripción de puntajes, figuras de dominios y categorías interpretativas, pruebas de chi-cuadrado para categorías, evaluación de normalidad, comparación de puntajes mediante Kruskal-Wallis, estimación de epsilon cuadrado como tamaño del efecto y comparaciones post hoc mediante prueba de Dunn.
paquetes <- c(
"readxl", "writexl", "dplyr", "tidyr", "stringr", "forcats",
"ggplot2", "scales", "rstatix", "janitor", "purrr", "flextable"
)
instalar <- paquetes[!paquetes %in% rownames(installed.packages())]
if(length(instalar) > 0){
install.packages(instalar)
}
invisible(lapply(paquetes, library, character.only = TRUE))
La base de entrada debe corresponder a la base calculada con el
paquete capl, es decir, debe contener los puntajes por
dominio, el puntaje total, las variables de estado de completitud y las
categorías interpretativas.
# Ajustar esta ruta si el archivo está en otra carpeta.
ruta_base <- "FASE3_validacion_calculo_CAPL2_caracterizacion.xlsx"
if(!file.exists(ruta_base)){
stop("No se encontró el archivo de entrada. Verifique la ruta_base.")
}
hojas <- readxl::excel_sheets(ruta_base)
print(hojas)
## [1] "resultados_capl" "validacion_estructura"
## [3] "validacion_variables_capl" "na_scores_capl"
## [5] "status_capl" "estatus_por_dominio"
## [7] "status_por_region" "disponibilidad_dominios"
## [9] "disponibilidad_region" "resumen_podometro_region"
## [11] "dias_validos_region" "rangos_scores_capl"
# El código intenta identificar automáticamente una hoja que contenga resultados CAPL.
hoja_resultados <- hojas[stringr::str_detect(tolower(hojas), "resultado|capl|calculo")][1]
# Si no se identifica, se usa la primera hoja.
if(is.na(hoja_resultados)){
hoja_resultados <- hojas[1]
}
resultados_capl <- readxl::read_excel(ruta_base, sheet = hoja_resultados) %>%
janitor::clean_names()
cat("Hoja utilizada:", hoja_resultados, "\n")
## Hoja utilizada: resultados_capl
cat("Dimensiones de la base:", nrow(resultados_capl), "filas x", ncol(resultados_capl), "columnas\n")
## Dimensiones de la base: 843 filas x 107 columnas
# Esta sección permite que el archivo funcione aunque la variable de subregión
# haya quedado nombrada como region, subregion o sub_region.
if(!"region" %in% names(resultados_capl)){
if("subregion" %in% names(resultados_capl)){
resultados_capl <- resultados_capl %>% rename(region = subregion)
} else if("sub_region" %in% names(resultados_capl)){
resultados_capl <- resultados_capl %>% rename(region = sub_region)
} else {
stop("No se encontró una variable de región/subregión.")
}
}
if(!"gender" %in% names(resultados_capl)){
if("sexo" %in% names(resultados_capl)){
resultados_capl <- resultados_capl %>% rename(gender = sexo)
}
}
# Orden analítico de subregiones.
orden_region <- c(
"Caribe",
"Pacífico",
"Centro-Oriente",
"Centro sur-Amazonía",
"Eje cafetero-Antioquia",
"Llanos-Orinoquía"
)
resultados_capl <- resultados_capl %>%
mutate(
region = factor(region, levels = orden_region),
gender = as.character(gender)
)
vars_requeridas <- c(
"region", "age", "gender", "grade",
"pc_score", "db_score", "mc_score", "ku_score", "capl_score",
"pc_status", "db_status", "mc_status", "ku_status", "capl_status",
"pc_interpretation", "db_interpretation", "mc_interpretation", "ku_interpretation", "capl_interpretation"
)
faltantes <- setdiff(vars_requeridas, names(resultados_capl))
if(length(faltantes) > 0){
stop(paste("Faltan variables requeridas:", paste(faltantes, collapse = ", ")))
}
cat("Todas las variables requeridas están disponibles.\n")
## Todas las variables requeridas están disponibles.
# Recodificación simple del sexo para presentación.
base_caracterizacion <- resultados_capl %>%
mutate(
sexo_rec = case_when(
str_to_lower(gender) %in% c("male", "m", "masculino", "niño", "nino", "hombre") ~ "Niños",
str_to_lower(gender) %in% c("female", "f", "femenino", "niña", "nina", "mujer") ~ "Niñas",
TRUE ~ as.character(gender)
)
)
tabla_1 <- base_caracterizacion %>%
group_by(region) %>%
summarise(
n = n(),
edad_media = mean(age, na.rm = TRUE),
edad_de = sd(age, na.rm = TRUE),
edad_mediana = median(age, na.rm = TRUE),
edad_q1 = quantile(age, 0.25, na.rm = TRUE),
edad_q3 = quantile(age, 0.75, na.rm = TRUE),
n_ninos = sum(sexo_rec == "Niños", na.rm = TRUE),
n_ninas = sum(sexo_rec == "Niñas", na.rm = TRUE),
pct_ninos = n_ninos / n * 100,
pct_ninas = n_ninas / n * 100,
.groups = "drop"
) %>%
mutate(
`Edad media ± DE` = sprintf("%.2f ± %.2f", edad_media, edad_de),
`Edad mediana [RIQ]` = sprintf("%.0f [%.0f–%.0f]", edad_mediana, edad_q1, edad_q3),
`Niños n (%)` = sprintf("%d (%.1f%%)", n_ninos, pct_ninos),
`Niñas n (%)` = sprintf("%d (%.1f%%)", n_ninas, pct_ninas)
) %>%
select(
Subregión = region,
n,
`Edad media ± DE`,
`Edad mediana [RIQ]`,
`Niños n (%)`,
`Niñas n (%)`
)
tabla_1
## # A tibble: 6 × 6
## Subregión n `Edad media ± DE` `Edad mediana [RIQ]` `Niños n (%)`
## <fct> <int> <chr> <chr> <chr>
## 1 Caribe 140 9.91 ± 1.36 10 [9–11] 0 (0.0%)
## 2 Pacífico 140 9.99 ± 1.40 10 [9–11] 0 (0.0%)
## 3 Centro-Oriente 140 10.01 ± 1.44 10 [9–11] 0 (0.0%)
## 4 Centro sur-Amazonía 141 10.00 ± 1.41 10 [9–11] 0 (0.0%)
## 5 Eje cafetero-Antio… 141 10.01 ± 1.42 10 [9–11] 0 (0.0%)
## 6 Llanos-Orinoquía 141 10.01 ± 1.42 10 [9–11] 0 (0.0%)
## # ℹ 1 more variable: `Niñas n (%)` <chr>
resumen_grado <- base_caracterizacion %>%
count(grade, name = "n") %>%
mutate(porcentaje = n / sum(n) * 100) %>%
arrange(grade)
resumen_grado
## # A tibble: 8 × 3
## grade n porcentaje
## <dbl> <int> <dbl>
## 1 2 17 2.02
## 2 3 140 16.6
## 3 4 207 24.6
## 4 5 131 15.5
## 5 6 208 24.7
## 6 7 111 13.2
## 7 8 1 0.119
## 8 NA 28 3.32
tabla_2 <- tibble::tibble(
Dominio = c(
"Competencia física",
"Comportamiento diario",
"Motivación y confianza",
"Conocimiento y comprensión",
"CAPL total"
),
status = c("pc_status", "db_status", "mc_status", "ku_status", "capl_status")
) %>%
mutate(
n_total = nrow(resultados_capl),
n_valido = purrr::map_int(status, ~sum(resultados_capl[[.x]] == "complete", na.rm = TRUE)),
pct_valido = n_valido / n_total * 100,
n_incompleto = n_total - n_valido,
pct_incompleto = n_incompleto / n_total * 100
) %>%
select(
Dominio,
`n total` = n_total,
`n válido` = n_valido,
`% válido` = pct_valido,
`n incompleto` = n_incompleto,
`% incompleto` = pct_incompleto
) %>%
mutate(
across(c(`% válido`, `% incompleto`), ~round(.x, 1))
)
tabla_2
## # A tibble: 5 × 6
## Dominio `n total` `n válido` `% válido` `n incompleto` `% incompleto`
## <chr> <int> <int> <dbl> <int> <dbl>
## 1 Competencia fís… 843 829 98.3 14 1.7
## 2 Comportamiento … 843 819 97.2 24 2.8
## 3 Motivación y co… 843 834 98.9 9 1.1
## 4 Conocimiento y … 843 839 99.5 4 0.5
## 5 CAPL total 843 816 96.8 27 3.2
tabla_3 <- resultados_capl %>%
filter(capl_status == "complete", !is.na(capl_score), !is.na(region)) %>%
group_by(region) %>%
summarise(
n = n(),
media = mean(capl_score, na.rm = TRUE),
de = sd(capl_score, na.rm = TRUE),
mediana = median(capl_score, na.rm = TRUE),
q1 = quantile(capl_score, 0.25, na.rm = TRUE),
q3 = quantile(capl_score, 0.75, na.rm = TRUE),
.groups = "drop"
) %>%
mutate(
`Media ± DE` = sprintf("%.2f ± %.2f", media, de),
`Mediana [RIQ]` = sprintf("%.2f [%.2f–%.2f]", mediana, q1, q3)
) %>%
select(Subregión = region, n, `Media ± DE`, `Mediana [RIQ]`)
tabla_3
## # A tibble: 6 × 4
## Subregión n `Media ± DE` `Mediana [RIQ]`
## <fct> <int> <chr> <chr>
## 1 Caribe 125 49.35 ± 7.40 49.80 [44.80–55.30]
## 2 Pacífico 139 56.82 ± 8.14 57.10 [52.20–63.30]
## 3 Centro-Oriente 134 54.62 ± 11.42 53.05 [46.02–62.00]
## 4 Centro sur-Amazonía 138 60.18 ± 12.02 59.33 [51.15–69.07]
## 5 Eje cafetero-Antioquia 141 47.50 ± 12.73 45.30 [37.50–57.60]
## 6 Llanos-Orinoquía 139 63.55 ± 8.32 62.63 [57.25–69.62]
Los dominios se expresan como porcentaje del máximo teórico para facilitar la comparación visual, dado que conocimiento y comprensión tiene un máximo de 10 puntos, mientras que los demás dominios tienen máximo de 30 puntos.
base_dominios_larga <- bind_rows(
resultados_capl %>%
filter(pc_status == "complete") %>%
transmute(region, dominio = "Competencia física", puntaje = pc_score, maximo = 30),
resultados_capl %>%
filter(db_status == "complete") %>%
transmute(region, dominio = "Comportamiento diario", puntaje = db_score, maximo = 30),
resultados_capl %>%
filter(mc_status == "complete") %>%
transmute(region, dominio = "Motivación y confianza", puntaje = mc_score, maximo = 30),
resultados_capl %>%
filter(ku_status == "complete") %>%
transmute(region, dominio = "Conocimiento y comprensión", puntaje = ku_score, maximo = 10)
) %>%
filter(!is.na(region), !is.na(puntaje)) %>%
mutate(
region = factor(region, levels = orden_region),
dominio = factor(
dominio,
levels = c(
"Competencia física",
"Comportamiento diario",
"Motivación y confianza",
"Conocimiento y comprensión"
)
),
porcentaje_maximo = puntaje / maximo * 100
)
resumen_dominios_region <- base_dominios_larga %>%
group_by(region, dominio) %>%
summarise(
n = n(),
mediana = median(puntaje, na.rm = TRUE),
q1 = quantile(puntaje, 0.25, na.rm = TRUE),
q3 = quantile(puntaje, 0.75, na.rm = TRUE),
mediana_porcentaje = median(porcentaje_maximo, na.rm = TRUE),
q1_porcentaje = quantile(porcentaje_maximo, 0.25, na.rm = TRUE),
q3_porcentaje = quantile(porcentaje_maximo, 0.75, na.rm = TRUE),
.groups = "drop"
)
resumen_dominios_region
## # A tibble: 24 × 9
## region dominio n mediana q1 q3 mediana_porcentaje q1_porcentaje
## <fct> <fct> <int> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 Caribe Compet… 140 9 6 13.5 30 20
## 2 Caribe Compor… 127 9 7 12 30 23.3
## 3 Caribe Motiva… 138 24.4 22.1 27 81.3 73.7
## 4 Caribe Conoci… 140 4 3 6 40 30
## 5 Pacífico Compet… 139 7.5 6 12 25 20
## 6 Pacífico Compor… 139 17 12 20 56.7 40
## 7 Pacífico Motiva… 140 25.0 21.9 27.4 83.2 72.9
## 8 Pacífico Conoci… 140 7 6 9 70 60
## 9 Centro-Or… Compet… 128 12 9 16.5 40 30
## 10 Centro-Or… Compor… 135 11 8 18 36.7 26.7
## # ℹ 14 more rows
## # ℹ 1 more variable: q3_porcentaje <dbl>
figura_1 <- ggplot(
resumen_dominios_region,
aes(x = region, y = mediana_porcentaje)
) +
geom_errorbar(
aes(ymin = q1_porcentaje, ymax = q3_porcentaje),
width = 0.18,
linewidth = 0.45
) +
geom_point(size = 2.8) +
coord_flip() +
facet_wrap(~ dominio, ncol = 2) +
scale_y_continuous(
limits = c(0, 100),
breaks = seq(0, 100, 20),
labels = function(x) paste0(x, "%")
) +
labs(
title = NULL,
subtitle = "Mediana e intervalo intercuartílico expresados como porcentaje del máximo teórico",
x = NULL,
y = "Porcentaje del máximo teórico"
) +
theme_minimal(base_size = 12) +
theme(
plot.subtitle = element_text(size = 10),
strip.text = element_text(face = "bold", size = 10),
axis.text.y = element_text(size = 9),
axis.text.x = element_text(size = 9),
panel.grid.major.y = element_blank(),
panel.grid.minor = element_blank()
)
figura_1
Figura 1. Dominios del CAPL-2 según subregión. Los puntos representan la mediana y las barras el rango intercuartílico. Los valores se expresan como porcentaje del máximo teórico de cada dominio.
orden_categorias <- c("beginning", "progressing", "achieving", "excelling")
# Función para estandarizar categorías.
normalizar_categoria <- function(x){
x %>%
as.character() %>%
stringr::str_trim() %>%
stringr::str_to_lower()
}
base_cat_capl <- resultados_capl %>%
filter(capl_status == "complete", !is.na(capl_interpretation), !is.na(region)) %>%
mutate(
categoria = factor(normalizar_categoria(capl_interpretation), levels = orden_categorias),
region = factor(region, levels = orden_region)
)
resumen_cat_capl <- base_cat_capl %>%
count(region, categoria, name = "n") %>%
group_by(region) %>%
mutate(
porcentaje = n / sum(n) * 100
) %>%
ungroup()
figura_2 <- ggplot(
resumen_cat_capl,
aes(x = region, y = porcentaje, fill = categoria)
) +
geom_col(width = 0.72) +
coord_flip() +
scale_y_continuous(
limits = c(0, 100),
breaks = seq(0, 100, 25),
labels = function(x) paste0(x, "%")
) +
labs(
title = NULL,
x = NULL,
y = "Proporción",
fill = "Categoría"
) +
theme_minimal(base_size = 12) +
theme(
axis.text.y = element_text(size = 10),
axis.text.x = element_text(size = 10),
legend.position = "right",
panel.grid.major.y = element_blank(),
panel.grid.minor = element_blank()
)
figura_2
Se utilizó la prueba de chi-cuadrado de Pearson para evaluar la asociación entre subregión y categorías interpretativas. El análisis se realizó para el puntaje total del CAPL-2 y para cada dominio.
calcular_chi <- function(datos, variable_categoria, variable_status, dominio_nombre){
base <- datos %>%
filter(.data[[variable_status]] == "complete") %>%
mutate(
categoria = factor(normalizar_categoria(.data[[variable_categoria]]), levels = orden_categorias),
region = factor(region, levels = orden_region)
) %>%
filter(!is.na(region), !is.na(categoria))
tabla <- table(base$region, base$categoria)
prueba <- suppressWarnings(chisq.test(tabla, correct = FALSE))
tibble::tibble(
dominio = dominio_nombre,
metodo = "Chi-cuadrado de Pearson",
estadistico = unname(prueba$statistic),
gl = unname(prueba$parameter),
p_valor = prueba$p.value,
n = sum(tabla),
celdas_esperadas_menor_5 = sum(prueba$expected < 5),
significancia = case_when(
p_valor < 0.001 ~ "<0.001",
TRUE ~ sprintf("%.3f", p_valor)
),
nota = ifelse(
celdas_esperadas_menor_5 > 0,
"Interpretar con cautela por frecuencias esperadas bajas",
"Frecuencias esperadas adecuadas"
)
)
}
tabla_chi_categorias <- bind_rows(
calcular_chi(resultados_capl, "pc_interpretation", "pc_status", "Competencia física"),
calcular_chi(resultados_capl, "db_interpretation", "db_status", "Comportamiento diario"),
calcular_chi(resultados_capl, "mc_interpretation", "mc_status", "Motivación y confianza"),
calcular_chi(resultados_capl, "ku_interpretation", "ku_status", "Conocimiento y comprensión"),
calcular_chi(resultados_capl, "capl_interpretation", "capl_status", "CAPL total")
) %>%
mutate(
estadistico = round(estadistico, 3),
p = significancia
) %>%
select(
Dominio = dominio,
Prueba = metodo,
`χ²` = estadistico,
gl,
n,
p,
Nota = nota
)
tabla_chi_categorias
## # A tibble: 5 × 7
## Dominio Prueba `χ²` gl n p Nota
## <chr> <chr> <dbl> <int> <int> <chr> <chr>
## 1 Competencia física Chi-cuadrado de Pear… 90.0 15 829 <0.0… Inte…
## 2 Comportamiento diario Chi-cuadrado de Pear… 155. 15 819 <0.0… Frec…
## 3 Motivación y confianza Chi-cuadrado de Pear… 212. 15 834 <0.0… Frec…
## 4 Conocimiento y comprensión Chi-cuadrado de Pear… 322. 15 839 <0.0… Frec…
## 5 CAPL total Chi-cuadrado de Pear… 213. 15 816 <0.0… Frec…
La normalidad se evaluó mediante la prueba de Shapiro-Wilk en cada subregión para el puntaje total y los dominios del CAPL-2. Estos resultados se utilizaron para definir la prueba comparativa entre subregiones.
base_puntajes_larga <- bind_rows(
resultados_capl %>%
filter(capl_status == "complete") %>%
transmute(region, dominio = "CAPL total", puntaje = capl_score),
resultados_capl %>%
filter(pc_status == "complete") %>%
transmute(region, dominio = "Competencia física", puntaje = pc_score),
resultados_capl %>%
filter(db_status == "complete") %>%
transmute(region, dominio = "Comportamiento diario", puntaje = db_score),
resultados_capl %>%
filter(mc_status == "complete") %>%
transmute(region, dominio = "Motivación y confianza", puntaje = mc_score),
resultados_capl %>%
filter(ku_status == "complete") %>%
transmute(region, dominio = "Conocimiento y comprensión", puntaje = ku_score)
) %>%
filter(!is.na(region), !is.na(puntaje)) %>%
mutate(
region = factor(region, levels = orden_region),
dominio = factor(
dominio,
levels = c(
"CAPL total",
"Competencia física",
"Comportamiento diario",
"Motivación y confianza",
"Conocimiento y comprensión"
)
)
)
normalidad <- base_puntajes_larga %>%
group_by(dominio, region) %>%
shapiro_test(puntaje) %>%
ungroup() %>%
mutate(
decision = ifelse(p < 0.05, "No normal", "Compatible con normalidad")
)
normalidad
## # A tibble: 30 × 6
## region dominio variable statistic p decision
## <fct> <fct> <chr> <dbl> <dbl> <chr>
## 1 Caribe CAPL total puntaje 0.990 5.28e-1 Compati…
## 2 Pacífico CAPL total puntaje 0.987 2.02e-1 Compati…
## 3 Centro-Oriente CAPL total puntaje 0.981 5.18e-2 Compati…
## 4 Centro sur-Amazonía CAPL total puntaje 0.982 7.38e-2 Compati…
## 5 Eje cafetero-Antioquia CAPL total puntaje 0.963 7.77e-4 No norm…
## 6 Llanos-Orinoquía CAPL total puntaje 0.990 3.98e-1 Compati…
## 7 Caribe Competencia física puntaje 0.941 1.16e-5 No norm…
## 8 Pacífico Competencia física puntaje 0.922 6.32e-7 No norm…
## 9 Centro-Oriente Competencia física puntaje 0.970 6.52e-3 No norm…
## 10 Centro sur-Amazonía Competencia física puntaje 0.981 5.13e-2 Compati…
## # ℹ 20 more rows
Dado que los puntajes no cumplieron normalidad en todos los grupos, se utilizó la prueba no paramétrica de Kruskal-Wallis para comparar subregiones. El tamaño del efecto se estimó mediante epsilon cuadrado.
calcular_kruskal <- function(datos, dominio_nombre){
prueba <- kruskal.test(puntaje ~ region, data = datos)
n <- nrow(datos)
k <- dplyr::n_distinct(datos$region)
H <- unname(prueba$statistic)
gl <- unname(prueba$parameter)
p <- prueba$p.value
# Epsilon cuadrado para Kruskal-Wallis.
# Fórmula usada: epsilon² = (H - k + 1) / (n - k)
epsilon2 <- (H - k + 1) / (n - k)
tibble::tibble(
Dominio = dominio_nombre,
Prueba = "Kruskal-Wallis",
H = H,
gl = gl,
p_valor = p,
n = n,
epsilon2 = epsilon2,
Magnitud = case_when(
epsilon2 < 0.01 ~ "Muy pequeña",
epsilon2 < 0.06 ~ "Pequeña",
epsilon2 < 0.14 ~ "Moderada",
TRUE ~ "Grande"
)
)
}
tabla_kruskal <- base_puntajes_larga %>%
group_split(dominio) %>%
purrr::map_dfr(~calcular_kruskal(.x, as.character(unique(.x$dominio)))) %>%
mutate(
H = round(H, 3),
p = ifelse(p_valor < 0.001, "<0.001", sprintf("%.3f", p_valor)),
epsilon2 = round(epsilon2, 3)
) %>%
select(
Dominio,
Prueba,
H,
gl,
p,
`ε²` = epsilon2,
Magnitud
)
tabla_kruskal
## # A tibble: 5 × 7
## Dominio Prueba H gl p `ε²` Magnitud
## <chr> <chr> <dbl> <int> <chr> <dbl> <chr>
## 1 CAPL total Kruskal-Wallis 190. 5 <0.001 0.228 Grande
## 2 Competencia física Kruskal-Wallis 120. 5 <0.001 0.14 Grande
## 3 Comportamiento diario Kruskal-Wallis 154. 5 <0.001 0.183 Grande
## 4 Motivación y confianza Kruskal-Wallis 221. 5 <0.001 0.261 Grande
## 5 Conocimiento y comprensión Kruskal-Wallis 296. 5 <0.001 0.349 Grande
Se aplicó la prueba de Dunn cuando Kruskal-Wallis mostró diferencias estadísticamente significativas. Para el cuerpo del documento se seleccionaron contrastes significativos relevantes por dominio.
posthoc_dunn <- base_puntajes_larga %>%
group_by(dominio) %>%
dunn_test(puntaje ~ region, p.adjust.method = "holm") %>%
ungroup()
posthoc_dunn_resumen <- posthoc_dunn %>%
mutate(
p_ajustada = p.adj,
significancia = case_when(
p_ajustada < 0.001 ~ "<0.001",
TRUE ~ sprintf("%.3f", p_ajustada)
),
z_abs = abs(statistic)
) %>%
arrange(dominio, desc(z_abs))
posthoc_dunn_resumen
## # A tibble: 75 × 13
## dominio .y. group1 group2 n1 n2 statistic p p.adj
## <fct> <chr> <chr> <chr> <int> <int> <dbl> <dbl> <dbl>
## 1 CAPL total puntaje Eje cafete… Llano… 141 139 11.3 2.08e-29 3.12e-28
## 2 CAPL total puntaje Caribe Llano… 125 139 10.5 6.20e-26 8.68e-25
## 3 CAPL total puntaje Centro sur… Eje c… 138 141 -8.09 5.89e-16 7.65e-15
## 4 CAPL total puntaje Caribe Centr… 125 138 7.46 8.59e-14 1.03e-12
## 5 CAPL total puntaje Centro-Ori… Llano… 134 139 6.75 1.47e-11 1.62e-10
## 6 CAPL total puntaje Pacífico Eje c… 139 141 -6.47 9.71e-11 9.71e-10
## 7 CAPL total puntaje Caribe Pacíf… 125 139 5.89 3.90e- 9 3.51e- 8
## 8 CAPL total puntaje Pacífico Llano… 139 139 4.77 1.83e- 6 1.47e- 5
## 9 CAPL total puntaje Centro-Ori… Eje c… 134 141 -4.38 1.18e- 5 8.28e- 5
## 10 CAPL total puntaje Caribe Centr… 125 134 3.87 1.10e- 4 6.61e- 4
## # ℹ 65 more rows
## # ℹ 4 more variables: p.adj.signif <chr>, p_ajustada <dbl>,
## # significancia <chr>, z_abs <dbl>
Esta tabla reproduce la lógica usada en el documento: se seleccionan contrastes significativos de mayor utilidad para interpretar los patrones descriptivos observados previamente.
# Medianas por dominio y subregión para anexarlas a los contrastes.
medianas_dominios <- base_puntajes_larga %>%
group_by(dominio, region) %>%
summarise(mediana = median(puntaje, na.rm = TRUE), .groups = "drop")
posthoc_significativos <- posthoc_dunn_resumen %>%
filter(p_ajustada < 0.05) %>%
left_join(
medianas_dominios,
by = c("dominio", "group1" = "region")
) %>%
rename(mediana_group1 = mediana) %>%
left_join(
medianas_dominios,
by = c("dominio", "group2" = "region")
) %>%
rename(mediana_group2 = mediana) %>%
mutate(
grupo_mayor = ifelse(mediana_group1 >= mediana_group2, as.character(group1), as.character(group2)),
grupo_menor = ifelse(mediana_group1 >= mediana_group2, as.character(group2), as.character(group1)),
mediana_mayor = pmax(mediana_group1, mediana_group2),
mediana_menor = pmin(mediana_group1, mediana_group2),
contraste = paste0(grupo_mayor, " > ", grupo_menor)
)
# Selección manual de los contrastes que se reportaron en resultados.
contrastes_seleccionados <- tribble(
~dominio, ~grupo_mayor, ~grupo_menor,
"CAPL total", "Llanos-Orinoquía", "Eje cafetero-Antioquia",
"CAPL total", "Llanos-Orinoquía", "Caribe",
"CAPL total", "Centro sur-Amazonía", "Eje cafetero-Antioquia",
"CAPL total", "Pacífico", "Eje cafetero-Antioquia",
"Competencia física", "Centro sur-Amazonía", "Pacífico",
"Competencia física", "Centro sur-Amazonía", "Caribe",
"Competencia física", "Llanos-Orinoquía", "Pacífico",
"Comportamiento diario", "Llanos-Orinoquía", "Caribe",
"Comportamiento diario", "Pacífico", "Caribe",
"Comportamiento diario", "Llanos-Orinoquía", "Centro-Oriente",
"Conocimiento y comprensión", "Llanos-Orinoquía", "Eje cafetero-Antioquia",
"Conocimiento y comprensión", "Pacífico", "Eje cafetero-Antioquia",
"Conocimiento y comprensión", "Llanos-Orinoquía", "Caribe",
"Motivación y confianza", "Centro sur-Amazonía", "Eje cafetero-Antioquia",
"Motivación y confianza", "Pacífico", "Eje cafetero-Antioquia",
"Motivación y confianza", "Caribe", "Eje cafetero-Antioquia"
)
tabla_posthoc_seleccionada <- posthoc_significativos %>%
semi_join(contrastes_seleccionados, by = c("dominio", "grupo_mayor", "grupo_menor")) %>%
mutate(
`Contraste significativo` = paste0(grupo_mayor, " > ", grupo_menor),
`Mediana grupo mayor` = round(mediana_mayor, 2),
`Mediana grupo menor` = round(mediana_menor, 2),
`|Z| Dunn` = round(z_abs, 3),
`p ajustada` = ifelse(p_ajustada < 0.001, "<0.001", sprintf("%.3f", p_ajustada))
) %>%
select(
Dominio = dominio,
`Contraste significativo`,
`Mediana grupo mayor`,
`Mediana grupo menor`,
`|Z| Dunn`,
`p ajustada`
)
tabla_posthoc_seleccionada
## # A tibble: 16 × 6
## Dominio Contraste significat…¹ `Mediana grupo mayor` `Mediana grupo menor`
## <fct> <chr> <dbl> <dbl>
## 1 CAPL total Llanos-Orinoquía > Ej… 62.6 45.3
## 2 CAPL total Llanos-Orinoquía > Ca… 62.6 49.8
## 3 CAPL total Centro sur-Amazonía >… 59.3 45.3
## 4 CAPL total Pacífico > Eje cafete… 57.1 45.3
## 5 Competenc… Centro sur-Amazonía >… 16 7.5
## 6 Competenc… Centro sur-Amazonía >… 16 9
## 7 Competenc… Llanos-Orinoquía > Pa… 12 7.5
## 8 Comportam… Llanos-Orinoquía > Ca… 19 9
## 9 Comportam… Pacífico > Caribe 17 9
## 10 Comportam… Llanos-Orinoquía > Ce… 19 11
## 11 Motivació… Centro sur-Amazonía >… 25.1 18.3
## 12 Motivació… Pacífico > Eje cafete… 25.0 18.3
## 13 Motivació… Caribe > Eje cafetero… 24.4 18.3
## 14 Conocimie… Llanos-Orinoquía > Ej… 8 4
## 15 Conocimie… Pacífico > Eje cafete… 7 4
## 16 Conocimie… Llanos-Orinoquía > Ca… 8 4
## # ℹ abbreviated name: ¹`Contraste significativo`
## # ℹ 2 more variables: `|Z| Dunn` <dbl>, `p ajustada` <chr>
dir.create("salidas_CAPL2_caracterizacion", showWarnings = FALSE)
dir.create("salidas_CAPL2_caracterizacion/figuras", showWarnings = FALSE)
writexl::write_xlsx(
list(
"tabla_1_caracterizacion" = tabla_1,
"grado_escolar" = resumen_grado,
"tabla_2_disponibilidad" = tabla_2,
"tabla_3_capl_total" = tabla_3,
"resumen_dominios_region" = resumen_dominios_region,
"categorias_capl_total" = resumen_cat_capl,
"tabla_chi_categorias" = tabla_chi_categorias,
"normalidad" = normalidad,
"tabla_kruskal" = tabla_kruskal,
"posthoc_dunn_completo" = posthoc_dunn_resumen,
"tabla_posthoc_seleccionada" = tabla_posthoc_seleccionada
),
"salidas_CAPL2_caracterizacion/tablas_CAPL2_caracterizacion.xlsx"
)
ggsave(
filename = "salidas_CAPL2_caracterizacion/figuras/Figura_1_dominios_CAPL2_subregion.png",
plot = figura_1,
width = 10,
height = 7,
dpi = 600
)
ggsave(
filename = "salidas_CAPL2_caracterizacion/figuras/Figura_2_categorias_CAPL_total_subregion.png",
plot = figura_2,
width = 10,
height = 6,
dpi = 600
)
cat("\nAnálisis finalizado. Revise la carpeta salidas_CAPL2_caracterizacion.\n")
##
## Análisis finalizado. Revise la carpeta salidas_CAPL2_caracterizacion.
sessionInfo()
## R version 4.5.1 (2025-06-13 ucrt)
## Platform: x86_64-w64-mingw32/x64
## Running under: Windows 11 x64 (build 26200)
##
## Matrix products: default
## LAPACK version 3.12.1
##
## locale:
## [1] LC_COLLATE=Spanish_Colombia.utf8 LC_CTYPE=Spanish_Colombia.utf8
## [3] LC_MONETARY=Spanish_Colombia.utf8 LC_NUMERIC=C
## [5] LC_TIME=Spanish_Colombia.utf8
##
## time zone: America/Bogota
## tzcode source: internal
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] flextable_0.9.11 purrr_1.1.0 janitor_2.2.1 rstatix_0.7.2
## [5] scales_1.4.0 ggplot2_4.0.1 forcats_1.0.0 stringr_1.5.1
## [9] tidyr_1.3.1 dplyr_1.2.0 writexl_1.5.4 readxl_1.4.5
##
## loaded via a namespace (and not attached):
## [1] gtable_0.3.6 xfun_0.55 bslib_0.9.0
## [4] vctrs_0.7.1 tools_4.5.1 generics_0.1.4
## [7] tibble_3.3.0 pkgconfig_2.0.3 data.table_1.17.8
## [10] RColorBrewer_1.1-3 S7_0.2.1 uuid_1.2-1
## [13] lifecycle_1.0.5 compiler_4.5.1 farver_2.1.2
## [16] textshaping_1.0.1 carData_3.0-5 snakecase_0.11.1
## [19] fontquiver_0.2.1 fontLiberation_0.1.0 htmltools_0.5.8.1
## [22] sass_0.4.10 yaml_2.3.10 Formula_1.2-5
## [25] pillar_1.11.0 car_3.1-3 jquerylib_0.1.4
## [28] openssl_2.3.3 cachem_1.1.0 abind_1.4-8
## [31] fontBitstreamVera_0.1.1 zip_2.3.3 tidyselect_1.2.1
## [34] digest_0.6.37 stringi_1.8.7 fastmap_1.2.0
## [37] grid_4.5.1 cli_3.6.6 magrittr_2.0.3
## [40] patchwork_1.3.1 utf8_1.2.6 broom_1.0.8
## [43] withr_3.0.2 gdtools_0.5.0 backports_1.5.0
## [46] lubridate_1.9.4 timechange_0.3.0 rmarkdown_2.29
## [49] officer_0.7.3 cellranger_1.1.0 askpass_1.2.1
## [52] ragg_1.4.0 evaluate_1.0.4 knitr_1.50
## [55] rlang_1.2.0 Rcpp_1.1.0 glue_1.8.0
## [58] xml2_1.3.8 rstudioapi_0.17.1 jsonlite_2.0.0
## [61] R6_2.6.1 systemfonts_1.3.1