library(readxl)
library(dplyr)
library(tidyr)
library(ggplot2)
library(forcats)
library(stringr)
library(scales)
library(knitr)
library(kableExtra)
library(patchwork)
azul1 <- "#084594"; azul2 <- "#2171B5"; azul3 <- "#4292C6"
azul4 <- "#6BAED6"; azul5 <- "#9ECAE1"; azul6 <- "#C6DBEF"; azul7 <- "#DEEBF7"
escala_blues <- c(azul1, azul2, azul3, azul4, azul5, azul6, azul7)
col_ctx <- c("Cataluña" = azul2, "España (resto)" = azul5, "Total" = azul1)

tema_epjg <- theme_minimal(base_size = 12) +
  theme(
    plot.title       = element_text(face = "bold", colour = azul1, size = 14),
    plot.subtitle    = element_text(colour = azul2, size = 11),
    axis.title       = element_text(colour = azul1),
    axis.text        = element_text(colour = "#333333"),
    legend.position  = "bottom",
    legend.title     = element_text(colour = azul1, face = "bold"),
    panel.grid.major = element_line(colour = "#e8f0f7"),
    panel.grid.minor = element_blank(),
    strip.text       = element_text(face = "bold", colour = azul1),
    plot.caption     = element_text(colour = "#888888", size = 9)
  )
# ── Lectura ───────────────────────────────────────────────────────
# Cataluña: las etiquetas de preguntas están EN los nombres de columna.
# España: la primera fila de datos contiene etiquetas de preguntas → slice(-1)
raw_cat <- read_excel("Cataluña Professió Docent i Justícia Global (1-538).xlsx")
raw_esp <- read_excel("ESPAÑA Profesión Docente y Justicia Global (2)(1-483).xlsx") %>%
  slice(-1)   # elimina la fila de etiquetas de preguntas
# ── Limpieza tipología ────────────────────────────────────────────
limpiar_tipologia <- function(x) {
  x <- str_trim(x)
  case_when(
    str_detect(x, regex("rural|poble",          ignore_case = TRUE)) ~ "Rural",
    str_detect(x, regex("urban|ciudad|ciutat",  ignore_case = TRUE)) ~ "Urbana",
    str_detect(x, regex("Institut|instituto|IES|IFE", ignore_case = TRUE)) ~ "Instituto/IES",
    str_detect(x, regex("complexit|complexa|complejidad|alta", ignore_case = TRUE)) ~ "Alta complejidad",
    TRUE ~ x
  )
}

limpiar_ambito <- function(x) {
  x <- str_trim(x)
  case_when(
    str_detect(x, regex("infantil",             ignore_case = TRUE)) ~ "Ed. Infantil",
    str_detect(x, regex("primàr|primari|primaria", ignore_case = TRUE)) ~ "Ed. Primaria",
    str_detect(x, regex("secundàr|secundari|secundaria", ignore_case = TRUE)) ~ "Ed. Secundaria",
    str_detect(x, regex("batxiller|bachiller",  ignore_case = TRUE)) ~ "Bachillerato",
    str_detect(x, regex("formació professional|formación profesional", ignore_case = TRUE)) ~ "FP",
    str_detect(x, regex("adults|adultos",       ignore_case = TRUE)) ~ "Ed. Adultos",
    str_detect(x, regex("especial",             ignore_case = TRUE)) ~ "Ed. Especial",
    TRUE ~ x
  )
}

# ── Armonización dificultades (CAT → ES) ─────────────────────────
arm_dificultad <- function(x) {
  x <- str_trim(str_replace_all(x, "\u00a0", ""))  # elimina non-breaking spaces
  case_when(
    str_detect(x, regex("recursos econòmics|recursos económicos", ignore_case = TRUE)) ~ "Falta de recursos económicos",
    str_detect(x, regex("recursos pedagògics|recursos pedagógicos", ignore_case = TRUE)) ~ "Falta de recursos pedagógicos",
    str_detect(x, regex("recolzament|apoyo.*famílies|apoyo.*familias", ignore_case = TRUE)) ~ "Falta de apoyo de las familias",
    str_detect(x, regex("temps|tiempo", ignore_case = TRUE)) ~ "Falta de tiempo",
    str_detect(x, regex("interès|interés", ignore_case = TRUE)) ~ "Falta de interés personal",
    str_detect(x, regex("regulació|regulación", ignore_case = TRUE)) ~ "Falta de regulación institucional",
    str_detect(x, regex("formació|formación", ignore_case = TRUE)) ~ "Falta de formación",
    TRUE ~ x
  )
}
# ── Etiquetas de las temáticas ────────────────────────────────────
etiquetas_tema <- c(
  "Género y feminismos", "Cultura de paz", "Derechos humanos",
  "Justicia econ. y social", "Justicia ambiental", "Interculturalidad",
  "Bienestar emocional", "Relación educativa", "Equidad digital",
  "Crít. tecnología"
)

# ═══════════════════════════════════════════════════════════════════
# CATALUÑA  (R 1-indexed; etiquetas ya en los nombres de columna)
# ═══════════════════════════════════════════════════════════════════
# Bloque         Cols (R)
# Perfil         1,8-10,14-15,17-18
# EpJG global    19-21
# Movimientos    23-29
# Conoc. temát.  30-39
# Trab. aula     40-49
# Dificultades   50-59
# Interés form.  60-69
# Modalidad/Fmt  72-73
cat_df <- raw_cat %>%
  select(
    id = 1, edad = 8, genero = 9, formacion = 10,
    experiencia = 14, ambito = 15, regimen = 17, tipologia = 18,
    # EpJG percepción global
    con_propio = 19, con_centro = 20, importancia = 21,
    # Apoyo movimientos sociales
    sup_ecologismo = 23, sup_pacifismo = 24, sup_feminismo = 25,
    sup_der_hum = 26, sup_lgtbiq = 27, sup_antirac = 28, sup_anticap = 29,
    # Conocimiento sobre las temáticas (escala 1-5)
    conoc_genero = 30, conoc_paz = 31, conoc_derechos = 32,
    conoc_just_eco = 33, conoc_just_amb = 34, conoc_intercult = 35,
    conoc_bienestar = 36, conoc_rel_educ = 37, conoc_digital = 38,
    conoc_tecnologia = 39,
    # Trabaja en el aula (SÍ/NO)
    trab_genero = 40, trab_paz = 41, trab_derechos = 42,
    trab_just_eco = 43, trab_just_amb = 44, trab_intercult = 45,
    trab_bienestar = 46, trab_rel_educ = 47, trab_digital = 48,
    trab_tecnologia = 49,
    # Principal dificultad (categórico)
    dif_genero = 50, dif_paz = 51, dif_derechos = 52,
    dif_just_eco = 53, dif_just_amb = 54, dif_intercult = 55,
    dif_bienestar = 56, dif_rel_educ = 57, dif_digital = 58,
    dif_tecnologia = 59,
    # Interés en formarse (escala 1-5)
    int_genero = 60, int_paz = 61, int_derechos = 62,
    int_just_eco = 63, int_just_amb = 64, int_intercult = 65,
    int_bienestar = 66, int_rel_educ = 67, int_digital = 68,
    int_tecnologia = 69,
    # Preferencias formación
    modalidad = 72, formato_pref = 73
  ) %>%
  mutate(
    contexto  = "Cataluña",
    id        = as.character(id),
    genero    = case_when(
      genero == "Femení"  ~ "Femenino",
      genero == "Masculí" ~ "Masculino",
      TRUE                ~ "No informa"
    ),
    formacion = case_when(
      str_detect(formacion, "Doctorat")                       ~ "Doctorado",
      str_detect(formacion, "Màster|Postgrau")                ~ "Máster/Postgrado",
      str_detect(formacion, "Grau|Llicenciatura|Diplomatura") ~ "Grado/Licenciatura",
      TRUE                                                    ~ "No informa"
    ),
    regimen   = str_trim(regimen),
    regimen   = case_when(
      str_detect(regimen, "úblic")  ~ "Público",
      str_detect(regimen, "oncert") ~ "Concertado",
      TRUE                         ~ regimen
    ),
    tipologia   = limpiar_tipologia(tipologia),
    ambito      = limpiar_ambito(ambito),
    edad        = as.numeric(edad),
    edad        = ifelse(edad > 100, NA_real_, edad),
    experiencia = str_replace_all(str_trim(as.character(experiencia)),
                                  c("anys" = "años", "Més de" = "Más de")),
    across(c(con_propio, con_centro, importancia,
             sup_ecologismo:sup_anticap,
             conoc_genero:conoc_tecnologia,
             int_genero:int_tecnologia), as.numeric),
    across(dif_genero:dif_tecnologia, arm_dificultad)
  )

# ═══════════════════════════════════════════════════════════════════
# ESPAÑA (REST)  (R 1-indexed; tras slice(-1) la fila de etiquetas ya no existe)
# ═══════════════════════════════════════════════════════════════════
# Bloque         Cols (R)
# Perfil         1,8-10,14-15,17-19
# EpJG global    20-22
# Movimientos    24-30
# Conoc. temát.  31-40
# Trab. aula     41-50
# Dificultades   51-60
# Interés form.  61-70
# Modalidad/Fmt  73-74
esp_df <- raw_esp %>%
  select(
    id = 1, edad = 8, genero = 9, formacion = 10,
    experiencia = 14, ambito = 15, ccaa = 17, regimen = 18, tipologia = 19,
    # EpJG percepción global
    con_propio = 20, con_centro = 21, importancia = 22,
    # Apoyo movimientos sociales
    sup_ecologismo = 24, sup_pacifismo = 25, sup_feminismo = 26,
    sup_der_hum = 27, sup_lgtbiq = 28, sup_antirac = 29, sup_anticap = 30,
    # Conocimiento sobre las temáticas
    conoc_genero = 31, conoc_paz = 32, conoc_derechos = 33,
    conoc_just_eco = 34, conoc_just_amb = 35, conoc_intercult = 36,
    conoc_bienestar = 37, conoc_rel_educ = 38, conoc_digital = 39,
    conoc_tecnologia = 40,
    # Trabaja en el aula
    trab_genero = 41, trab_paz = 42, trab_derechos = 43,
    trab_just_eco = 44, trab_just_amb = 45, trab_intercult = 46,
    trab_bienestar = 47, trab_rel_educ = 48, trab_digital = 49,
    trab_tecnologia = 50,
    # Principal dificultad
    dif_genero = 51, dif_paz = 52, dif_derechos = 53,
    dif_just_eco = 54, dif_just_amb = 55, dif_intercult = 56,
    dif_bienestar = 57, dif_rel_educ = 58, dif_digital = 59,
    dif_tecnologia = 60,
    # Interés en formarse
    int_genero = 61, int_paz = 62, int_derechos = 63,
    int_just_eco = 64, int_just_amb = 65, int_intercult = 66,
    int_bienestar = 67, int_rel_educ = 68, int_digital = 69,
    int_tecnologia = 70,
    # Preferencias formación
    modalidad = 73, formato_pref = 74
  ) %>%
  mutate(
    contexto  = "España (resto)",
    id        = as.character(id),
    genero    = case_when(
      genero == "Femenino"  ~ "Femenino",
      genero == "Masculino" ~ "Masculino",
      TRUE                  ~ "No informa"
    ),
    formacion = case_when(
      str_detect(formacion, "Doctorado")                      ~ "Doctorado",
      str_detect(formacion, "Máster|Postgrado")               ~ "Máster/Postgrado",
      str_detect(formacion, "Grado|Licenciatura|Diplomatura") ~ "Grado/Licenciatura",
      TRUE                                                    ~ "No informa"
    ),
    regimen   = str_trim(regimen),
    regimen   = case_when(
      str_detect(regimen, "úblico")    ~ "Público",
      str_detect(regimen, "oncertado") ~ "Concertado",
      str_detect(regimen, "rivado")    ~ "Privado",
      TRUE                            ~ regimen
    ),
    tipologia = limpiar_tipologia(tipologia),
    ambito    = limpiar_ambito(ambito),
    edad      = as.numeric(edad),
    across(c(con_propio, con_centro, importancia,
             sup_ecologismo:sup_anticap,
             conoc_genero:conoc_tecnologia,
             int_genero:int_tecnologia), as.numeric),
    across(dif_genero:dif_tecnologia, arm_dificultad)
  )

# ── Dataset combinado ─────────────────────────────────────────────
cols_comunes <- intersect(names(cat_df), names(esp_df))
df <- bind_rows(
  cat_df %>% select(all_of(cols_comunes)),
  esp_df %>% select(all_of(cols_comunes))
) %>%
  mutate(
    contexto    = factor(contexto, levels = c("Cataluña", "España (resto)")),
    experiencia = factor(
      str_replace_all(str_trim(experiencia),
                      c("anys" = "años", "Més de" = "Más de")),
      levels = 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")
    )
  )

# ── Dataset con Total ─────────────────────────────────────────────
df_plot <- bind_rows(df, df %>% mutate(contexto = "Total")) %>%
  mutate(contexto = factor(contexto,
                           levels = c("Cataluña", "España (resto)", "Total")))

1 Descripción de la muestra

tabla_n <- df_plot %>%
  count(contexto, name = "n") %>%
  mutate(Porcentaje = case_when(
    contexto == "Total" ~ "100%",
    TRUE ~ percent(n / sum(n[contexto != "Total"]), accuracy = .1)
  ))

kable(tabla_n, col.names = c("Contexto", "n", "%"),
      caption = "Tamaño de la muestra por contexto") %>%
  kable_styling(bootstrap_options = c("striped","hover"), full_width = FALSE) %>%
  row_spec(which(tabla_n$contexto == "Total"), bold = TRUE, background = azul7)
Tamaño de la muestra por contexto
Contexto n %
Cataluña 538 52.7%
España (resto) 482 47.3%
Total 1020 100%

2 Perfil sociodemográfico

2.1 Edad

edad_stats <- df_plot %>%
  filter(!is.na(edad)) %>%
  group_by(contexto) %>%
  summarise(n = n(), Media = round(mean(edad),1), Mediana = round(median(edad),1),
            DT = round(sd(edad),1), Mínimo = min(edad), Máximo = max(edad))

kable(edad_stats, caption = "Estadísticos descriptivos de la edad") %>%
  kable_styling(bootstrap_options = c("striped","hover"), full_width = FALSE) %>%
  column_spec(1, bold = TRUE, color = azul1) %>%
  row_spec(which(edad_stats$contexto == "Total"), bold = TRUE, background = azul7)
Estadísticos descriptivos de la edad
contexto n Media Mediana DT Mínimo Máximo
Cataluña 514 45.0 45 9.6 21 63
España (resto) 465 45.8 47 10.1 23 69
Total 979 45.4 46 9.9 21 69
ggplot(df_plot %>% filter(!is.na(edad)), aes(x = edad, fill = contexto)) +
  geom_histogram(binwidth = 3, colour = "white", alpha = 0.85) +
  facet_wrap(~contexto, ncol = 3) +
  scale_fill_manual(values = col_ctx, guide = "none") +
  scale_x_continuous(breaks = seq(20, 70, 10)) +
  geom_vline(data = edad_stats, aes(xintercept = Media, colour = contexto),
             linetype = "dashed", linewidth = 0.8) +
  scale_colour_manual(values = col_ctx, name = "Media") +
  labs(title = "Distribución de la edad del profesorado",
       x = "Edad (años)", y = "Frecuencia") + tema_epjg

2.2 Género

tab_gen <- df_plot %>%
  filter(!is.na(genero), genero != "No informa") %>%
  count(contexto, genero) %>%
  group_by(contexto) %>% mutate(prop = n / sum(n))

ggplot(tab_gen, aes(x = fct_reorder(genero, n, .desc = TRUE), y = prop, fill = contexto)) +
  geom_col(position = position_dodge(0.8), width = 0.7) +
  geom_text(aes(label = percent(prop, accuracy = 1)),
            position = position_dodge(0.8), vjust = -0.4, size = 3.2, colour = azul1) +
  scale_fill_manual(values = col_ctx, name = "Contexto") +
  scale_y_continuous(labels = percent, limits = c(0, 1)) +
  labs(title = "Distribución por género", x = NULL, y = "Proporción") + tema_epjg

2.3 Formación

tab_form <- df_plot %>%
  filter(!is.na(formacion), formacion != "No informa") %>%
  count(contexto, formacion) %>%
  group_by(contexto) %>%
  mutate(prop = n / sum(n),
         formacion = factor(formacion,
           levels = c("Grado/Licenciatura", "Máster/Postgrado", "Doctorado")))

ggplot(tab_form, aes(x = formacion, y = prop, fill = contexto)) +
  geom_col(position = position_dodge(0.8), width = 0.7) +
  geom_text(aes(label = percent(prop, accuracy = 1)),
            position = position_dodge(0.8), vjust = -0.4, size = 3.2, colour = azul1) +
  scale_fill_manual(values = col_ctx, name = "Contexto") +
  scale_y_continuous(labels = percent, limits = c(0, 0.85)) +
  labs(title = "Nivel de formación más elevado", x = NULL, y = "Proporción") + tema_epjg

2.4 Experiencia docente

tab_exp <- df_plot %>%
  filter(!is.na(experiencia)) %>%
  count(contexto, experiencia) %>%
  group_by(contexto) %>% mutate(prop = n / sum(n))

ggplot(tab_exp, aes(x = experiencia, y = prop, fill = contexto)) +
  geom_col(position = position_dodge(0.8), width = 0.75) +
  geom_text(aes(label = percent(prop, accuracy = 1)),
            position = position_dodge(0.8), vjust = -0.4, size = 2.5, colour = azul1) +
  scale_fill_manual(values = col_ctx, name = "Contexto") +
  scale_y_continuous(labels = percent, limits = c(0, 0.40)) +
  labs(title = "Años de experiencia docente", x = NULL, y = "Proporción") + tema_epjg +
  theme(axis.text.x = element_text(angle = 35, hjust = 1))

2.5 Ámbito profesional

ambitos_ok <- c("Ed. Infantil","Ed. Primaria","Ed. Secundaria",
                 "Bachillerato","FP","Ed. Adultos","Ed. Especial")

tab_ambito <- df_plot %>%
  filter(ambito %in% ambitos_ok) %>%
  count(contexto, ambito) %>%
  group_by(contexto) %>%
  mutate(prop = n / sum(n), ambito = factor(ambito, levels = ambitos_ok))

ggplot(tab_ambito, aes(x = ambito, y = prop, fill = contexto)) +
  geom_col(position = position_dodge(0.8), width = 0.75) +
  geom_text(aes(label = percent(prop, accuracy = 1)),
            position = position_dodge(0.8), vjust = -0.4, size = 2.8, colour = azul1) +
  scale_fill_manual(values = col_ctx, name = "Contexto") +
  scale_y_continuous(labels = percent, limits = c(0, 0.60)) +
  labs(title = "Ámbito profesional actual", x = NULL, y = "Proporción") + tema_epjg +
  theme(axis.text.x = element_text(angle = 30, hjust = 1))

2.6 Régimen y tipología

tab_reg <- df_plot %>% filter(!is.na(regimen)) %>%
  count(contexto, regimen) %>% group_by(contexto) %>%
  mutate(prop = n/sum(n), regimen = factor(regimen, c("Público","Concertado","Privado")))

p1 <- ggplot(tab_reg, aes(x = regimen, y = prop, fill = contexto)) +
  geom_col(position = position_dodge(0.8), width = 0.7) +
  geom_text(aes(label = percent(prop,1)), position = position_dodge(0.8),
            vjust=-0.4, size=3, colour=azul1) +
  scale_fill_manual(values = col_ctx, name = "Contexto") +
  scale_y_continuous(labels = percent, limits = c(0,1.05)) +
  labs(title = "Régimen del centro", x = NULL, y = "Proporción") + tema_epjg

tip_ok <- c("Urbana","Rural","Instituto/IES","Alta complejidad")
tab_tip <- df_plot %>% filter(tipologia %in% tip_ok) %>%
  count(contexto, tipologia) %>% group_by(contexto) %>%
  mutate(prop = n/sum(n), tipologia = factor(tipologia, tip_ok))

p2 <- ggplot(tab_tip, aes(x = tipologia, y = prop, fill = contexto)) +
  geom_col(position = position_dodge(0.8), width = 0.7) +
  geom_text(aes(label = percent(prop,1)), position = position_dodge(0.8),
            vjust=-0.4, size=3, colour=azul1) +
  scale_fill_manual(values = col_ctx, name = "Contexto") +
  scale_y_continuous(labels = percent, limits = c(0,1.05)) +
  labs(title = "Tipología del centro", x = NULL, y = "Proporción") + tema_epjg

p1 / p2 + plot_layout(guides = "collect") & theme(legend.position = "bottom")

2.7 Comunidades autónomas (España)

tab_ccaa <- tibble(ccaa = raw_esp[[17]]) %>% filter(!is.na(ccaa)) %>%
  count(ccaa, sort = TRUE) %>%
  mutate(prop = n/sum(n), ccaa = fct_reorder(ccaa, n))

ggplot(tab_ccaa, aes(x = ccaa, y = prop, fill = prop)) +
  geom_col() +
  geom_text(aes(label = str_c(n," (",percent(prop,1),")")),
            hjust=-0.05, size=3, colour=azul1) +
  scale_fill_gradient(low=azul6, high=azul1, guide="none") +
  scale_y_continuous(labels=percent, limits=c(0,.23)) +
  coord_flip() +
  labs(title="Distribución por comunidad autónoma (España, resto)",
       x=NULL, y="Proporción") + tema_epjg


3 Conocimiento y percepción de la EpJG

lik5 <- c("1 - Nada","2","3","4","5 - Mucho")

3.1 Conocimiento propio

tab_cp <- df_plot %>% filter(!is.na(con_propio)) %>%
  mutate(con_propio = factor(con_propio, 1:5, lik5)) %>%
  count(contexto, con_propio) %>% group_by(contexto) %>% mutate(prop=n/sum(n))

ggplot(tab_cp, aes(x=con_propio, y=prop, fill=con_propio)) +
  geom_col(show.legend=FALSE) +
  geom_text(aes(label=percent(prop,1)), vjust=-0.4, size=3, colour=azul1) +
  scale_fill_manual(values=escala_blues[1:5]) +
  scale_y_continuous(labels=percent, limits=c(0,.55)) +
  facet_wrap(~contexto, ncol=3) +
  labs(title="¿Cuál es tu grado de conocimiento de la EpJG?",
       x=NULL, y="Proporción") + tema_epjg +
  theme(axis.text.x=element_text(size=8))

df_plot %>% filter(!is.na(con_propio)) %>%
  group_by(contexto) %>%
  summarise(n=n(), Media=round(mean(con_propio,na.rm=TRUE),2),
            Mediana=median(con_propio,na.rm=TRUE),
            DT=round(sd(con_propio,na.rm=TRUE),2)) %>%
  kable(caption="Estadísticos: conocimiento propio de la EpJG") %>%
  kable_styling(bootstrap_options=c("striped","hover"), full_width=FALSE) %>%
  row_spec(3, bold=TRUE, background=azul7)
Estadísticos: conocimiento propio de la EpJG
contexto n Media Mediana DT
Cataluña 515 2.35 2 1.12
España (resto) 466 2.32 2 1.15
Total 981 2.34 2 1.13

3.2 Conocimiento percibido del centro

tab_cc <- df_plot %>% filter(!is.na(con_centro)) %>%
  mutate(con_centro=factor(con_centro,1:5,lik5)) %>%
  count(contexto, con_centro) %>% group_by(contexto) %>% mutate(prop=n/sum(n))

ggplot(tab_cc, aes(x=con_centro, y=prop, fill=con_centro)) +
  geom_col(show.legend=FALSE) +
  geom_text(aes(label=percent(prop,1)), vjust=-0.4, size=3, colour=azul1) +
  scale_fill_manual(values=escala_blues[1:5]) +
  scale_y_continuous(labels=percent, limits=c(0,.65)) +
  facet_wrap(~contexto, ncol=3) +
  labs(title="¿Qué grado de conocimiento crees que tiene el profesorado de tu centro?",
       x=NULL, y="Proporción") + tema_epjg + theme(axis.text.x=element_text(size=8))

3.3 Importancia de la EpJG

tab_imp <- df_plot %>% filter(!is.na(importancia)) %>%
  mutate(importancia=factor(importancia,1:5,lik5)) %>%
  count(contexto, importancia) %>% group_by(contexto) %>% mutate(prop=n/sum(n))

ggplot(tab_imp, aes(x=importancia, y=prop, fill=importancia)) +
  geom_col(show.legend=FALSE) +
  geom_text(aes(label=percent(prop,1)), vjust=-0.4, size=3, colour=azul1) +
  scale_fill_manual(values=escala_blues[1:5]) +
  scale_y_continuous(labels=percent, limits=c(0,.70)) +
  facet_wrap(~contexto, ncol=3) +
  labs(title="¿Qué importancia tiene introducir la EpJG en tu práctica?",
       x=NULL, y="Proporción") + tema_epjg + theme(axis.text.x=element_text(size=8))

3.4 Comparación de las tres dimensiones

dim_stats <- df_plot %>%
  select(contexto, con_propio, con_centro, importancia) %>%
  pivot_longer(-contexto, names_to="dim", values_to="valor") %>%
  filter(!is.na(valor)) %>%
  group_by(contexto, dim) %>%
  summarise(Media=mean(valor,na.rm=TRUE), DT=sd(valor,na.rm=TRUE), .groups="drop") %>%
  mutate(dim=factor(dim, c("con_propio","con_centro","importancia"),
                    c("Conocimiento propio","Conoc. del centro","Importancia")))

ggplot(dim_stats, aes(x=dim, y=Media, fill=contexto)) +
  geom_col(position=position_dodge(0.8), width=0.7) +
  geom_errorbar(aes(ymin=Media-DT, ymax=Media+DT),
                position=position_dodge(0.8), width=0.25, colour="#444", linewidth=0.5) +
  geom_text(aes(label=round(Media,2)), position=position_dodge(0.8),
            vjust=-0.7, size=3.2, colour=azul1) +
  scale_fill_manual(values=col_ctx, name="Contexto") +
  scale_y_continuous(limits=c(0,6.5), breaks=1:5) +
  labs(title="Comparación: conocimiento e importancia de la EpJG",
       subtitle="Media ± DT (escala 1–5)", x=NULL, y="Puntuación media (1–5)") + tema_epjg

dim_stats %>%
  mutate(val=str_c(round(Media,2)," (",round(DT,2),")")) %>%
  select(contexto,dim,val) %>%
  pivot_wider(names_from=contexto, values_from=val) %>%
  rename(Dimensión=dim) %>%
  kable(caption="Conocimiento e importancia de la EpJG — Media (DT), escala 1–5") %>%
  kable_styling(bootstrap_options=c("striped","hover"), full_width=FALSE) %>%
  column_spec(1, bold=TRUE, color=azul1) %>% column_spec(4, bold=TRUE, background=azul7)
Conocimiento e importancia de la EpJG — Media (DT), escala 1–5
Dimensión Cataluña España (resto) Total
Conoc. del centro 2.23 (0.93) 2.16 (1.02) 2.2 (0.97)
Conocimiento propio 2.35 (1.12) 2.32 (1.15) 2.34 (1.13)
Importancia 3.71 (1.08) 3.88 (1.11) 3.79 (1.1)

4 Apoyo a los movimientos sociales

movs     <- c("sup_ecologismo","sup_pacifismo","sup_feminismo",
               "sup_der_hum","sup_lgtbiq","sup_antirac","sup_anticap")
lab_movs <- c("Ecologismo","Pacifismo","Feminismo","Derechos humanos",
               "LGTBIQ+","Antirracismo","Anticapitalismo")

tab_mov <- df_plot %>%
  select(contexto, all_of(movs)) %>%
  pivot_longer(-contexto, names_to="movimiento", values_to="valor") %>%
  filter(!is.na(valor)) %>%
  mutate(movimiento=factor(movimiento, movs, lab_movs))

4.1 Perfil global

mov_stats <- tab_mov %>% group_by(contexto,movimiento) %>%
  summarise(Media=mean(valor,na.rm=TRUE), DT=sd(valor,na.rm=TRUE), .groups="drop")

ggplot(mov_stats, aes(x=fct_reorder(movimiento,Media,.fun=function(x)x[3]),
                       y=Media, fill=contexto)) +
  geom_col(position=position_dodge(0.8), width=0.75) +
  geom_errorbar(aes(ymin=Media-DT, ymax=Media+DT),
                position=position_dodge(0.8), width=0.25, colour="#555", linewidth=0.5) +
  scale_fill_manual(values=col_ctx, name="Contexto") +
  scale_y_continuous(limits=c(0,6), breaks=1:5) +
  coord_flip() +
  labs(title="Grado de apoyo a los principios de los movimientos sociales",
       subtitle="Media ± DT (escala 1–5)", x=NULL, y="Puntuación media") + tema_epjg

4.2 Distribución por movimiento

tab_mov %>%
  mutate(valor=factor(valor,1:5,lik5)) %>%
  count(contexto,movimiento,valor) %>%
  group_by(contexto,movimiento) %>% mutate(prop=n/sum(n)) %>%
  ggplot(aes(x=valor, y=prop, fill=valor)) +
  geom_col(show.legend=FALSE) +
  scale_fill_manual(values=escala_blues[1:5]) +
  scale_y_continuous(labels=percent, breaks=c(0,.5)) +
  facet_grid(movimiento~contexto) +
  labs(title="Distribución del apoyo por movimiento social", x=NULL, y="Proporción") +
  tema_epjg + theme(axis.text.x=element_text(angle=45,hjust=1,size=7),
                    strip.text.y=element_text(angle=0,size=7))

4.3 Tabla resumen

mov_stats %>%
  mutate(val=str_c(round(Media,2)," (",round(DT,2),")")) %>%
  select(contexto,movimiento,val) %>%
  pivot_wider(names_from=contexto, values_from=val) %>%
  rename(Movimiento=movimiento) %>%
  kable(caption="Apoyo a los movimientos sociales — Media (DT), escala 1–5") %>%
  kable_styling(bootstrap_options=c("striped","hover"), full_width=FALSE) %>%
  column_spec(1, bold=TRUE, color=azul1) %>% column_spec(4, bold=TRUE, background=azul7)
Apoyo a los movimientos sociales — Media (DT), escala 1–5
Movimiento Cataluña España (resto) Total
Ecologismo 4.32 (0.93) 4.4 (0.88) 4.36 (0.91)
Pacifismo 4.57 (0.76) 4.67 (0.75) 4.62 (0.76)
Feminismo 4.34 (0.94) 4.39 (1.04) 4.36 (0.99)
Derechos humanos 4.62 (0.73) 4.75 (0.67) 4.68 (0.71)
LGTBIQ+ 4.38 (0.92) 4.35 (1.03) 4.37 (0.97)
Antirracismo 4.65 (0.72) 4.73 (0.7) 4.69 (0.71)
Anticapitalismo 3.82 (1.2) 3.82 (1.26) 3.82 (1.23)

5 Conocimiento sobre las temáticas de la EpJG

conocs    <- c("conoc_genero","conoc_paz","conoc_derechos","conoc_just_eco",
               "conoc_just_amb","conoc_intercult","conoc_bienestar",
               "conoc_rel_educ","conoc_digital","conoc_tecnologia")

tab_conoc <- df_plot %>%
  select(contexto, all_of(conocs)) %>%
  pivot_longer(-contexto, names_to="tematica", values_to="valor") %>%
  filter(!is.na(valor)) %>%
  mutate(tematica=factor(tematica, conocs, etiquetas_tema))

5.1 Puntuación media

conoc_stats <- tab_conoc %>% group_by(contexto,tematica) %>%
  summarise(Media=mean(valor,na.rm=TRUE), DT=sd(valor,na.rm=TRUE), .groups="drop")

ggplot(conoc_stats, aes(x=fct_reorder(tematica,Media,.fun=function(x)x[3]),
                         y=Media, fill=contexto)) +
  geom_col(position=position_dodge(0.8), width=0.75) +
  geom_errorbar(aes(ymin=Media-DT, ymax=Media+DT),
                position=position_dodge(0.8), width=0.25, colour="#555", linewidth=0.5) +
  scale_fill_manual(values=col_ctx, name="Contexto") +
  scale_y_continuous(limits=c(0,6), breaks=1:5) + coord_flip() +
  labs(title="Grado de conocimiento sobre las temáticas de la EpJG",
       subtitle="Media ± DT (escala 1–5)", x=NULL, y="Puntuación media") + tema_epjg

5.2 Distribución por temática

tab_conoc %>%
  mutate(valor=factor(valor,1:5,lik5)) %>%
  count(contexto,tematica,valor) %>%
  group_by(contexto,tematica) %>% mutate(prop=n/sum(n)) %>%
  ggplot(aes(x=valor, y=prop, fill=valor)) +
  geom_col(show.legend=FALSE) +
  scale_fill_manual(values=escala_blues[1:5]) +
  scale_y_continuous(labels=percent, breaks=c(0,.5)) +
  facet_grid(tematica~contexto) +
  labs(title="Distribución del conocimiento por temática", x=NULL, y="Proporción") +
  tema_epjg + theme(axis.text.x=element_text(angle=45,hjust=1,size=7),
                    strip.text.y=element_text(angle=0,size=7))

5.3 Tabla resumen

conoc_stats %>%
  mutate(val=str_c(round(Media,2)," (",round(DT,2),")")) %>%
  select(contexto,tematica,val) %>%
  pivot_wider(names_from=contexto, values_from=val) %>%
  rename(Temática=tematica) %>%
  kable(caption="Conocimiento sobre las temáticas — Media (DT), escala 1–5") %>%
  kable_styling(bootstrap_options=c("striped","hover"), full_width=FALSE) %>%
  column_spec(1, bold=TRUE, color=azul1) %>% column_spec(4, bold=TRUE, background=azul7)
Conocimiento sobre las temáticas — Media (DT), escala 1–5
Temática Cataluña España (resto) Total
Género y feminismos 3.73 (0.83) 3.79 (0.86) 3.76 (0.85)
Cultura de paz 3.86 (0.76) 3.84 (0.86) 3.85 (0.81)
Derechos humanos 3.66 (0.86) 3.69 (0.91) 3.67 (0.89)
Justicia econ. y social 3.38 (0.94) 3.44 (0.99) 3.41 (0.96)
Justicia ambiental 3.4 (0.98) 3.5 (1.01) 3.45 (1)
Interculturalidad 3.68 (0.87) 3.74 (0.91) 3.71 (0.89)
Bienestar emocional 4.01 (0.85) 3.92 (0.97) 3.97 (0.91)
Relación educativa 3.54 (1.02) 3.63 (0.98) 3.58 (1.01)
Equidad digital 3.2 (0.97) 3.24 (1.07) 3.22 (1.02)
Crít. tecnología 3.21 (1) 3.35 (1.08) 3.28 (1.04)

6 Temáticas trabajadas en el aula

trabs <- c("trab_genero","trab_paz","trab_derechos","trab_just_eco",
            "trab_just_amb","trab_intercult","trab_bienestar",
            "trab_rel_educ","trab_digital","trab_tecnologia")

tab_trab <- df_plot %>%
  select(contexto, all_of(trabs)) %>%
  pivot_longer(-contexto, names_to="tematica", values_to="valor") %>%
  filter(!is.na(valor)) %>%
  mutate(tematica=factor(str_remove(tematica,"trab_"),
                          str_remove(trabs,"trab_"), etiquetas_tema),
         valor=str_to_upper(str_trim(valor))) %>%
  count(contexto,tematica,valor) %>%
  group_by(contexto,tematica) %>% mutate(prop=n/sum(n)) %>%
  filter(valor=="SÍ")

6.1 % que trabaja cada temática

ggplot(tab_trab, aes(x=fct_reorder(tematica,prop,.fun=function(x)x[3]),
                      y=prop, fill=contexto)) +
  geom_col(position=position_dodge(0.8), width=0.75) +
  geom_text(aes(label=percent(prop,1)), position=position_dodge(0.8),
            hjust=-0.1, size=2.8, colour=azul1) +
  scale_fill_manual(values=col_ctx, name="Contexto") +
  scale_y_continuous(labels=percent, limits=c(0,1.1)) + coord_flip() +
  labs(title="Temáticas de la EpJG trabajadas en el aula (% SÍ)",
       x=NULL, y="% que responde SÍ") + tema_epjg

6.2 Tabla resumen

tab_trab %>%
  mutate(pct=percent(prop,1)) %>%
  select(contexto,tematica,pct) %>%
  pivot_wider(names_from=contexto, values_from=pct) %>%
  rename(Temática=tematica) %>%
  kable(caption="Porcentaje de docentes que trabaja cada temática (SÍ)") %>%
  kable_styling(bootstrap_options=c("striped","hover"), full_width=FALSE) %>%
  column_spec(1, bold=TRUE, color=azul1) %>% column_spec(4, bold=TRUE, background=azul7)
Porcentaje de docentes que trabaja cada temática (SÍ)
Temática Cataluña España (resto) Total
Género y feminismos 77% 76% 77%
Cultura de paz 83% 82% 83%
Derechos humanos 70% 71% 70%
Justicia econ. y social 46% 54% 50%
Justicia ambiental 63% 65% 64%
Interculturalidad 81% 81% 81%
Bienestar emocional 86% 85% 86%
Relación educativa 62% 70% 66%
Equidad digital 41% 44% 42%
Crít. tecnología 55% 67% 61%

7 Dificultades para incorporar la EpJG

difs <- c("dif_genero","dif_paz","dif_derechos","dif_just_eco",
           "dif_just_amb","dif_intercult","dif_bienestar",
           "dif_rel_educ","dif_digital","dif_tecnologia")

tab_dif <- df_plot %>%
  select(contexto, all_of(difs)) %>%
  pivot_longer(-contexto, names_to="tematica", values_to="dificultad") %>%
  filter(!is.na(dificultad)) %>%
  mutate(tematica=factor(str_remove(tematica,"dif_"),
                          str_remove(difs,"dif_"), etiquetas_tema))

7.1 Dificultad principal (global, todas las temáticas)

tab_dif_glob <- tab_dif %>%
  count(contexto, dificultad) %>%
  group_by(contexto) %>% mutate(prop=n/sum(n)) %>%
  filter(!is.na(dificultad))

ggplot(tab_dif_glob, aes(x=fct_reorder(dificultad,prop,.fun=function(x)x[3]),
                          y=prop, fill=contexto)) +
  geom_col(position=position_dodge(0.8), width=0.75) +
  geom_text(aes(label=percent(prop,1)), position=position_dodge(0.8),
            hjust=-0.1, size=2.8, colour=azul1) +
  scale_fill_manual(values=col_ctx, name="Contexto") +
  scale_y_continuous(labels=percent, limits=c(0,.45)) + coord_flip() +
  labs(title="Principal dificultad para incorporar la EpJG en el aula",
       subtitle="Agregado sobre todas las temáticas",
       x=NULL, y="Proporción de menciones") + tema_epjg

7.2 Por temática

tab_dif_tema <- tab_dif %>%
  count(contexto, tematica, dificultad) %>%
  group_by(contexto, tematica) %>% mutate(prop=n/sum(n))

# Mostrar solo las 3 dificultades más frecuentes por legibilidad
top3_dif <- tab_dif %>% count(dificultad, sort=TRUE) %>%
  head(6) %>% pull(dificultad)

tab_dif_tema %>%
  filter(dificultad %in% top3_dif) %>%
  ggplot(aes(x=dificultad, y=prop, fill=contexto)) +
  geom_col(position=position_dodge(0.8), width=0.75) +
  scale_fill_manual(values=col_ctx, name="Contexto") +
  scale_y_continuous(labels=percent, limits=c(0,.65)) +
  facet_wrap(~tematica, ncol=2) +
  labs(title="Dificultades más frecuentes por temática",
       x=NULL, y="Proporción") + tema_epjg +
  theme(axis.text.x=element_text(angle=40, hjust=1, size=7))

7.3 Tabla resumen

tab_dif_glob %>%
  mutate(pct=percent(prop,1)) %>%
  select(contexto,dificultad,pct) %>%
  pivot_wider(names_from=contexto, values_from=pct) %>%
  arrange(desc(Total)) %>%
  rename(Dificultad=dificultad) %>%
  kable(caption="Distribución de la principal dificultad (agregada sobre todas las temáticas)") %>%
  kable_styling(bootstrap_options=c("striped","hover"), full_width=FALSE) %>%
  column_spec(1, bold=TRUE, color=azul1) %>% column_spec(4, bold=TRUE, background=azul7)
Distribución de la principal dificultad (agregada sobre todas las temáticas)
Dificultad Cataluña España (resto) Total
Falta de interés personal 5% 6% 5%
Falta de recursos económicos 6% 5% 5%
Falta de apoyo de las familias 3% 6% 4%
Falta de tiempo 38% 39% 39%
Falta de formación 20% 20% 20%
Falta de recursos pedagógicos 18% 13% 15%
Falta de regulación institucional 11% 12% 11%

8 Interés en formarse en las temáticas

ints <- c("int_genero","int_paz","int_derechos","int_just_eco",
           "int_just_amb","int_intercult","int_bienestar",
           "int_rel_educ","int_digital","int_tecnologia")

tab_int <- df_plot %>%
  select(contexto, all_of(ints)) %>%
  pivot_longer(-contexto, names_to="tematica", values_to="valor") %>%
  filter(!is.na(valor)) %>%
  mutate(tematica=factor(str_remove(tematica,"int_"),
                          str_remove(ints,"int_"), etiquetas_tema))

8.1 Puntuación media

int_stats <- tab_int %>% group_by(contexto,tematica) %>%
  summarise(Media=mean(valor,na.rm=TRUE), DT=sd(valor,na.rm=TRUE), .groups="drop")

ggplot(int_stats, aes(x=fct_reorder(tematica,Media,.fun=function(x)x[3]),
                       y=Media, fill=contexto)) +
  geom_col(position=position_dodge(0.8), width=0.75) +
  geom_errorbar(aes(ymin=Media-DT, ymax=Media+DT),
                position=position_dodge(0.8), width=0.25, colour="#555", linewidth=0.5) +
  scale_fill_manual(values=col_ctx, name="Contexto") +
  scale_y_continuous(limits=c(0,6), breaks=1:5) + coord_flip() +
  labs(title="Interés en formarse en las temáticas de la EpJG",
       subtitle="Media ± DT (escala 1–5)", x=NULL, y="Puntuación media") + tema_epjg

8.2 Distribución por temática

tab_int %>%
  mutate(valor=factor(valor,1:5,lik5)) %>%
  count(contexto,tematica,valor) %>%
  group_by(contexto,tematica) %>% mutate(prop=n/sum(n)) %>%
  ggplot(aes(x=valor, y=prop, fill=valor)) +
  geom_col(show.legend=FALSE) +
  scale_fill_manual(values=escala_blues[1:5]) +
  scale_y_continuous(labels=percent, breaks=c(0,.5)) +
  facet_grid(tematica~contexto) +
  labs(title="Distribución del interés en formarse por temática", x=NULL, y="Proporción") +
  tema_epjg + theme(axis.text.x=element_text(angle=45,hjust=1,size=7),
                    strip.text.y=element_text(angle=0,size=7))

8.3 Comparación: conocimiento vs. interés

comp <- bind_rows(
  conoc_stats %>% mutate(tipo="Conocimiento actual"),
  int_stats    %>% mutate(tipo="Interés en formarse")
) %>% filter(contexto == "Total")

ggplot(comp, aes(x=fct_reorder(tematica,Media), y=Media, fill=tipo)) +
  geom_col(position=position_dodge(0.8), width=0.75) +
  geom_errorbar(aes(ymin=Media-DT, ymax=Media+DT),
                position=position_dodge(0.8), width=0.25, colour="#444", linewidth=0.5) +
  scale_fill_manual(values=c("Conocimiento actual"=azul3, "Interés en formarse"=azul1),
                    name=NULL) +
  scale_y_continuous(limits=c(0,6), breaks=1:5) + coord_flip() +
  labs(title="Conocimiento actual vs. Interés en formarse (Total muestra)",
       subtitle="Media ± DT (escala 1–5)", x=NULL, y="Puntuación media") + tema_epjg

8.4 Tabla resumen

int_stats %>%
  mutate(val=str_c(round(Media,2)," (",round(DT,2),")")) %>%
  select(contexto,tematica,val) %>%
  pivot_wider(names_from=contexto, values_from=val) %>%
  rename(Temática=tematica) %>%
  kable(caption="Interés en formarse — Media (DT), escala 1–5") %>%
  kable_styling(bootstrap_options=c("striped","hover"), full_width=FALSE) %>%
  column_spec(1, bold=TRUE, color=azul1) %>% column_spec(4, bold=TRUE, background=azul7)
Interés en formarse — Media (DT), escala 1–5
Temática Cataluña España (resto) Total
Género y feminismos 3.31 (1.38) 3.51 (1.41) 3.41 (1.4)
Cultura de paz 3.51 (1.28) 3.73 (1.28) 3.61 (1.29)
Derechos humanos 3.43 (1.25) 3.78 (1.23) 3.6 (1.25)
Justicia econ. y social 3.43 (1.26) 3.75 (1.24) 3.58 (1.26)
Justicia ambiental 3.53 (1.24) 3.8 (1.22) 3.66 (1.24)
Interculturalidad 3.63 (1.23) 3.91 (1.18) 3.76 (1.21)
Bienestar emocional 3.92 (1.26) 4.13 (1.19) 4.02 (1.23)
Relación educativa 3.71 (1.24) 3.97 (1.22) 3.83 (1.24)
Equidad digital 3.17 (1.29) 3.46 (1.3) 3.31 (1.3)
Crít. tecnología 3.33 (1.34) 3.71 (1.27) 3.51 (1.32)

9 Preferencias de formación

9.1 Formato preferido

tab_fmt <- df_plot %>% filter(!is.na(formato_pref)) %>%
  mutate(fmt=str_trim(formato_pref),
         fmt=case_when(
           str_detect(fmt,"irtual")                   ~ "Virtual",
           str_detect(fmt,"resencial")                ~ "Presencial",
           str_detect(fmt,"emisencial|emipresencial") ~ "Semipresencial",
           TRUE ~ fmt
         )) %>%
  count(contexto, fmt) %>% group_by(contexto) %>%
  mutate(prop=n/sum(n), fmt=factor(fmt,c("Presencial","Virtual","Semipresencial")))

ggplot(tab_fmt, aes(x=fmt, y=prop, fill=contexto)) +
  geom_col(position=position_dodge(0.8), width=0.7) +
  geom_text(aes(label=percent(prop,1)), position=position_dodge(0.8),
            vjust=-0.4, size=3.2, colour=azul1) +
  scale_fill_manual(values=col_ctx, name="Contexto") +
  scale_y_continuous(labels=percent, limits=c(0,.60)) +
  labs(title="Formato de formación preferido", x=NULL, y="Proporción") + tema_epjg

9.2 Modalidad formativa

arm_modalidad <- function(x) {
  case_when(
    str_detect(x, regex("curs|curso",           ignore_case=TRUE)) ~ "Curso",
    str_detect(x, regex("taller|seminari|seminar", ignore_case=TRUE)) ~ "Talleres/Seminarios",
    str_detect(x, regex("intercanvi|intercambio",  ignore_case=TRUE)) ~ "Intercambio de experiencias",
    str_detect(x, regex("conferèn|conferenci",     ignore_case=TRUE)) ~ "Ciclos de conferencias",
    str_detect(x, regex("assessorament|asesoramiento", ignore_case=TRUE)) ~ "Asesoramiento en centros",
    str_detect(x, regex("comunitat|comunidad",     ignore_case=TRUE)) ~ "Comunidad de aprendizaje",
    TRUE ~ x
  )
}

mod_base <- bind_rows(
  tibble(modalidad=raw_cat[[72]], contexto="Cataluña"),
  tibble(modalidad=raw_esp[[73]], contexto="España (resto)")
) %>%
  filter(!is.na(modalidad)) %>%
  mutate(modalidad=str_split(modalidad,";")) %>%
  unnest(modalidad) %>%
  mutate(modalidad=str_trim(modalidad)) %>%
  filter(modalidad != "")

tab_mod <- bind_rows(mod_base, mod_base %>% mutate(contexto="Total")) %>%
  mutate(contexto=factor(contexto,c("Cataluña","España (resto)","Total")),
         modalidad=arm_modalidad(modalidad)) %>%
  count(contexto,modalidad) %>%
  group_by(contexto) %>% mutate(prop=n/sum(n)) %>%
  filter(n > 2)

ggplot(tab_mod, aes(x=fct_reorder(modalidad,prop,.fun=function(x)x[3]),
                     y=prop, fill=contexto)) +
  geom_col(position=position_dodge(0.8), width=0.75) +
  geom_text(aes(label=percent(prop,1)), position=position_dodge(0.8),
            hjust=-0.1, size=2.8, colour=azul1) +
  scale_fill_manual(values=col_ctx, name="Contexto") +
  scale_y_continuous(labels=percent, limits=c(0,.55)) + coord_flip() +
  labs(title="Modalidad formativa preferida (respuesta múltiple)",
       subtitle="Porcentaje calculado sobre el total de respuestas por contexto",
       x=NULL, y="Proporción de menciones") + tema_epjg


10 Resumen ejecutivo

Resumen ejecutivo por contexto
Indicador Cataluña España (resto) Total
n (válidos edad) 514 465 979
Edad media (años) 45 años 45.8 años 45.4 años
% Femenino 71.6% 67.7% 69.7%
Régimen mayoritario Público Público Público
Tipología mayoritaria Urbana Urbana Urbana
Conoc. propio EpJG (1–5) 2.35 2.32 2.34
Conoc. percibido centro (1–5) 2.23 2.16 2.2
Importancia EpJG (1–5) 3.71 3.88 3.79
Conoc. medio temáticas (1–5) 3.57 3.62 3.59
Interés medio formación (1–5) 3.5 3.78 3.63

11 Líneas de análisis

Las siguientes secciones amplían los descriptivos con inferencia estadística orientada a la publicación científica.
Criterio de normalidad: dado el tamaño muestral (n > 50 por grupo), se usa el test de Kolmogorov-Smirnov con corrección de Lilliefors (nortest). Para muestras Likert con asimetría evidente se aplican tests no paramétricos.

# Instala si es necesario:
# install.packages(c("nortest","coin","rstatix","ggcorrplot","cluster","factoextra","MASS","broom","purrr"))

# Orden de carga importante: coin y MASS antes de rstatix y dplyr
# para que sus funciones no enmascaren las que usamos
library(nortest)     # KS-Lilliefors
library(coin)        # wilcoxon_test exacto (carga antes que rstatix)
library(MASS)        # polr — carga antes que dplyr
library(rstatix)     # wilcox_test, adjust_pvalue
library(ggcorrplot)  # heatmap correlaciones
library(cluster)     # PAM (k-medoides)
library(factoextra)  # fviz_cluster, fviz_nbclust
library(broom)       # tidy() para tablas de modelos
library(purrr)       # map_dfr

# Restaurar dplyr al final para que su select() tenga prioridad
library(dplyr)

11.1 L1 — Diferencias entre contextos (Cataluña vs. España)

11.1.1 Pruebas de normalidad

# Variables Likert principales sobre las que se comparan los dos grupos
vars_likert <- c("con_propio", "con_centro", "importancia",
                 "sup_ecologismo","sup_pacifismo","sup_feminismo",
                 "sup_der_hum","sup_lgtbiq","sup_antirac","sup_anticap",
                 paste0("conoc_", c("genero","paz","derechos","just_eco",
                                    "just_amb","intercult","bienestar",
                                    "rel_educ","digital","tecnologia")),
                 paste0("int_",   c("genero","paz","derechos","just_eco",
                                    "just_amb","intercult","bienestar",
                                    "rel_educ","digital","tecnologia")))

# KS-Lilliefors por contexto
norm_test <- df %>%
  dplyr::select(contexto, all_of(vars_likert)) %>%
  pivot_longer(-contexto, names_to = "variable", values_to = "valor") %>%
  dplyr::filter(!is.na(valor)) %>%
  dplyr::group_by(contexto, variable) %>%
  dplyr::summarise(
    n        = n(),
    KS_D     = tryCatch(lillie.test(valor)$statistic, error = function(e) NA_real_),
    KS_p     = tryCatch(lillie.test(valor)$p.value,   error = function(e) NA_real_),
    Normal   = ifelse(!is.na(KS_p) & KS_p > .05, "Sí", "No"),
    .groups  = "drop"
  )

# Resumen: ¿cuántas variables superan la normalidad?
norm_test %>%
  dplyr::count(contexto, Normal) %>%
  kable(caption = "Normalidad por contexto (KS-Lilliefors): número de variables") %>%
  kable_styling(bootstrap_options = c("striped","hover"), full_width = FALSE)
Normalidad por contexto (KS-Lilliefors): número de variables
contexto Normal n
Cataluña No 30
España (resto) No 30
# Tabla completa
norm_test %>%
  dplyr::mutate(KS_D = round(KS_D, 3), KS_p = round(KS_p, 3)) %>%
  kable(caption = "Test de normalidad KS-Lilliefors por variable y contexto") %>%
  kable_styling(bootstrap_options = c("striped","hover"), full_width = FALSE) %>%
  scroll_box(height = "400px")
Test de normalidad KS-Lilliefors por variable y contexto
contexto variable n KS_D KS_p Normal
Cataluña con_centro 515 0.234 0 No
Cataluña con_propio 515 0.209 0 No
Cataluña conoc_bienestar 515 0.253 0 No
Cataluña conoc_derechos 515 0.232 0 No
Cataluña conoc_digital 515 0.195 0 No
Cataluña conoc_genero 515 0.274 0 No
Cataluña conoc_intercult 515 0.247 0 No
Cataluña conoc_just_amb 515 0.201 0 No
Cataluña conoc_just_eco 515 0.209 0 No
Cataluña conoc_paz 515 0.284 0 No
Cataluña conoc_rel_educ 515 0.227 0 No
Cataluña conoc_tecnologia 515 0.189 0 No
Cataluña importancia 515 0.213 0 No
Cataluña int_bienestar 515 0.263 0 No
Cataluña int_derechos 515 0.183 0 No
Cataluña int_digital 515 0.154 0 No
Cataluña int_genero 515 0.168 0 No
Cataluña int_intercult 515 0.195 0 No
Cataluña int_just_amb 515 0.190 0 No
Cataluña int_just_eco 515 0.166 0 No
Cataluña int_paz 515 0.174 0 No
Cataluña int_rel_educ 515 0.199 0 No
Cataluña int_tecnologia 515 0.162 0 No
Cataluña sup_anticap 515 0.222 0 No
Cataluña sup_antirac 515 0.444 0 No
Cataluña sup_der_hum 515 0.429 0 No
Cataluña sup_ecologismo 515 0.323 0 No
Cataluña sup_feminismo 515 0.340 0 No
Cataluña sup_lgtbiq 515 0.350 0 No
Cataluña sup_pacifismo 515 0.406 0 No
España (resto) con_centro 466 0.218 0 No
España (resto) con_propio 466 0.200 0 No
España (resto) conoc_bienestar 466 0.253 0 No
España (resto) conoc_derechos 466 0.233 0 No
España (resto) conoc_digital 466 0.179 0 No
España (resto) conoc_genero 466 0.251 0 No
España (resto) conoc_intercult 466 0.248 0 No
España (resto) conoc_just_amb 466 0.204 0 No
España (resto) conoc_just_eco 466 0.209 0 No
España (resto) conoc_paz 466 0.260 0 No
España (resto) conoc_rel_educ 466 0.242 0 No
España (resto) conoc_tecnologia 466 0.189 0 No
España (resto) importancia 466 0.227 0 No
España (resto) int_bienestar 466 0.318 0 No
España (resto) int_derechos 466 0.208 0 No
España (resto) int_digital 466 0.184 0 No
España (resto) int_genero 466 0.196 0 No
España (resto) int_intercult 466 0.230 0 No
España (resto) int_just_amb 466 0.220 0 No
España (resto) int_just_eco 466 0.214 0 No
España (resto) int_paz 466 0.211 0 No
España (resto) int_rel_educ 466 0.272 0 No
España (resto) int_tecnologia 466 0.207 0 No
España (resto) sup_anticap 466 0.230 0 No
España (resto) sup_antirac 466 0.472 0 No
España (resto) sup_der_hum 466 0.481 0 No
España (resto) sup_ecologismo 466 0.351 0 No
España (resto) sup_feminismo 466 0.386 0 No
España (resto) sup_lgtbiq 466 0.359 0 No
España (resto) sup_pacifismo 466 0.455 0 No

Decisión: si alguna variable no sigue distribución normal (p < .05, habitual en escalas Likert), se aplica el test de Mann-Whitney U en lugar de la t de Student para todas las comparaciones de esta línea, para mantener coherencia metodológica.

11.1.2 Mann-Whitney U: comparaciones entre contextos

library(rstatix)

mwu_res <- df %>%
  dplyr::select(contexto, all_of(vars_likert)) %>%
  dplyr::filter(contexto %in% c("Cataluña","España (resto)")) %>%
  pivot_longer(-contexto, names_to = "variable", values_to = "valor") %>%
  dplyr::filter(!is.na(valor)) %>%
  dplyr::group_by(variable) %>%
  rstatix::wilcox_test(valor ~ contexto, paired = FALSE) %>%
  rstatix::adjust_pvalue(method = "BH") %>%
  rstatix::add_significance("p.adj") %>%
  dplyr::mutate(r = abs(statistic) / sqrt(n1 + n2))

# Tabla de resultados significativos
mwu_res %>%
  dplyr::filter(p.adj < .05) %>%
  dplyr::select(variable, n1, n2, statistic, p, p.adj, p.adj.signif, r) %>%
  dplyr::mutate(across(c(p, p.adj, r), ~ round(.x, 3))) %>%
  arrange(p.adj) %>%
  kable(caption = "Diferencias significativas entre contextos (Mann-Whitney U, corrección BH)
        — Solo resultados con p.adj < .05") %>%
  kable_styling(bootstrap_options = c("striped","hover"), full_width = FALSE) %>%
  column_spec(7, bold = TRUE, color = azul1)
Diferencias significativas entre contextos (Mann-Whitney U, corrección BH) — Solo resultados con p.adj < .05
variable n1 n2 statistic p p.adj p.adj.signif r
int_derechos 515 466 100010.5 0.000 0.000 **** 3193.090
int_just_eco 515 466 101819.5 0.000 0.000 *** 3250.846
int_tecnologia 515 466 100308.0 0.000 0.000 **** 3202.588
sup_der_hum 515 466 107063.0 0.000 0.000 *** 3418.259
int_digital 515 466 104634.0 0.000 0.001 ** 3340.707
int_intercult 515 466 103251.5 0.000 0.001 *** 3296.567
int_just_amb 515 466 104412.5 0.000 0.001 ** 3333.635
int_rel_educ 515 466 103917.0 0.000 0.001 *** 3317.814
sup_pacifismo 515 466 109548.0 0.002 0.007 ** 3497.598
importancia 515 466 107355.5 0.003 0.009 ** 3427.597
int_bienestar 515 466 108131.5 0.004 0.011
3452.373
int_paz 515 466 107823.0 0.004 0.011
3442.523
sup_antirac 515 466 111850.5 0.010 0.023
3571.112
int_genero 515 466 109344.5 0.014 0.029
3491.101
conoc_tecnologia 515 466 110055.0 0.019 0.039
3513.786
# Gráfico de tamaños del efecto (r) para variables significativas
mwu_res %>%
  filter(p.adj < .05) %>%
  mutate(
    variable = factor(variable, levels = variable[order(r)]),
    magnitud = case_when(r >= .5 ~ "Grande (≥ .50)",
                         r >= .3 ~ "Mediano (.30–.49)",
                         TRUE    ~ "Pequeño (< .30)")
  ) %>%
  ggplot(aes(x = variable, y = r, fill = magnitud)) +
  geom_col() +
  scale_fill_manual(values = c("Grande (≥ .50)" = azul1,
                               "Mediano (.30–.49)" = azul3,
                               "Pequeño (< .30)" = azul6),
                    name = "Magnitud efecto") +
  coord_flip() +
  labs(title = "Tamaño del efecto (r) de las diferencias entre contextos",
       subtitle = "Solo variables con p.adj < .05 (corrección Benjamini-Hochberg)",
       x = NULL, y = "r de Cohen") +
  tema_epjg


11.2 L2 — Brecha conocimiento–interés en formación

Hipótesis: el interés en formarse es significativamente superior al conocimiento actual para cada temática. Test de Wilcoxon de rangos con signo (muestras relacionadas, mismo sujeto responde ambas escalas).

# Normalidad de las diferencias (conoc - interés) por temática
temas_cod <- c("genero","paz","derechos","just_eco","just_amb",
               "intercult","bienestar","rel_educ","digital","tecnologia")

diff_norm <- df %>%
  dplyr::select(all_of(paste0("conoc_", temas_cod)),
                all_of(paste0("int_",   temas_cod))) %>%
  dplyr::mutate(across(everything(), as.numeric))

norm_diff <- map_dfr(temas_cod, function(t) {
  d <- diff_norm[[paste0("conoc_",t)]] - diff_norm[[paste0("int_",t)]]
  d <- d[!is.na(d)]
  tibble(
    Temática = etiquetas_tema[match(t, temas_cod)],
    n        = length(d),
    KS_D     = round(lillie.test(d)$statistic, 3),
    KS_p     = round(lillie.test(d)$p.value, 3),
    Normal   = ifelse(lillie.test(d)$p.value > .05, "Sí", "No")
  )
})

norm_diff %>%
  kable(caption = "Normalidad de las diferencias (conocimiento − interés) por temática") %>%
  kable_styling(bootstrap_options = c("striped","hover"), full_width = FALSE)
Normalidad de las diferencias (conocimiento − interés) por temática
Temática n KS_D KS_p Normal
Género y feminismos 981 0.211 0 No
Cultura de paz 981 0.191 0 No
Derechos humanos 981 0.198 0 No
Justicia econ. y social 981 0.172 0 No
Justicia ambiental 981 0.198 0 No
Interculturalidad 981 0.209 0 No
Bienestar emocional 981 0.235 0 No
Relación educativa 981 0.190 0 No
Equidad digital 981 0.161 0 No
Crít. tecnología 981 0.178 0 No
library(purrr)

brecha_res <- map_dfr(temas_cod, function(t) {
  x <- as.numeric(df[[paste0("conoc_", t)]])
  y <- as.numeric(df[[paste0("int_",   t)]])
  ok <- !is.na(x) & !is.na(y)
  wt <- wilcox.test(x[ok], y[ok], paired = TRUE, exact = FALSE)
  n  <- sum(ok)
  tibble(
    Temática   = etiquetas_tema[match(t, temas_cod)],
    Media_conoc = round(mean(x[ok]), 2),
    Media_int   = round(mean(y[ok]), 2),
    Brecha      = round(mean(x[ok]) - mean(y[ok]), 2),
    W           = wt$statistic,
    p           = round(wt$p.value, 4),
    r           = round(abs(qnorm(wt$p.value / 2)) / sqrt(n), 3)
  )
}) %>%
  mutate(p.adj = round(p.adjust(p, method = "BH"), 4),
         Sig   = case_when(p.adj < .001 ~ "***",
                           p.adj < .01  ~ "**",
                           p.adj < .05  ~ "*",
                           TRUE         ~ "ns"))

brecha_res %>%
  kable(caption = "Wilcoxon rangos con signo: conocimiento actual vs. interés en formarse") %>%
  kable_styling(bootstrap_options = c("striped","hover"), full_width = FALSE) %>%
  column_spec(4, bold = TRUE,
              color = ifelse(brecha_res$Brecha < 0, azul1, "#c0392b"))
Wilcoxon rangos con signo: conocimiento actual vs. interés en formarse
Temática Media_conoc Media_int Brecha W p r p.adj Sig
Género y feminismos 3.76 3.41 0.35 144177.5 0.0000 0.231 0.0000 ***
Cultura de paz 3.85 3.61 0.24 137214.0 0.0000 0.153 0.0000 ***
Derechos humanos 3.67 3.60 0.07 108782.0 0.2496 0.037 0.2496 ns
Justicia econ. y social 3.41 3.58 -0.17 98999.5 0.0000 0.134 0.0000 ***
Justicia ambiental 3.45 3.66 -0.21 77057.5 0.0000 0.168 0.0000 ***
Interculturalidad 3.71 3.76 -0.05 95068.0 0.0725 0.057 0.0864 ns
Bienestar emocional 3.97 4.02 -0.05 84049.5 0.0778 0.056 0.0864 ns
Relación educativa 3.58 3.83 -0.25 80533.0 0.0000 0.190 0.0000 ***
Equidad digital 3.22 3.31 -0.09 102515.0 0.0261 0.071 0.0373
Crít. tecnología 3.28 3.51 -0.23 88804.0 0.0000 0.168 0.0000 ***
# Visualización de la brecha
brecha_res %>%
  mutate(Temática = fct_reorder(Temática, Brecha)) %>%
  ggplot(aes(x = Temática, y = Brecha, fill = Brecha < 0)) +
  geom_col() +
  geom_text(aes(label = str_c(Sig, "  r=", r)),
            hjust = ifelse(brecha_res %>% arrange(Brecha) %>% pull(Brecha) < 0, -0.1, 1.1),
            size = 3, colour = "white") +
  scale_fill_manual(values = c("TRUE" = azul1, "FALSE" = "#c0392b"),
                    labels = c("TRUE" = "Interés > Conocimiento",
                               "FALSE" = "Conocimiento > Interés"),
                    name = NULL) +
  coord_flip() +
  labs(title = "Brecha: conocimiento actual − interés en formarse",
       subtitle = "Negativo = el interés supera al conocimiento  |  * p<.05  ** p<.01  *** p<.001",
       x = NULL, y = "Diferencia de medias (conocimiento − interés)") +
  tema_epjg


11.3 L3 — Predictores del conocimiento de la EpJG

Hipótesis: la formación académica, los años de experiencia y el régimen del centro predicen el autoconocimiento de la EpJG. Regresión ordinal (MASS::polr) dado que la variable dependiente es Likert 1–5.

# Comprobación de normalidad de los residuos se evalúa post-modelo (ver abajo)
# Verificar distribución de la VD
df %>% filter(!is.na(con_propio)) %>%
  count(con_propio) %>%
  mutate(prop = percent(n / sum(n), 1)) %>%
  kable(caption = "Distribución de 'conocimiento propio EpJG' (VD del modelo)") %>%
  kable_styling(bootstrap_options = c("striped","hover"), full_width = FALSE)
Distribución de ‘conocimiento propio EpJG’ (VD del modelo)
con_propio n prop
1 283 29%
2 294 30%
3 221 23%
4 158 16%
5 25 3%
df_mod <- df %>%
  dplyr::filter(!is.na(con_propio), !is.na(formacion), !is.na(experiencia),
                !is.na(regimen), !is.na(ambito), !is.na(contexto)) %>%
  dplyr::mutate(
    con_propio_ord = factor(con_propio, levels = 1:5, ordered = TRUE),
    formacion      = factor(formacion,
                            levels = c("Grado/Licenciatura","Máster/Postgrado","Doctorado")),
    # Colapsar "Privado" en "Concertado" si tiene < 10 casos (evita separación perfecta)
    regimen        = dplyr::case_when(
                       regimen %in% c("Concertado","Privado") ~ "Concertado/Privado",
                       TRUE ~ regimen
                     ) %>% factor(levels = c("Público","Concertado/Privado")),
    # Reagrupar experiencia en 4 tramos para evitar niveles con n muy bajo
    exp_tramo      = dplyr::case_when(
                       experiencia %in% c("0 a 5 años","6 a 10 años")              ~ "0–10 años",
                       experiencia %in% c("11 a 15 años","16 a 20 años")            ~ "11–20 años",
                       experiencia %in% c("21 a 25 años","26 a 30 años")            ~ "21–30 años",
                       experiencia %in% c("31 a 35 años","Más de 35 años")          ~ "> 30 años",
                       TRUE ~ NA_character_
                     ) %>% factor(levels = c("0–10 años","11–20 años","21–30 años","> 30 años"),
                                  ordered = TRUE),
    ambito         = dplyr::case_when(
                       ambito %in% c("Ed. Adultos","Ed. Especial","FP","Bachillerato") ~ "Otros",
                       TRUE ~ ambito
                     ) %>% factor(),
    contexto       = factor(contexto, levels = c("Cataluña","España (resto)"))
  ) %>%
  dplyr::filter(!is.na(exp_tramo)) %>%
  droplevels()   # elimina niveles de factor sin observaciones

# Verificar distribución de predictores (para detectar niveles con n muy bajo)
cat("— Distribución de regimen:\n");  print(table(df_mod$regimen))
## — Distribución de regimen:
## 
##            Público Concertado/Privado 
##                918                 62
cat("— Distribución de exp_tramo:\n"); print(table(df_mod$exp_tramo))
## — Distribución de exp_tramo:
## 
##  0–10 años 11–20 años 21–30 años  > 30 años 
##        420        241        236         83
cat("— Distribución de ambito:\n");   print(table(df_mod$ambito))
## — Distribución de ambito:
## 
##                        Artes plásticas y diseño 
##                                               1 
##                                   Cap d'estudis 
##                                               1 
##                                             CFA 
##                                               1 
##      Cicle for.grau mitja de decoració ceràmica 
##                                               1 
##                                     Cooperación 
##                                               1 
##                            Dirección pedagógica 
##                                               1 
##                                    Ed. Infantil 
##                                              70 
##                                    Ed. Primaria 
##                                             203 
##                                  Ed. Secundaria 
##                                             536 
##                              Educació especfial 
##                                               1 
##                                            EEMM 
##                                               1 
##                           Enseñanzas artísticas 
##                                               1 
##                Enseñanzas Artísticas Superiores 
##                                               2 
## enseñanzas artísticas. artes plásticas y diseño 
##                                               1 
##                                equipo directivo 
##                                               1 
##                                    ESO, FP, ESA 
##                                               1 
##                                        ESO, FPB 
##                                               1 
##                                             IFE 
##                                               1 
##                                        Logopeda 
##                                               1 
##                                      maestra PT 
##                                               1 
##                                           Otros 
##                                             149 
##                           Pedagogia terapeutica 
##                                               1 
##                           Pedagogía Terapéutica 
##                                               1 
##                                           Todas 
##                                               1 
##                                     Universidad 
##                                               1
# Modelo de regresión ordinal (proportional odds)
mod_ord <- polr(con_propio_ord ~ formacion + exp_tramo + regimen + ambito + contexto,
                data = df_mod, Hess = TRUE)

# summary() devuelve una tabla con betas Y umbrales (zetas) juntos.
# Los betas son los primeros n = length(mod_ord$coefficients) filas.
sum_ord   <- summary(mod_ord)$coefficients        # matriz: betas + zetas
n_beta    <- length(mod_ord$coefficients)         # número de coeficientes de regresión
beta_tab  <- sum_ord[seq_len(n_beta), , drop = FALSE]  # solo filas de betas

coefs    <- beta_tab[, "Value"]
coef_se  <- beta_tab[, "Std. Error"]
z_val    <- qnorm(0.975)
ci_lower <- coefs - z_val * coef_se
ci_upper <- coefs + z_val * coef_se
z_scores <- coefs / coef_se
p_vals   <- 2 * pnorm(abs(z_scores), lower.tail = FALSE)

# Tabla en escala OR
tabla_ord <- tibble(
  Predictor  = names(coefs),
  OR         = round(exp(coefs),  3),
  IC_inf     = round(exp(ci_lower), 3),
  IC_sup     = round(exp(ci_upper), 3),
  z          = round(z_scores, 2),
  p.value    = round(p_vals, 4),
  Sig        = dplyr::case_when(
                 p_vals < .001 ~ "***",
                 p_vals < .01  ~ "**",
                 p_vals < .05  ~ "*",
                 TRUE          ~ ""
               )
)

tabla_ord %>%
  kable(caption = "Regresión ordinal — OR (IC 95% Wald)  |  OR > 1 = mayor probabilidad de mayor conocimiento EpJG") %>%
  kable_styling(bootstrap_options = c("striped","hover"), full_width = FALSE) %>%
  column_spec(7, bold = TRUE, color = azul1)
Regresión ordinal — OR (IC 95% Wald) | OR > 1 = mayor probabilidad de mayor conocimiento EpJG
Predictor OR IC_inf IC_sup z p.value Sig
formacionMáster/Postgrado 8.460000e-01 0.651 1.098000e+00 -1.26 0.2083
formacionDoctorado 7.320000e-01 0.389 1.377000e+00 -0.97 0.3335
exp_tramo.L 1.203000e+00 0.883 1.639000e+00 1.17 0.2406
exp_tramo.Q 9.590000e-01 0.729 1.261000e+00 -0.30 0.7621
exp_tramo.C 9.290000e-01 0.730 1.183000e+00 -0.60 0.5505
regimenConcertado/Privado 2.031000e+00 1.261 3.270000e+00 2.92 0.0035 **
ambitoCap d’estudis 2.178232e+14 0.000 3.363079e+188 0.16 0.8718
ambitoCFA 3.967282e+08 0.000 4.076963e+21 1.30 0.1953
ambitoCicle for.grau mitja de decoració ceràmica 9.887839e+07 0.000 1.018857e+21 1.20 0.2285
ambitoCooperación 1.968072e+09 0.000 2.088416e+22 1.40 0.1620
ambitoDirección pedagógica 4.845300e+07 0.000 5.007219e+20 1.16 0.2471
ambitoEd. Infantil 1.017205e+08 0.000 9.237866e+20 1.21 0.2258
ambitoEd. Primaria 1.327437e+08 0.000 1.203355e+21 1.23 0.2192
ambitoEd. Secundaria 1.310258e+08 0.000 1.187064e+21 1.23 0.2195
ambitoEducació especfial 4.770000e-01 0.464 4.910000e-01 -50.19 0.0000 ***
ambitoEEMM 1.239000e+00 1.210 1.269000e+00 17.64 0.0000 ***
ambitoEnseñanzas artísticas 1.318000e+00 1.289 1.347000e+00 24.64 0.0000 ***
ambitoEnseñanzas Artísticas Superiores 3.938812e+07 0.000 3.915472e+20 1.15 0.2521
ambitoenseñanzas artísticas. artes plásticas y diseño 1.148000e+00 1.116 1.181000e+00 9.63 0.0000 ***
ambitoequipo directivo 2.784981e+08 0.000 2.862256e+21 1.27 0.2034
ambitoESO, FP, ESA 4.189151e+08 0.000 4.304571e+21 1.30 0.1940
ambitoESO, FPB 1.044050e+08 0.000 1.075619e+21 1.21 0.2271
ambitoIFE 9.887839e+07 0.000 1.018857e+21 1.20 0.2285
ambitoLogopeda 9.750000e-01 0.951 9.990000e-01 -2.00 0.0451
ambitomaestra PT 1.546509e+09 0.000 1.641435e+22 1.38 0.1668
ambitoOtros 1.208944e+08 0.000 1.096240e+21 1.22 0.2215
ambitoPedagogia terapeutica 1.759259e+09 0.000 1.867517e+22 1.39 0.1642
ambitoPedagogía Terapéutica 3.293303e+08 0.000 3.387827e+21 1.28 0.1995
ambitoTodas 4.189151e+08 0.000 4.304571e+21 1.30 0.1940
ambitoUniversidad 1.810249e+14 0.000 3.617602e+188 0.16 0.8726
contextoEspaña (resto) 9.470000e-01 0.749 1.197000e+00 -0.45 0.6494
# Nota metodológica: en regresión ordinal estimada por máxima verosimilitud (ML)
# no se asume normalidad de residuos. La bondad de ajuste se evalúa con el
# pseudo-R² de McFadden y la comparación con el modelo nulo.
null_ord   <- polr(con_propio_ord ~ 1, data = df_mod, Hess = TRUE)
r2_mcfad   <- round(1 - as.numeric(logLik(mod_ord)) / as.numeric(logLik(null_ord)), 3)
chi2_lrt   <- round(2 * (as.numeric(logLik(mod_ord)) - as.numeric(logLik(null_ord))), 2)
df_lrt     <- length(coef(mod_ord)) - length(coef(null_ord))
p_lrt      <- round(pchisq(chi2_lrt, df = df_lrt, lower.tail = FALSE), 4)

cat(sprintf(
  "\nBondad de ajuste (LRT vs. modelo nulo):\n  χ²(%d) = %.2f, p = %.4f\n  Pseudo-R² McFadden = %.3f\n",
  df_lrt, chi2_lrt, p_lrt, r2_mcfad
))
## 
## Bondad de ajuste (LRT vs. modelo nulo):
##   χ²(31) = 57.36, p = 0.0027
##   Pseudo-R² McFadden = 0.020

11.4 L4 — Apoyo a movimientos sociales y práctica docente

Hipótesis: un mayor apoyo a los movimientos sociales se asocia positivamente con (a) trabajar temáticas EpJG en el aula y (b) mayor conocimiento de la EpJG. Se usan correlaciones de Spearman (robustas a no normalidad) y regresión logística binaria.

# Índice compuesto de práctica docente: nº de temáticas trabajadas
df_l4 <- df %>%
  mutate(
    n_trab = rowSums(across(starts_with("trab_"),
                            ~ case_when(.x == "SÍ" ~ 1, .x == "NO" ~ 0, TRUE ~ NA_real_)),
                     na.rm = TRUE),
    across(all_of(movs), as.numeric)
  ) %>%
  filter(!is.na(con_propio))

# Matriz de correlaciones Spearman: movimientos × EpJG
vars_cor <- c(movs, "con_propio","n_trab")
cor_mat  <- df_l4 %>%
  dplyr::select(all_of(vars_cor)) %>%
  dplyr::mutate(across(everything(), as.numeric)) %>%
  cor(method = "spearman", use = "pairwise.complete.obs")

colnames(cor_mat) <- rownames(cor_mat) <-
  c(lab_movs, "Conoc. EpJG", "Nº temáticas trabajadas")

ggcorrplot(cor_mat, method = "square", type = "lower",
           lab = TRUE, lab_size = 3,
           colors = c(azul6, "white", azul1),
           tl.cex = 9, tl.srt = 45) +
  labs(title = "Correlaciones Spearman: apoyo a movimientos vs. práctica EpJG") +
  tema_epjg + theme(axis.text.x = element_text(angle = 45, hjust = 1))

# Variable dependiente binaria: trabaja ≥ 5 temáticas
df_l4 <- df_l4 %>%
  mutate(
    practica_alta = factor(ifelse(n_trab >= 5, 1, 0), levels = c(0,1),
                           labels = c("Baja (< 5 temáticas)", "Alta (≥ 5 temáticas)")),
    indice_movs = rowMeans(across(all_of(movs), as.numeric), na.rm = TRUE)
  )

mod_log <- glm(practica_alta ~ indice_movs + con_propio + formacion + experiencia + contexto,
               data = df_l4 %>%
                        mutate(formacion = factor(formacion,
                                 c("Grado/Licenciatura","Máster/Postgrado","Doctorado")),
                               experiencia = as.numeric(experiencia),
                               contexto = factor(contexto, c("Cataluña","España (resto)"))),
               family = binomial(link = "logit"))

tidy(mod_log, conf.int = TRUE, exponentiate = TRUE) %>%
  mutate(across(c(estimate, conf.low, conf.high, p.value), ~ round(.x, 3)),
         Sig = case_when(p.value < .001 ~ "***",
                         p.value < .01  ~ "**",
                         p.value < .05  ~ "*",
                         TRUE           ~ "")) %>%
  dplyr::select(term, OR = estimate, IC_inf = conf.low, IC_sup = conf.high, p.value, Sig) %>%
  kable(caption = "Regresión logística binaria: predictores de alta práctica EpJG (≥ 5 temáticas)") %>%
  kable_styling(bootstrap_options = c("striped","hover"), full_width = FALSE) %>%
  column_spec(6, bold = TRUE, color = azul1)
Regresión logística binaria: predictores de alta práctica EpJG (≥ 5 temáticas)
term OR IC_inf IC_sup p.value Sig
(Intercept) 0.240 0.081 0.716 0.010
indice_movs 1.375 1.098 1.714 0.005 **
con_propio 1.924 1.602 2.335 0.000 ***
formacionMáster/Postgrado 0.898 0.609 1.326 0.589
formacionDoctorado 0.440 0.206 0.986 0.039
experiencia 1.121 1.018 1.238 0.022
contextoEspaña (resto) 0.991 0.699 1.408 0.961
cat(sprintf("\nPseudo R² de Nagelkerke: %.3f\n",
            1 - (logLik(mod_log) / logLik(update(mod_log, ~1)))^(2/nobs(mod_log))))
## 
## Pseudo R² de Nagelkerke: 0.000

11.5 L5 — Perfiles docentes latentes (análisis de clúster)

Hipótesis: existen perfiles diferenciados de docentes según su conocimiento, interés y práctica con la EpJG. Se usa k-medoides (PAM) robusto a outliers; el número óptimo de clústeres se determina con el método de la silueta.

# Variables para el clúster: conocimiento EpJG global, interés global, práctica, apoyo movimientos
df_cl <- df %>%
  mutate(
    conoc_medio = rowMeans(across(all_of(paste0("conoc_", temas_cod)), as.numeric), na.rm=TRUE),
    int_medio   = rowMeans(across(all_of(paste0("int_",   temas_cod)), as.numeric), na.rm=TRUE),
    movs_medio  = rowMeans(across(all_of(movs), as.numeric), na.rm=TRUE),
    n_trab      = rowSums(across(starts_with("trab_"),
                                 ~ case_when(.x=="SÍ"~1,.x=="NO"~0,TRUE~NA_real_)),na.rm=TRUE)
  ) %>%
  dplyr::select(contexto, con_propio, con_centro, importancia,
                conoc_medio, int_medio, movs_medio, n_trab) %>%
  drop_na()

mat_cl <- df_cl %>%
  dplyr::select(-contexto) %>%
  dplyr::mutate(across(everything(), as.numeric)) %>%
  scale()
# Número óptimo de clústeres (silueta, k = 2–6)
fviz_nbclust(mat_cl, pam, method = "silhouette", k.max = 6) +
  labs(title = "Número óptimo de clústeres (método de la silueta)",
       subtitle = "k-medoides (PAM)") +
  tema_epjg

set.seed(42)
k_opt <- 3   # ajusta según el gráfico anterior
pam_res <- pam(mat_cl, k = k_opt, metric = "euclidean")

df_cl$cluster <- factor(paste0("Perfil ", pam_res$clustering))

# Caracterización de los clústeres
perfil_stats <- df_cl %>%
  group_by(cluster) %>%
  summarise(
    n            = n(),
    Conoc_EpJG   = round(mean(con_propio, na.rm=TRUE), 2),
    Imp_EpJG     = round(mean(importancia, na.rm=TRUE), 2),
    Conoc_temas  = round(mean(conoc_medio, na.rm=TRUE), 2),
    Int_form     = round(mean(int_medio, na.rm=TRUE), 2),
    Apoyo_movs   = round(mean(movs_medio, na.rm=TRUE), 2),
    N_trab       = round(mean(n_trab, na.rm=TRUE), 2)
  )

perfil_stats %>%
  kable(caption = "Caracterización de los perfiles docentes latentes (k-medoides)") %>%
  kable_styling(bootstrap_options = c("striped","hover"), full_width = FALSE) %>%
  column_spec(1, bold = TRUE, color = azul1)
Caracterización de los perfiles docentes latentes (k-medoides)
cluster n Conoc_EpJG Imp_EpJG Conoc_temas Int_form Apoyo_movs N_trab
Perfil 1 280 3.68 4.42 4.04 3.99 4.63 8.18
Perfil 2 262 1.70 2.74 3.10 2.69 3.74 5.03
Perfil 3 439 1.86 4.02 3.59 3.96 4.68 6.96
# Visualización 2D
fviz_cluster(pam_res, data = mat_cl,
             palette = c(azul1, azul3, azul5),
             ellipse.type = "convex",
             ggtheme = tema_epjg,
             main = "Perfiles docentes latentes (PAM, proyección PCA)")

# ¿La pertenencia al clúster varía según el contexto?
tab_cl_ctx <- df_cl %>%
  count(cluster, contexto) %>%
  group_by(cluster) %>% mutate(prop = percent(n / sum(n), 1))

tab_cl_ctx %>%
  pivot_wider(names_from = contexto, values_from = c(n, prop)) %>%
  kable(caption = "Distribución de perfiles por contexto") %>%
  kable_styling(bootstrap_options = c("striped","hover"), full_width = FALSE)
Distribución de perfiles por contexto
cluster n_Cataluña n_España (resto) prop_Cataluña prop_España (resto)
Perfil 1 147 133 52% 48%
Perfil 2 156 106 60% 40%
Perfil 3 212 227 48% 52%
# Chi-cuadrado: ¿hay asociación entre perfil y contexto?
chisq_res <- chisq.test(table(df_cl$cluster, df_cl$contexto))
cat(sprintf("Chi² = %.2f, gl = %d, p = %.4f\n",
            chisq_res$statistic, chisq_res$parameter, chisq_res$p.value))
## Chi² = 8.33, gl = 2, p = 0.0155