Este documento reproduce íntegramente los análisis del apartado de Resultados. Cada tabla y figura del manuscrito se genera aquí a partir de los ficheros de datos originales, sin pasos manuales intermedios. El código permanece visible en todos los bloques.

1 Paquetes y parámetros globales

library(readxl)      
library(dplyr)       
library(tidyr)       
library(ggplot2)     
library(purrr)      
library(forcats)     
library(knitr)       
library(kableExtra) 
library(stringr)


col_no_fuerte  <- "#E6F1FB"
col_si_fuerte  <- "#85B7EB"
col_azul       <- "#185FA5"
col_azul_suave <- "#B5D4F4"
col_rojo       <- "#C0392B"
pal_pais <- c("España" = "#185FA5", "México" = "#4E93D9", "Chile" = "#B5D4F4")


DIMS <- c("genero","paz","ddhh","justeco","justamb",
          "intercul","bienestar","cuidado","digital")
LAB  <- c(genero    = "Género y feminismos",
          paz       = "Cultura de paz",
          ddhh      = "Derechos humanos",
          justeco   = "Justicia económica y social",
          justamb   = "Justicia ambiental",
          intercul  = "Interculturalidad",
          bienestar = "Bienestar emocional",
          cuidado   = "Cuidado de la relación educativa",
          digital   = "Equidad digital y tecnología")


TRAMOS <- c("0 a 5 años","6 a 10 años","11 a 15 años","16 a 20 años",
            "21 a 25 años","26 a 30 años","31 a 35 años","Más de 35 años")

PAISES <- c("España","México","Chile")
set.seed(42)

2 Funciones auxiliares

Se definen aquí todas las funciones de cálculo empleadas más adelante, de modo que los criterios estadísticos queden explícitos y sean auditables.

num <- function(x) suppressWarnings(as.numeric(x))

si01 <- function(x) as.integer(grepl("^s", trimws(as.character(x)), ignore.case = TRUE))

dif_norm <- function(x) {
  z <- tolower(trimws(gsub("\u00a0", " ", as.character(x))))
  dplyr::case_when(
    grepl("temps|tiempo", z)             ~ "Falta de tiempo",
    grepl("formaci", z)                  ~ "Falta de formación",
    grepl("pedag", z)                    ~ "Falta de recursos pedagógicos",
    grepl("econ", z)                     ~ "Falta de recursos económicos",
    grepl("regulaci|institucional", z)   ~ "Falta de regulación institucional",
    grepl("fam[ií]li", z)                ~ "Falta de apoyo de las familias",
    grepl("inter[eèé]s", z)              ~ "Falta de interés personal",
    TRUE                                 ~ NA_character_)
}


zona_norm <- function(x) {
  z <- tolower(trimws(gsub("\u00a0", " ", as.character(x))))
  dplyr::case_when(
    z %in% c("escuela urbana","escola urbana","urbano") ~ "Urbano",
    z %in% c("escuela rural","escola rural","rural")    ~ "Rural",
    TRUE ~ NA_character_)
}


kw_test <- function(lst) {
  lst <- lapply(lst, function(v) v[!is.na(v)])
  N <- sum(lengths(lst)); k <- length(lst)
  ht <- kruskal.test(lst)
  data.frame(H = unname(ht$statistic), gl = unname(ht$parameter),
             p = ht$p.value, eta2 = (unname(ht$statistic) - k + 1) / (N - k),
             N = N)
}


mw_test <- function(a, b) {
  a <- a[!is.na(a)]; b <- b[!is.na(b)]
  n1 <- length(a); n2 <- length(b); N <- n1 + n2
  w  <- suppressWarnings(wilcox.test(a, b, exact = FALSE, correct = FALSE))
  U  <- unname(w$statistic)
  tc <- as.numeric(table(c(a, b)))
  tie <- sum(tc^3 - tc)
  mU <- n1 * n2 / 2
  sU <- sqrt((n1 * n2 / 12) * ((N + 1) - tie / (N * (N - 1))))
  Z  <- (U - mU) / sU
  data.frame(U = U, Z = Z, p = w$p.value, r = abs(Z) / sqrt(N),
             N = N, n1 = n1, n2 = n2)
}


dunn_bh <- function(d, val, grp, levels) {
  d <- d[!is.na(d[[val]]) & !is.na(d[[grp]]), c(val, grp)]
  d$rk <- rank(d[[val]]); N <- nrow(d)
  tc  <- as.numeric(table(d[[val]])); Tt <- sum(tc^3 - tc)
  cmb <- combn(levels, 2, simplify = FALSE)
  res <- purrr::map_dfr(cmb, function(pr) {
    A <- d$rk[d[[grp]] == pr[1]]; B <- d$rk[d[[grp]] == pr[2]]
    if (length(A) < 2 || length(B) < 2) return(NULL)
    se <- sqrt(((N * (N + 1)) / 12 - Tt / (12 * (N - 1))) *
                 (1/length(A) + 1/length(B)))
    Z  <- (mean(A) - mean(B)) / se
    data.frame(g1 = pr[1], g2 = pr[2], Z = Z, p = 2 * pnorm(-abs(Z)))
  })
  res$p_bh <- p.adjust(res$p, method = "BH")
  res
}


homog_letters <- function(levels, medias, dunn_res, alpha = .05) {
  ord  <- levels[order(-medias[levels])]
  difs <- function(x, y) {
    r <- dunn_res[(dunn_res$g1 == x & dunn_res$g2 == y) |
                  (dunn_res$g1 == y & dunn_res$g2 == x), ]
    if (nrow(r) == 0) FALSE else r$p_bh[1] < alpha
  }
  grupos <- list()
  for (l in ord) {
    col <- NULL
    for (i in seq_along(grupos))
      if (all(!vapply(grupos[[i]], function(m) difs(l, m), logical(1)))) { col <- i; break }
    if (is.null(col)) grupos[[length(grupos) + 1]] <- l
    else grupos[[col]] <- c(grupos[[col]], l)
  }
  out <- setNames(rep("", length(levels)), levels)
  for (i in seq_along(grupos)) for (l in grupos[[i]]) out[l] <- paste0(out[l], letters[i])
  out
}


cramer_v <- function(tab) {
  ch <- suppressWarnings(chisq.test(tab))
  n  <- sum(tab); k <- min(dim(tab)) - 1
  data.frame(chi2 = unname(ch$statistic), gl = unname(ch$parameter),
             p = ch$p.value, V = sqrt(unname(ch$statistic) / (n * k)), N = n)
}


fp <- function(p) ifelse(p < .001, "< .001",
                  sub("^0", "", sprintf("%.3f", p)))

3 Carga y fusión de los datos

3.1 España: integración de los dos subconjuntos

cat_raw <- read_excel("Cataluña JG.xlsx")
cat_raw <- cat_raw[trimws(cat_raw[[7]]) == "Sí", ]   

GEN_CA <- c("Femení"="Femenino", "Masculí"="Masculino",
            "Prefereixo No respondre"="Otro / NS-NC", "No binari"="Otro / NS-NC")
FOR_CA <- c("Grau/Llicenciatura/Diplomatura"="Grado/Licenciatura",
            "Màster/Postgrau"="Máster/Postgrado", "Doctorat"="Doctorado")

d_cat <- tibble(
  pais = "España", fuente = "Cataluña",
  edad        = num(cat_raw[[8]]),
  genero      = unname(GEN_CA[as.character(cat_raw[[9]])]),
  formacion   = unname(FOR_CA[as.character(cat_raw[[10]])]),
  experiencia = trimws(gsub("Més", "Más", gsub("anys", "años",
                        as.character(cat_raw[[14]])))),
  zona         = zona_norm(cat_raw[[18]]),
  conoc_propio = num(cat_raw[[19]]),
  conoc_centro = num(cat_raw[[20]]),
  importancia  = num(cat_raw[[21]])
)

for (j in 1:8) {
  d <- DIMS[j]
  d_cat[[paste0("k_", d)]] <- num(cat_raw[[29 + j]])
  d_cat[[paste0("a_", d)]] <- si01(cat_raw[[39 + j]])
  d_cat[[paste0("d_", d)]] <- dif_norm(cat_raw[[49 + j]])
}

d_cat$k_digital <- rowMeans(cbind(num(cat_raw[[38]]), num(cat_raw[[39]])), na.rm = TRUE)
d_cat$a_digital <- pmax(si01(cat_raw[[48]]), si01(cat_raw[[49]]), na.rm = TRUE)
d_cat$d_digital <- dif_norm(cat_raw[[58]])

esp_raw <- read_excel("ESPAÑA JG.xlsx", skip = 1)
esp_raw <- esp_raw[trimws(esp_raw[[7]]) == "Sí", ]

FOR_ES <- c("Grado/Licienciatura/Diplomatura"="Grado/Licenciatura",
            "Máster/Postgrado"="Máster/Postgrado", "Doctorado"="Doctorado")

d_esp <- tibble(
  pais = "España", fuente = "Resto de España",
  edad        = num(esp_raw[[8]]),
  genero      = ifelse(esp_raw[[9]] %in% c("Femenino","Masculino"),
                       as.character(esp_raw[[9]]), "Otro / NS-NC"),
  formacion   = unname(FOR_ES[as.character(esp_raw[[10]])]),
  experiencia = trimws(as.character(esp_raw[[14]])),
  zona         = zona_norm(esp_raw[[19]]),
  conoc_propio = num(esp_raw[[20]]),
  conoc_centro = num(esp_raw[[21]]),
  importancia  = num(esp_raw[[22]])
)
for (j in 1:8) {
  d <- DIMS[j]
  d_esp[[paste0("k_", d)]] <- num(esp_raw[[30 + j]])
  d_esp[[paste0("a_", d)]] <- si01(esp_raw[[40 + j]])
  d_esp[[paste0("d_", d)]] <- dif_norm(esp_raw[[50 + j]])
}
d_esp$k_digital <- rowMeans(cbind(num(esp_raw[[39]]), num(esp_raw[[40]])), na.rm = TRUE)
d_esp$a_digital <- pmax(si01(esp_raw[[49]]), si01(esp_raw[[50]]), na.rm = TRUE)
d_esp$d_digital <- dif_norm(esp_raw[[59]])

ES <- bind_rows(d_cat, d_esp)
cat("Cataluña:", nrow(d_cat), "| Resto de España:", nrow(d_esp),
    "| España total:", nrow(ES), "\n")
## Cataluña: 515 | Resto de España: 466 | España total: 981

3.2 Chile

cl_raw <- read_excel("Chile.xlsx")

FOR_CL <- c("Titulo Profesional / Licenciatura"="Grado/Licenciatura",
            "Magister/Master"="Máster/Postgrado",
            "Postítulo"="Máster/Postgrado",  
            "Doctorado"="Doctorado")

CL <- tibble(
  pais = "Chile", fuente = "Chile",
  edad        = num(cl_raw[[3]]),
  genero      = ifelse(cl_raw[[4]] %in% c("Femenino","Masculino"),
                       as.character(cl_raw[[4]]), "Otro / NS-NC"),
  formacion   = unname(FOR_CL[as.character(cl_raw[[5]])]),
  experiencia = trimws(as.character(cl_raw[[10]])),
  zona         = zona_norm(cl_raw[[16]]),
  conoc_propio = num(cl_raw[[17]]),
  conoc_centro = num(cl_raw[[18]]),
  importancia  = num(cl_raw[[19]])
)
for (j in 1:8) {
  d <- DIMS[j]
  CL[[paste0("k_", d)]] <- num(cl_raw[[27 + j]])
  CL[[paste0("a_", d)]] <- si01(cl_raw[[37 + j]])
  CL[[paste0("d_", d)]] <- dif_norm(cl_raw[[47 + j]])
}
CL$k_digital <- rowMeans(cbind(num(cl_raw[[36]]), num(cl_raw[[37]])), na.rm = TRUE)
CL$a_digital <- pmax(si01(cl_raw[[46]]), si01(cl_raw[[47]]), na.rm = TRUE)
CL$d_digital <- dif_norm(cl_raw[[56]])
cat("Chile:", nrow(CL), "\n")
## Chile: 545

3.3 México

mx_raw <- read_excel("México.xlsx")
mx_raw <- mx_raw[trimws(mx_raw[[3]]) == "Acepto", ]

FOR_MX <- c("Licenciatura"="Grado/Licenciatura",
            "Maestría"="Máster/Postgrado", "Doctorado"="Doctorado")

MX <- tibble(
  pais = "México", fuente = trimws(as.character(mx_raw[[2]])),
  edad        = num(mx_raw[[4]]),
  genero      = ifelse(mx_raw[[5]] %in% c("Femenino","Masculino"),
                       as.character(mx_raw[[5]]), "Otro / NS-NC"),
  formacion   = unname(FOR_MX[as.character(mx_raw[[6]])]),
  
  experiencia = as.character(cut(num(mx_raw[[10]]),
                    breaks = c(-Inf, 5, 10, 15, 20, 25, 30, 35, Inf),
                    labels = TRAMOS, right = TRUE)),
  zona         = zona_norm(mx_raw[[14]]),
  conoc_propio = NA_real_,          
  conoc_centro = num(mx_raw[[20]]),
  importancia  = num(mx_raw[[21]])
)
for (j in seq_along(DIMS)) {
  d <- DIMS[j]
  MX[[paste0("k_", d)]] <- num(mx_raw[[29 + j]])
  
  MX[[paste0("a_", d)]] <- as.integer(num(mx_raw[[38 + j]]) >= 3)
  MX[[paste0("d_", d)]] <- dif_norm(mx_raw[[47 + j]])
}
cat("México:", nrow(MX), "\n")
## México: 10669

3.4 Unión, depuración e índices

df <- bind_rows(ES, MX, CL) %>%
  mutate(
    pais   = factor(pais, levels = PAISES),
    genero = factor(genero, levels = c("Femenino","Masculino","Otro / NS-NC")),
    formacion = factor(formacion,
                 levels = c("Grado/Licenciatura","Máster/Postgrado","Doctorado")),
    experiencia = factor(ifelse(experiencia %in% TRAMOS, experiencia, NA),
                         levels = TRAMOS),
    
    exp4 = fct_collapse(experiencia,
             "0–10 años"  = TRAMOS[1:2], "11–20 años" = TRAMOS[3:4],
             "21–30 años" = TRAMOS[5:6], "Más de 30"  = TRAMOS[7:8]),
    zona = factor(zona, levels = c("Urbano","Rural")),
    
    edad = ifelse(edad < 18 | edad > 90, NA, edad)
  ) %>%
  mutate(
    idx_conoc = rowMeans(dplyr::select(., all_of(paste0("k_", DIMS))), na.rm = TRUE),
    n_temas   = rowSums(dplyr::select(., all_of(paste0("a_", DIMS))), na.rm = TRUE)
  )

df %>% count(pais, name = "n") %>%
  kbl(caption = "N por país tras aplicar el consentimiento informado") %>%
  kable_styling(full_width = FALSE)
N por país tras aplicar el consentimiento informado
pais n
España 981
México 10669
Chile 545
df %>% group_by(pais) %>%
  summarise(Urbano = sum(zona == "Urbano", na.rm = TRUE),
            Rural  = sum(zona == "Rural",  na.rm = TRUE),
            `% perdidos` = round(mean(is.na(zona)) * 100, 1)) %>%
  kbl(caption = "Cobertura de la variable urbano/rural") %>%
  kable_styling(full_width = FALSE)
Cobertura de la variable urbano/rural
pais Urbano Rural % perdidos
España 740 180 6.2
México 6399 4270 0.0
Chile 477 55 2.4

4 Indicadores generales de conocimiento

df %>% filter(pais != "México") %>% group_by(pais) %>%
  summarise(n = sum(!is.na(conoc_propio)),
            M = round(mean(conoc_propio, na.rm = TRUE), 2),
            DT = round(sd(conoc_propio, na.rm = TRUE), 2),
            Md = median(conoc_propio, na.rm = TRUE)) %>%
  kbl(caption = "Conocimiento autopercibido del enfoque EpJG") %>%
  kable_styling(full_width = FALSE)
Conocimiento autopercibido del enfoque EpJG
pais n M DT Md
España 981 2.33 1.13 2
Chile 545 2.45 1.16 2
mw_test(df$conoc_propio[df$pais == "España"],
        df$conoc_propio[df$pais == "Chile"])
kw_test(split(df$conoc_centro, df$pais))
kw_test(split(df$importancia,  df$pais))
kw_test(split(df$idx_conoc, df$pais))
dunn_bh(df, "idx_conoc", "pais", PAISES)

5 Tabla 1. Conocimiento por temática y país

tabla1 <- purrr::map_dfr(DIMS, function(d) {
  v  <- paste0("k_", d)
  st <- df %>% group_by(pais) %>%
        summarise(M = mean(.data[[v]], na.rm = TRUE),
                  DT = sd(.data[[v]], na.rm = TRUE), .groups = "drop")
  k  <- kw_test(split(df[[v]], df$pais))
  dn <- dunn_bh(df, v, "pais", PAISES)
  lt <- homog_letters(PAISES, setNames(st$M, st$pais), dn)
  data.frame(
    Temática = LAB[d],
    España = sprintf("%.2f (%.2f)%s", st$M[st$pais=="España"],
                     st$DT[st$pais=="España"], lt["España"]),
    México = sprintf("%.2f (%.2f)%s", st$M[st$pais=="México"],
                     st$DT[st$pais=="México"], lt["México"]),
    Chile  = sprintf("%.2f (%.2f)%s", st$M[st$pais=="Chile"],
                     st$DT[st$pais=="Chile"],  lt["Chile"]),
    H = round(k$H, 2), p_raw = k$p, eta2 = round(k$eta2, 3))
})

tabla1$p_adj <- fp(p.adjust(tabla1$p_raw, method = "BH"))
tabla1 %>% dplyr::select(-p_raw) %>%
  kbl(caption = "Tabla 1. Conocimiento declarado por temática y país",
      col.names = c("Temática","España M (DT)","México M (DT)","Chile M (DT)",
                    "H(2)","η²","p adj")) %>%
  kable_styling(bootstrap_options = c("striped","hover"), full_width = FALSE) %>%
  footnote(general = "Las medias que no comparten letra difieren significativamente (Dunn, BH, p < .05). La letra 'a' corresponde al valor más elevado.")
Tabla 1. Conocimiento declarado por temática y país
Temática España M (DT) México M (DT) Chile M (DT) H(2) η² p adj
genero Género y feminismos 3.76 (0.85)a 3.36 (1.01)b 3.69 (0.87)a 193.01 0.016 < .001
paz Cultura de paz 3.85 (0.81)b 3.91 (0.96)a 4.00 (0.83)a 13.41 0.001 .001
ddhh Derechos humanos 3.67 (0.89)b 3.62 (0.99)b 3.98 (0.90)a 68.10 0.005 < .001
justeco Justicia económica y social 3.41 (0.96)c 3.47 (1.01)b 3.74 (0.91)a 43.80 0.003 < .001
justamb Justicia ambiental 3.45 (1.00)c 3.58 (1.04)b 3.77 (0.95)a 33.43 0.003 < .001
intercul Interculturalidad 3.71 (0.89)b 3.71 (0.99)b 3.87 (0.90)a 12.02 0.001 .002
bienestar Bienestar emocional 3.97 (0.91)b 3.81 (1.00)c 4.22 (0.81)a 103.34 0.008 < .001
cuidado Cuidado de la relación educativa 3.58 (1.01)c 3.68 (1.01)b 4.18 (0.88)a 146.81 0.012 < .001
digital Equidad digital y tecnología 3.25 (0.94)b 3.45 (1.04)a 3.49 (0.97)a 41.83 0.003 < .001
Note:
Las medias que no comparten letra difieren significativamente (Dunn, BH, p < .05). La letra ‘a’ corresponde al valor más elevado.

6 Tabla 2. Implementación en el aula por temática y país

tabla2 <- purrr::map_dfr(DIMS, function(d) {
  v   <- paste0("a_", d)
  sub <- df[!is.na(df[[v]]), ]
  pr  <- tapply(sub[[v]], sub$pais, mean)
  ch  <- cramer_v(table(sub$pais, sub[[v]]))
 
  cmb <- combn(PAISES, 2, simplify = FALSE)
  pv  <- vapply(cmb, function(pp) {
           s2 <- sub[sub$pais %in% pp, ]
           suppressWarnings(chisq.test(table(droplevels(s2$pais), s2[[v]]))$p.value)
         }, numeric(1))
  dn  <- data.frame(g1 = vapply(cmb, `[`, "", 1), g2 = vapply(cmb, `[`, "", 2),
                    p_bh = p.adjust(pv, method = "BH"))
  lt  <- homog_letters(PAISES, pr, dn)
  data.frame(Temática = LAB[d],
             España = sprintf("%.1f%s", pr["España"]*100, lt["España"]),
             México = sprintf("%.1f%s", pr["México"]*100, lt["México"]),
             Chile  = sprintf("%.1f%s", pr["Chile"]*100,  lt["Chile"]),
             chi2 = round(ch$chi2, 2), p_raw = ch$p, V = round(ch$V, 3))
})
tabla2$p_adj <- fp(p.adjust(tabla2$p_raw, method = "BH"))
tabla2 %>% dplyr::select(-p_raw) %>%
  kbl(caption = "Tabla 2. Implementación en el aula por temática y país",
      col.names = c("Temática","España %","México %","Chile %",
                    "χ²(2)","V","p adj")) %>%
  kable_styling(bootstrap_options = c("striped","hover"), full_width = FALSE)
Tabla 2. Implementación en el aula por temática y país
Temática España % México % Chile % χ²(2) V p adj
genero Género y feminismos 76.9a 73.2b 70.1b 9.34 0.028 .009
paz Cultura de paz 82.6c 93.9a 90.3b 180.76 0.122 < .001
ddhh Derechos humanos 70.4c 87.6a 78.5b 244.25 0.142 < .001
justeco Justicia económica y social 49.8b 79.1a 53.0b 574.22 0.217 < .001
justamb Justicia ambiental 64.3c 87.1a 75.0b 399.04 0.181 < .001
intercul Interculturalidad 80.7b 89.5a 81.5b 95.99 0.089 < .001
bienestar Bienestar emocional 85.6b 91.9a 92.5a 45.92 0.061 < .001
cuidado Cuidado de la relación educativa 65.9b 86.3a 88.6a 298.38 0.156 < .001
digital Equidad digital y tecnología 67.3b 77.3a 57.1c 154.98 0.113 < .001
df %>% group_by(pais) %>%
  summarise(M = round(mean(n_temas), 2), DT = round(sd(n_temas), 2),
            Md = median(n_temas),
            `% las 9` = round(mean(n_temas == 9) * 100, 1)) %>%
  kbl(caption = "Amplitud temática por país") %>% kable_styling(full_width = FALSE)
Amplitud temática por país
pais M DT Md % las 9
España 6.44 2.31 7 23.2
México 7.66 2.35 9 60.6
Chile 6.87 1.86 7 24.6
kw_test(split(df$n_temas, df$pais))
dunn_bh(df, "n_temas", "pais", PAISES)

7 Tabla 3. Dificultades percibidas

largo <- df %>%
  dplyr::select(pais, genero, formacion, exp4, zona, all_of(paste0("d_", DIMS))) %>%
  pivot_longer(starts_with("d_"), names_to = "dim", values_to = "dif") %>%
  filter(!is.na(dif)) %>%
  mutate(dim = LAB[sub("^d_", "", dim)])

DIF7 <- c("Falta de tiempo","Falta de formación","Falta de recursos pedagógicos",
          "Falta de regulación institucional","Falta de apoyo de las familias",
          "Falta de recursos económicos","Falta de interés personal")

tab_dif <- table(factor(largo$pais, levels = PAISES),
                 factor(largo$dif,  levels = DIF7))
cramer_v(tab_dif)
res_adj <- suppressWarnings(chisq.test(tab_dif))$stdres
pct     <- prop.table(tab_dif, 1) * 100

data.frame(
  Dificultad = DIF7,
  España = sprintf("%.1f (%+.1f)", pct["España", DIF7], res_adj["España", DIF7]),
  México = sprintf("%.1f (%+.1f)", pct["México", DIF7], res_adj["México", DIF7]),
  Chile  = sprintf("%.1f (%+.1f)", pct["Chile",  DIF7], res_adj["Chile",  DIF7])
) %>%
  kbl(caption = "Tabla 3. Dificultad principal por país: % (residuo tipificado corregido)") %>%
  kable_styling(bootstrap_options = c("striped","hover"), full_width = FALSE) %>%
  footnote(general = "Residuos superiores a |1.96| indican sobre o infrarrepresentación significativa.")
Tabla 3. Dificultad principal por país: % (residuo tipificado corregido)
Dificultad España México Chile
Falta de tiempo 39.3 (+27.6) 25.9 (-18.0) 22.2 (-7.5)
Falta de formación 19.1 (+8.4) 15.4 (-13.6) 21.4 (+10.6)
Falta de recursos pedagógicos 15.6 (-9.8) 20.2 (+12.5) 15.6 (-7.1)
Falta de regulación institucional 11.2 (+9.7) 7.7 (-23.2) 17.9 (+24.4)
Falta de apoyo de las familias 4.3 (-32.4) 18.1 (+31.9) 12.4 (-8.3)
Falta de recursos económicos 5.4 (-7.5) 7.6 (+7.5) 6.6 (-2.2)
Falta de interés personal 5.0 (-0.5) 5.2 (+2.8) 4.0 (-3.8)
Note:
Residuos superiores a |1.96| indican sobre o infrarrepresentación significativa.
largo %>% count(pais, dim, dif) %>% group_by(pais, dim) %>%
  mutate(pct = n / sum(n) * 100) %>% slice_max(pct, n = 1, with_ties = FALSE) %>%
  ungroup() %>% mutate(etq = sprintf("%s (%.1f%%)", dif, pct)) %>%
  dplyr::select(dim, pais, etq) %>% pivot_wider(names_from = pais, values_from = etq) %>%
  kbl(caption = "Dificultad modal en cada temática") %>% kable_styling(full_width = FALSE)
Dificultad modal en cada temática
dim España México Chile
Bienestar emocional Falta de tiempo (44.4%) Falta de tiempo (26.6%) Falta de tiempo (22.4%)
Cuidado de la relación educativa Falta de tiempo (35.4%) Falta de formación (23.4%) Falta de tiempo (27.3%)
Cultura de paz Falta de tiempo (48.5%) Falta de apoyo de las familias (29.3%) Falta de tiempo (23.7%)
Derechos humanos Falta de tiempo (40.4%) Falta de tiempo (26.9%) Falta de tiempo (23.7%)
Equidad digital y tecnología Falta de formación (28.5%) Falta de tiempo (22.8%) Falta de formación (36.0%)
Género y feminismos Falta de tiempo (42.3%) Falta de tiempo (24.9%) Falta de formación (21.8%)
Interculturalidad Falta de tiempo (43.4%) Falta de tiempo (28.8%) Falta de tiempo (22.9%)
Justicia ambiental Falta de tiempo (39.7%) Falta de tiempo (27.6%) Falta de tiempo (24.8%)
Justicia económica y social Falta de tiempo (31.8%) Falta de tiempo (25.3%) Falta de formación (28.4%)

8 Tabla 4. Diferencias según variables sociodemográficas

cruces <- purrr::map_dfr(c("idx_conoc","n_temas"), function(target) {
  purrr::map_dfr(PAISES, function(p) {
    s <- df %>% filter(pais == p)
    
    g <- s %>% filter(genero %in% c("Femenino","Masculino"))
    rg <- mw_test(g[[target]][g$genero == "Femenino"],
                  g[[target]][g$genero == "Masculino"])
    # Zona: Urbano/Rural
    z <- s %>% filter(!is.na(zona))
    rz <- mw_test(z[[target]][z$zona == "Urbano"], z[[target]][z$zona == "Rural"])
   
    f  <- s %>% filter(!is.na(formacion)) %>% mutate(formacion = droplevels(formacion))
    kf <- kw_test(split(f[[target]], f$formacion))
    x  <- s %>% filter(!is.na(exp4)) %>% mutate(exp4 = droplevels(exp4))
    kx <- kw_test(split(x[[target]], x$exp4))
    data.frame(
      Indicador = ifelse(target == "idx_conoc", "Conocimiento", "Implementación"),
      País = p,
      Variable = c("Género","Formación","Experiencia","Zona"),
      Estad = c(rg$Z, kf$H, kx$H, rz$Z),
      p_raw = c(rg$p, kf$p, kx$p, rz$p),
      Efecto = c(rg$r, kf$eta2, kx$eta2, rz$r),
      Índice = c("r","η²","η²","r"))
  })
})
cruces$p_adj <- p.adjust(cruces$p_raw, method = "BH")
cruces %>%
  mutate(Estad = round(Estad, 2), Efecto = round(Efecto, 3),
         Sig = ifelse(p_adj < .05, "Sí", "No"), p_adj = fp(p_adj)) %>%
  dplyr::select(-p_raw) %>%
  kbl(caption = "Tabla 4. Contrastes sociodemográficos por país (BH sobre 24 pruebas)") %>%
  kable_styling(bootstrap_options = c("striped","hover"), full_width = FALSE) %>%
  collapse_rows(columns = 1:2, valign = "middle")
Tabla 4. Contrastes sociodemográficos por país (BH sobre 24 pruebas)
Indicador País Variable Estad Efecto Índice p_adj Sig
Conocimiento España Género -0.48 0.016 r .720 No
Formación 5.22 0.003 η² .167 No
Experiencia 20.59 0.018 η² < .001
Zona 0.34 0.011 r .803 No
México Género -7.80 0.076 r < .001
Formación 11.72 0.001 η² .010
Experiencia 65.28 0.006 η² < .001
Zona -1.34 0.013 r .268 No
Chile Género 1.37 0.059 r .268 No
Formación 3.93 0.004 η² .268 No
Experiencia 9.49 0.012 η² .062 No
Zona -0.15 0.007 r .918 No
Implementación España Género 1.77 0.057 r .167 No
Formación 9.74 0.008 η² .023
Experiencia 24.27 0.022 η² < .001
Zona -0.83 0.027 r .491 No
México Género -6.73 0.065 r < .001
Formación 3.72 0.000 η² .268 No
Experiencia 53.02 0.005 η² < .001
Zona 0.09 0.001 r .930 No
Chile Género -1.00 0.043 r .400 No
Formación 3.15 0.002 η² .292 No
Experiencia 4.92 0.004 η² .268 No
Zona -1.02 0.044 r .400 No
df %>% filter(!is.na(exp4)) %>% group_by(pais, exp4) %>%
  summarise(Conocimiento = round(mean(idx_conoc, na.rm = TRUE), 2),
            Implementación = round(mean(n_temas, na.rm = TRUE), 2), .groups = "drop") %>%
  pivot_wider(names_from = exp4, values_from = c(Conocimiento, Implementación)) %>%
  kbl(caption = "Medias por tramo de experiencia docente") %>%
  kable_styling(full_width = FALSE, font_size = 11)
Medias por tramo de experiencia docente
pais Conocimiento_0–10 años Conocimiento_11–20 años Conocimiento_21–30 años Conocimiento_Más de 30 Implementación_0–10 años Implementación_11–20 años Implementación_21–30 años Implementación_Más de 30
España 3.52 3.67 3.71 3.82 6.08 6.72 6.57 7.04
México 3.59 3.59 3.64 3.80 7.60 7.63 7.66 7.93
Chile 3.82 3.83 3.97 4.07 6.75 6.93 7.04 6.79
purrr::map_dfr(PAISES, function(p) {
  s <- largo %>% filter(pais == p, !is.na(zona))
  cbind(País = p, cramer_v(table(s$zona, s$dif)))
}) %>% kbl(caption = "Asociación entre zona y dificultad señalada") %>%
  kable_styling(full_width = FALSE)
Asociación entre zona y dificultad señalada
País chi2 gl p V N
España 53.77137 6 0.0e+00 0.0805861 8280
México 279.14413 6 0.0e+00 0.0539177 96021
Chile 33.67619 6 7.8e-06 0.0838657 4788

9 Tabla 5. Conocimiento según implementación

tabla5 <- purrr::map_dfr(DIMS, function(d) {
  kv <- paste0("k_", d); av <- paste0("a_", d)
  purrr::map_dfr(PAISES, function(p) {
    s  <- df %>% filter(pais == p)
    r  <- mw_test(s[[kv]][s[[av]] == 1], s[[kv]][s[[av]] == 0])
    data.frame(Temática = LAB[d], País = p,
               M_si = mean(s[[kv]][s[[av]] == 1], na.rm = TRUE),
               M_no = mean(s[[kv]][s[[av]] == 0], na.rm = TRUE),
               Z = r$Z, p_raw = r$p, r = r$r)
  })
})
tabla5 <- tabla5 %>% mutate(dM = M_si - M_no,
                            p_adj = p.adjust(p_raw, method = "BH"))
tabla5 %>%
  mutate(celda = sprintf("%+.2f (r = %.3f)", dM, r)) %>%
  dplyr::select(Temática, País, celda) %>%
  pivot_wider(names_from = País, values_from = celda) %>%
  kbl(caption = "Tabla 5. Diferencia de conocimiento entre quienes trabajan la temática y quienes no") %>%
  kable_styling(bootstrap_options = c("striped","hover"), full_width = FALSE) %>%
  footnote(general = "Todos los contrastes resultaron significativos (p adj < .001, BH sobre 27 comparaciones).")
Tabla 5. Diferencia de conocimiento entre quienes trabajan la temática y quienes no
Temática España México Chile
Género y feminismos +0.52 (r = 0.225) +1.08 (r = 0.466) +0.61 (r = 0.306)
Cultura de paz +0.56 (r = 0.248) +1.60 (r = 0.334) +0.82 (r = 0.262)
Derechos humanos +0.57 (r = 0.290) +1.32 (r = 0.404) +0.62 (r = 0.277)
Justicia económica y social +0.69 (r = 0.355) +1.22 (r = 0.472) +0.58 (r = 0.314)
Justicia ambiental +0.81 (r = 0.383) +1.38 (r = 0.416) +0.77 (r = 0.338)
Interculturalidad +0.71 (r = 0.293) +1.43 (r = 0.399) +0.66 (r = 0.274)
Bienestar emocional +0.88 (r = 0.295) +1.55 (r = 0.366) +0.55 (r = 0.175)
Cuidado de la relación educativa +1.05 (r = 0.488) +1.38 (r = 0.431) +1.02 (r = 0.318)
Equidad digital y tecnología +0.85 (r = 0.414) +1.26 (r = 0.486) +0.75 (r = 0.378)
Note:
Todos los contrastes resultaron significativos (p adj < .001, BH sobre 27 comparaciones).
cat("Rango de p ajustados:", fp(max(tabla5$p_adj)), "\n")
## Rango de p ajustados: < .001

10 Figura 1. Brecha entre conocimiento e implementación

brecha <- purrr::map_dfr(PAISES, function(p) {
  s <- df %>% filter(pais == p)
  purrr::map_dfr(DIMS, function(d) {
    data.frame(pais = p, dim = LAB[d],
               conoc = mean(s[[paste0("k_", d)]], na.rm = TRUE) / 5 * 100,
               aula  = mean(s[[paste0("a_", d)]], na.rm = TRUE) * 100)
  })
}) %>% mutate(gap = aula - conoc,
              signo = ifelse(gap >= 0, "Implementación > conocimiento",
                                       "Conocimiento > implementación"))


orden <- brecha %>% group_by(dim) %>% summarise(m = mean(gap)) %>% arrange(m) %>% pull(dim)
brecha <- brecha %>% mutate(dim = factor(dim, levels = orden),
                            pais = factor(pais, levels = PAISES))

ggplot(brecha) +
  geom_segment(aes(x = conoc, xend = aula, y = dim, yend = dim, colour = signo),
               linewidth = 1.5, lineend = "round") +
  geom_point(aes(x = conoc, y = dim), size = 2.9, colour = "#4E93D9",
             fill = col_azul_suave, shape = 21, stroke = .7) +
  geom_point(aes(x = aula, y = dim), size = 2.9, colour = "white",
             fill = col_azul, shape = 21, stroke = .7) +
  geom_text(aes(x = pmax(conoc, aula) + 2, y = dim,
                label = sprintf("%+.1f", gap), colour = signo),
            hjust = 0, size = 2.7, fontface = "bold", show.legend = FALSE) +
  facet_wrap(~ pais, nrow = 1) +
  scale_colour_manual(values = c("Implementación > conocimiento" = "#4E93D9",
                                 "Conocimiento > implementación" = col_rojo),
                      name = NULL) +
  scale_x_continuous(limits = c(35, 108), breaks = c(40, 60, 80, 100)) +
  labs(x = "Puntuación normalizada 0–100", y = NULL,
       title = "Figura 1. Brecha entre el conocimiento declarado y la implementación en el aula") +
  theme_minimal(base_size = 10) +
  theme(legend.position = "bottom",
        panel.grid.major.y = element_blank(),
        panel.grid.minor = element_blank(),
        panel.grid.major.x = element_line(colour = col_no_fuerte),
        strip.text = element_text(face = "bold", colour = col_azul, size = 11),
        plot.title = element_text(face = "bold", size = 11))

ggsave("Figura1_brecha.tiff", width = 11, height = 5.2, dpi = 600, compression = "lzw")
ggsave("Figura1_brecha.pdf",  width = 11, height = 5.2)

11 Comprobación de supuestos

purrr::map_dfr(PAISES, function(p) {
  x  <- na.omit(df$idx_conoc[df$pais == p])
  xs <- if (length(x) > 5000) sample(x, 5000) else x
  s  <- shapiro.test(xs)
  data.frame(País = p, n = length(xs), W = round(unname(s$statistic), 3),
             p = fp(s$p.value),
             Decisión = ifelse(s$p.value < .05, "No normal", "Normal"))
}) %>% kbl(caption = "Prueba de normalidad de Shapiro-Wilk") %>%
  kable_styling(full_width = FALSE)
Prueba de normalidad de Shapiro-Wilk
País n W p Decisión
España 981 0.990 < .001 No normal
México 5000 0.969 < .001 No normal
Chile 545 0.976 < .001 No normal

El alejamiento de la normalidad en los tres subgrupos justifica el uso de pruebas no paramétricas en todos los contrastes reportados.