1 Introducción

Este documento presenta el análisis estadístico completo de la encuesta aplicada a estudiantes de la Facultad de Ciencias Exactas y Naturales de la Universidad Surcolombiana, sede Neiva. El objetivo es analizar las tendencias de pensamiento sobre el potencial científico y la aplicabilidad de la energía nuclear, y correlacionarlas con variables socioculturales y formativas.

Pregunta de investigación: ¿En qué medida las variables socioculturales y formativas predicen las tendencias de pensamiento sobre la energía nuclear y su potencial científico en los estudiantes de la Facultad de Ciencias Exactas y Naturales de la Universidad Surcolombiana, sede Neiva?


2 Carga de librerías y datos

# Instalar paquetes si no están disponibles
paquetes <- c("readxl", "dplyr", "ggplot2", "psych", "car", "knitr",
              "kableExtra", "tidyr", "scales", "ggpubr", "rstatix",
              "corrplot", "likert", "nnet", "lm.beta", "moments")

instalar <- paquetes[!paquetes %in% installed.packages()[,"Package"]]
if (length(instalar) > 0) install.packages(instalar, repos = "https://cran.r-project.org")

suppressPackageStartupMessages({
  library(readxl)
  library(dplyr)
  library(ggplot2)
  library(psych)
  library(car)
  library(knitr)
  library(kableExtra)
  library(tidyr)
  library(scales)
  library(ggpubr)
  library(rstatix)
  library(corrplot)
  library(moments)
})
# ── Carga del archivo ──────────────────────────────────────────────────────────
# INSTRUCCIÓN RÁPIDA:
#   1. Pon el .Rmd y el .xlsx en la misma carpeta.
#   2. En RStudio: Session > Set Working Directory > To Source File Location
#   3. Haz clic en Knit.
#
# Si prefieres indicar la ruta manualmente, edita la siguiente línea:
ruta_manual <- ""
# Ejemplo Windows : ruta_manual <- "C:/Users/Ana/Escritorio/Cuestionario_final__respuestas.xlsx"
# Ejemplo Mac/Linux: ruta_manual <- "/Users/ana/Escritorio/Cuestionario_final__respuestas.xlsx"

nombre_xlsx <- "Cuestionario_final__respuestas.xlsx"

ruta_excel <- if (nchar(trimws(ruta_manual)) > 0) ruta_manual else nombre_xlsx

if (!file.exists(ruta_excel)) {
  # Intento extra: buscar en carpetas comunes de Windows/Mac
  posibles <- c(
    file.path(Sys.getenv("USERPROFILE"), "Desktop", nombre_xlsx),
    file.path(Sys.getenv("HOME"), "Desktop", nombre_xlsx),
    file.path(Sys.getenv("USERPROFILE"), "Escritorio", nombre_xlsx),
    file.path(Sys.getenv("HOME"), "Escritorio", nombre_xlsx),
    file.path(Sys.getenv("USERPROFILE"), "Downloads", nombre_xlsx),
    file.path(Sys.getenv("HOME"), "Downloads", nombre_xlsx)
  )
  encontrado <- posibles[file.exists(posibles)]
  if (length(encontrado) > 0) {
    ruta_excel <- encontrado[1]
    cat("Archivo encontrado automáticamente en:", ruta_excel, "\n")
  } else {
    stop(paste0(
      "\n\nNo se encontró '", nombre_xlsx, "'.\n",
      "SOLUCIÓN DIRECTA: edita la línea ruta_manual en este chunk.\n",
      "Ejemplo: ruta_manual <- \"C:/Users/User/Desktop/proyecto/",
      nombre_xlsx, "\"\n",
      "Directorio actual: ", normalizePath(getwd()), "\n"
    ))
  }
}

cat("Archivo cargado desde:", normalizePath(ruta_excel), "\n")
## Archivo cargado desde: C:\Users\User\Desktop\Cuestionario_final__respuestas.xlsx
datos_raw <- read_excel(ruta_excel, sheet = 1)

# ── Nombres cortos de columnas ─────────────────────────────────────────────────
nombres_nuevos <- c(
  "timestamp", "edad", "semestre", "programa", "sexo",
  paste0("P", 1:20),
  "texto_conocimiento", "texto_beneficios_riesgos",
  "texto_fuentes", "texto_eleccion", "texto_formacion"
)
colnames(datos_raw) <- nombres_nuevos

# ── Conversión Likert: extraer número inicial ──────────────────────────────────
convertir_likert <- function(x) {
  as.integer(sub("^(\\d+).*", "\\1", trimws(as.character(x))))
}

datos <- datos_raw %>%
  mutate(across(P1:P20, convertir_likert)) %>%
  filter(rowSums(is.na(select(., P1:P20))) < 10)  # elimina filas casi vacías

# ── Variables categóricas limpias ─────────────────────────────────────────────
datos <- datos %>%
  mutate(
    programa = factor(trimws(programa),
                      levels = c("Biología", "Física", "Matemática Aplicada")),
    sexo     = factor(trimws(sexo),
                      levels = c("Femenino", "Masculino")),
    edad     = factor(trimws(edad),
                      levels = c("Menos de 18", "18 – 22", "23 – 27",
                                 "28 – 32", "Más de 32"))
  )

# ── Dimensiones teóricas ──────────────────────────────────────────────────────
# D1 Conocimiento/conciencia (P1-P4)
# D2 Percepción de riesgos   (P5, P7, P9)
# D3 Actitud favorable        (P6, P10, P11, P12, P13, P14)
# D4 Influencia mediática/formativa (P15, P16, P17)
# D5 Comparación de riesgos  (P18, P19, P20)
# P8 puede ir en D2 o D5 (es inversa en D2)

datos <- datos %>%
  rowwise() %>%
  mutate(
    D1_conocimiento = mean(c(P1, P2, P3, P4),       na.rm = TRUE),
    D2_riesgo       = mean(c(P5, P7, P9),            na.rm = TRUE),
    D3_actitud      = mean(c(P6, P10, P11, P12, P13, P14), na.rm = TRUE),
    D4_influencia   = mean(c(P15, P16, P17),         na.rm = TRUE),
    D5_comparacion  = mean(c(P18, P19, P20),         na.rm = TRUE),
    puntaje_total   = mean(c_across(P1:P20),          na.rm = TRUE)
  ) %>%
  ungroup()

cat("Dimensiones del dataset final:", nrow(datos), "observaciones,",
    ncol(datos), "variables.\n")
## Dimensiones del dataset final: 234 observaciones, 36 variables.

3 Diseño muestral

# ── Parámetros de diseño ───────────────────────────────────────────────────────
poblacion_total  <- 596
n_total          <- 234
n_biologia       <- 136
n_fisica         <- 46
n_matematica     <- 52

tabla_muestra <- data.frame(
  Programa            = c("Biología", "Física", "Matemática Aplicada", "TOTAL"),
  Población_N         = c(round(poblacion_total * 136/234),
                          round(poblacion_total * 46/234),
                          round(poblacion_total * 52/234),
                          poblacion_total),
  Muestra_n           = c(n_biologia, n_fisica, n_matematica, n_total),
  Fracción_muestreo   = c(
    round(n_biologia / round(poblacion_total*136/234), 3),
    round(n_fisica   / round(poblacion_total*46/234),  3),
    round(n_matematica / round(poblacion_total*52/234), 3),
    round(n_total / poblacion_total, 3)
  )
)

kable(tabla_muestra,
      caption = "Tabla 1. Diseño muestral estratificado proporcional",
      align = "lrrr") %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
                full_width = FALSE) %>%
  row_spec(4, bold = TRUE, background = "#d4e6f1")
Tabla 1. Diseño muestral estratificado proporcional
Programa Población_N Muestra_n Fracción_muestreo
Biología 346 136 0.393
Física 117 46 0.393
Matemática Aplicada 132 52 0.394
TOTAL 596 234 0.393

Método: Muestreo aleatorio simple por estratos proporcionales (programa académico). Nivel de confianza: 95 %, margen de error estimado: ±5 %.


4 Estadísticas descriptivas

4.1 Perfil sociodemográfico

# Distribución por programa
tab_prog <- datos %>% count(programa) %>%
  mutate(Porcentaje = round(n/sum(n)*100, 1))
kable(tab_prog, col.names = c("Programa", "n", "%"),
      caption = "Tabla 2. Distribución por programa académico") %>%
  kable_styling(bootstrap_options = "striped", full_width = FALSE)
Tabla 2. Distribución por programa académico
Programa n %
Biología 136 58.1
Física 46 19.7
Matemática Aplicada 52 22.2
# Distribución por sexo
tab_sexo <- datos %>% count(sexo) %>%
  mutate(Porcentaje = round(n/sum(n)*100, 1))
kable(tab_sexo, col.names = c("Sexo", "n", "%"),
      caption = "Tabla 3. Distribución por sexo") %>%
  kable_styling(bootstrap_options = "striped", full_width = FALSE)
Tabla 3. Distribución por sexo
Sexo n %
Femenino 114 48.7
Masculino 120 51.3
# Distribución por edad
tab_edad <- datos %>% count(edad) %>%
  mutate(Porcentaje = round(n/sum(n)*100, 1))
kable(tab_edad, col.names = c("Rango de edad", "n", "%"),
      caption = "Tabla 4. Distribución por rango de edad") %>%
  kable_styling(bootstrap_options = "striped", full_width = FALSE)
Tabla 4. Distribución por rango de edad
Rango de edad n %
Menos de 18 28 12.0
18 – 22 140 59.8
23 – 27 47 20.1
28 – 32 14 6.0
Más de 32 5 2.1

📊 Interpretación del perfil sociodemográfico: La distribución por programa replica el diseño estratificado; Biología concentra la mayor proporción de estudiantes. Por sexo, la muestra está casi equilibrada (masculino ≈ 51 %, femenino ≈ 49 %), lo que permite comparaciones sin sesgo de género. Por edad, el grupo predominante es el de 18–22 años (≈ 60 %), coherente con la población universitaria de pregrado; la presencia minoritaria de estudiantes mayores de 27 años puede reflejar trayectorias académicas no lineales y podría introducir mayor madurez reflexiva sobre temas científicos.

g1 <- ggplot(datos, aes(x = programa, fill = programa)) +
  geom_bar(color = "white") +
  geom_text(stat = "count", aes(label = ..count..), vjust = -0.4, size = 3.5) +
  scale_fill_manual(values = c("#2196F3", "#FF5722", "#4CAF50")) +
  labs(title = "Distribución por programa", x = NULL, y = "Frecuencia") +
  theme_minimal(base_size = 11) + theme(legend.position = "none")

g2 <- ggplot(datos, aes(x = sexo, fill = sexo)) +
  geom_bar(color = "white") +
  geom_text(stat = "count", aes(label = ..count..), vjust = -0.4, size = 3.5) +
  scale_fill_manual(values = c("#E91E63", "#3F51B5")) +
  labs(title = "Distribución por sexo", x = NULL, y = "Frecuencia") +
  theme_minimal(base_size = 11) + theme(legend.position = "none")

g3 <- ggplot(datos, aes(x = edad, fill = edad)) +
  geom_bar(color = "white") +
  geom_text(stat = "count", aes(label = ..count..), vjust = -0.4, size = 3.5) +
  scale_fill_brewer(palette = "Set2") +
  labs(title = "Distribución por edad", x = NULL, y = "Frecuencia") +
  theme_minimal(base_size = 11) + theme(legend.position = "none",
                                        axis.text.x = element_text(angle = 20, hjust = 1))

ggpubr::ggarrange(g1, g2, g3, ncol = 3)

4.2 Estadísticos descriptivos de ítems Likert

items <- datos %>% select(P1:P20)

desc <- data.frame(
  Ítem  = paste0("P", 1:20),
  n     = colSums(!is.na(items)),
  Media = round(colMeans(items, na.rm = TRUE), 2),
  DE    = round(apply(items, 2, sd, na.rm = TRUE), 2),
  Mín   = apply(items, 2, min, na.rm = TRUE),
  Mediana = apply(items, 2, median, na.rm = TRUE),
  Máx   = apply(items, 2, max, na.rm = TRUE),
  Asimetría = round(apply(items, 2, skewness, na.rm = TRUE), 2)
)

kable(desc, caption = "Tabla 5. Estadísticos descriptivos de los 20 ítems Likert (1–5)",
      row.names = FALSE) %>%
  kable_styling(bootstrap_options = c("striped", "hover", "condensed"),
                full_width = FALSE, font_size = 11) %>%
  column_spec(3, bold = TRUE)
Tabla 5. Estadísticos descriptivos de los 20 ítems Likert (1–5)
Ítem n Media DE Mín Mediana Máx Asimetría
P1 234 3.36 1.15 1 3.0 5 -0.44
P2 234 3.64 1.18 1 4.0 5 -0.64
P3 234 3.36 1.23 1 3.0 5 -0.31
P4 234 3.53 1.26 1 4.0 5 -0.51
P5 234 3.28 1.29 1 3.0 5 -0.32
P6 234 3.47 1.07 1 3.0 5 -0.34
P7 234 3.57 1.22 1 4.0 5 -0.57
P8 234 3.34 1.23 1 3.0 5 -0.31
P9 234 3.26 1.20 1 3.0 5 -0.32
P10 234 3.69 1.14 1 4.0 5 -0.62
P11 234 3.56 1.22 1 4.0 5 -0.54
P12 234 3.59 1.17 1 4.0 5 -0.63
P13 234 3.38 1.17 1 3.0 5 -0.32
P14 234 3.48 1.22 1 3.5 5 -0.45
P15 234 2.95 1.19 1 3.0 5 0.01
P16 234 2.99 1.17 1 3.0 5 -0.10
P17 234 3.03 1.24 1 3.0 5 -0.06
P18 234 3.33 1.14 1 3.0 5 -0.35
P19 234 3.22 1.13 1 3.0 5 -0.19
P20 234 3.01 1.14 1 3.0 5 -0.09

📊 Interpretación de la tabla descriptiva: Los ítems con media > 3.5 indican tendencia de acuerdo; los que tienen media < 2.5 indican desacuerdo predominante. Presta atención a la desviación estándar (DE): valores DE > 1.2 señalan alta dispersión, es decir, opiniones muy divididas dentro de la muestra — esto es relevante para el objetivo 1 (identificar tendencias). Los ítems con asimetría negativa fuerte (< −0.5) muestran que la mayoría se concentra en respuestas altas.

desc_long <- desc %>%
  mutate(Etiqueta = c(
    "P1: Conozco qué es la E.N.", "P2: Aplicaciones médicas",
    "P3: Sin emisiones CO₂", "P4: Uranio como combustible",
    "P5: Riesgo alto para salud/MA", "P6: Beneficiosa en salud",
    "P7: Residuos mayor inconveniente", "P8: Contamina menos que conv.",
    "P9: Riesgo de accidentes alto", "P10: Favorece desarrollo tecnológico",
    "P11: Apoyaría su uso en Colombia", "P12: Alternativa al petróleo",
    "P13: Sostenibilidad ambiental", "P14: Civil ≠ militar",
    "P15: Medios influyen en mi opinión", "P16: Confío en regulación estatal",
    "P17: Programa me informó objetivamente", "P18: Aire > riesgo que plantas",
    "P19: Tráfico/calor > reactores", "P20: Residuos < pesticidas"
  ))

ggplot(desc_long, aes(x = reorder(Etiqueta, Media), y = Media, fill = Media)) +
  geom_col(color = "white") +
  geom_errorbar(aes(ymin = Media - DE, ymax = Media + DE), width = 0.3, alpha = 0.6) +
  coord_flip() +
  scale_fill_gradient2(low = "#f44336", mid = "#FFC107", high = "#4CAF50",
                       midpoint = 3, name = "Media") +
  geom_hline(yintercept = 3, linetype = "dashed", color = "gray40") +
  labs(title = "Media ± DE por ítem Likert",
       subtitle = "Línea punteada = punto neutro (3)",
       x = NULL, y = "Puntaje promedio (1–5)") +
  scale_y_continuous(limits = c(0, 6)) +
  theme_minimal(base_size = 10)

4.3 Estadísticos descriptivos de dimensiones

📊 Interpretación del gráfico de medias: Las barras con colores cálidos (rojo/naranja) corresponden a ítems donde los estudiantes tienden al desacuerdo o incertidumbre; las barras verdes reflejan acuerdo. La línea punteada en 3.0 es el punto neutro. Si la mayoría de ítems de una dimensión superan ese umbral, la tendencia general de la facultad es favorable hacia esa dimensión de la energía nuclear.

dims <- datos %>% select(D1_conocimiento, D2_riesgo, D3_actitud, D4_influencia,
                          D5_comparacion, puntaje_total)

desc_dim <- data.frame(
  Dimensión = c("D1 Conocimiento/Conciencia",
                "D2 Percepción de Riesgo",
                "D3 Actitud Favorable",
                "D4 Influencia Mediática/Formativa",
                "D5 Comparación de Riesgos",
                "Puntaje Total"),
  n       = colSums(!is.na(dims)),
  Media   = round(colMeans(dims, na.rm = TRUE), 2),
  DE      = round(apply(dims, 2, sd, na.rm = TRUE), 2),
  Mín     = round(apply(dims, 2, min, na.rm = TRUE), 2),
  Mediana = round(apply(dims, 2, median, na.rm = TRUE), 2),
  Máx     = round(apply(dims, 2, max, na.rm = TRUE), 2)
)

kable(desc_dim, caption = "Tabla 6. Estadísticos descriptivos por dimensión",
      row.names = FALSE) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE) %>%
  row_spec(6, bold = TRUE, background = "#eaf4fb")
Tabla 6. Estadísticos descriptivos por dimensión
Dimensión n Media DE Mín Mediana Máx
D1 Conocimiento/Conciencia 234 3.47 0.99 1 3.50 5
D2 Percepción de Riesgo 234 3.37 0.98 1 3.33 5
D3 Actitud Favorable 234 3.53 1.00 1 3.67 5
D4 Influencia Mediática/Formativa 234 2.99 0.89 1 3.00 5
D5 Comparación de Riesgos 234 3.19 0.98 1 3.17 5
Puntaje Total 234 3.35 0.79 1 3.45 5

📊 Interpretación por dimensiones: Compara las medias de cada dimensión con el punto neutro (3.0): - D1 Conocimiento > 3 → los estudiantes reconocen aspectos científicos básicos de la energía nuclear. - D2 Riesgo > 3 → perciben los riesgos como altos — actitud de precaución predominante. - D3 Actitud > 3 → tendencia favorable hacia aplicaciones y potencial de la energía nuclear. - D4 Influencia > 3 → los medios y la formación académica sí moldean su opinión. - D5 Comparación → evalúa si relativizan el riesgo nuclear frente a otros riesgos cotidianos.

Una D3 alta con D2 también alta es un hallazgo clave: significa que los estudiantes reconocen el potencial de la energía nuclear a pesar de percibirla como riesgosa — ambivalencia actitudinal frecuente en este tipo de estudios.


5 Validación del instrumento — Alfa de Cronbach

# ── Alfa global ────────────────────────────────────────────────────────────────
alfa_global <- psych::alpha(items, na.rm = TRUE)

cat("=== ALFA DE CRONBACH — ESCALA COMPLETA (P1–P20) ===\n")
## === ALFA DE CRONBACH — ESCALA COMPLETA (P1–P20) ===
cat(sprintf("  α = %.3f\n", alfa_global$total$raw_alpha))
##   α = 0.934
cat(sprintf("  α estandarizado = %.3f\n", alfa_global$total$std.alpha))
##   α estandarizado = 0.935
cat(sprintf("  Correlación media inter-ítems = %.3f\n",
            alfa_global$total$average_r))
##   Correlación media inter-ítems = 0.418
cat(sprintf("  IC 95%%: [%.3f, %.3f]\n\n",
            alfa_global$total$raw_alpha - 1.96 * alfa_global$total$ase,
            alfa_global$total$raw_alpha + 1.96 * alfa_global$total$ase))
##   IC 95%: [0.922, 0.946]
# ── Interpretación ─────────────────────────────────────────────────────────────
alpha_val <- alfa_global$total$raw_alpha
interpretacion <- dplyr::case_when(
  alpha_val >= 0.90 ~ "Excelente (≥ 0.90)",
  alpha_val >= 0.80 ~ "Bueno (0.80–0.89)",
  alpha_val >= 0.70 ~ "Aceptable (0.70–0.79)",
  alpha_val >= 0.60 ~ "Cuestionable (0.60–0.69)",
  alpha_val >= 0.50 ~ "Deficiente (0.50–0.59)",
  TRUE              ~ "Inaceptable (< 0.50)"
)
cat(sprintf("  Interpretación: %s\n\n", interpretacion))
##   Interpretación: Excelente (≥ 0.90)
# ── Alfa por dimensión ─────────────────────────────────────────────────────────
alfa_dim <- list(
  D1_Conocimiento = psych::alpha(datos %>% select(P1:P4),        na.rm = TRUE),
  D2_Riesgo       = psych::alpha(datos %>% select(P5, P7, P9),   na.rm = TRUE),
  D3_Actitud      = psych::alpha(datos %>% select(P6, P10, P11, P12, P13, P14),
                                  na.rm = TRUE),
  D4_Influencia   = psych::alpha(datos %>% select(P15, P16, P17), na.rm = TRUE),
  D5_Comparacion  = psych::alpha(datos %>% select(P18, P19, P20), na.rm = TRUE)
)

tabla_alfa <- data.frame(
  Dimensión = c("D1 Conocimiento (P1–P4)",
                "D2 Percepción de riesgo (P5, P7, P9)",
                "D3 Actitud favorable (P6, P10–P14)",
                "D4 Influencia mediática (P15–P17)",
                "D5 Comparación de riesgos (P18–P20)",
                "Escala completa (P1–P20)"),
  Ítems = c(4, 3, 6, 3, 3, 20),
  Alpha = round(c(
    alfa_dim$D1_Conocimiento$total$raw_alpha,
    alfa_dim$D2_Riesgo$total$raw_alpha,
    alfa_dim$D3_Actitud$total$raw_alpha,
    alfa_dim$D4_Influencia$total$raw_alpha,
    alfa_dim$D5_Comparacion$total$raw_alpha,
    alfa_global$total$raw_alpha
  ), 3),
  Interpretacion = c(
    ifelse(alfa_dim$D1_Conocimiento$total$raw_alpha >= 0.70, "Aceptable o superior", "Cuestionable"),
    ifelse(alfa_dim$D2_Riesgo$total$raw_alpha >= 0.70, "Aceptable o superior", "Cuestionable"),
    ifelse(alfa_dim$D3_Actitud$total$raw_alpha >= 0.70, "Aceptable o superior", "Cuestionable"),
    ifelse(alfa_dim$D4_Influencia$total$raw_alpha >= 0.70, "Aceptable o superior", "Cuestionable"),
    ifelse(alfa_dim$D5_Comparacion$total$raw_alpha >= 0.70, "Aceptable o superior", "Cuestionable"),
    interpretacion
  )
)

kable(tabla_alfa,
      caption = "Tabla 7. Coeficiente alfa de Cronbach por dimensión",
      col.names = c("Dimensión", "Ítems", "α de Cronbach", "Interpretación"),
      row.names = FALSE) %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE) %>%
  row_spec(6, bold = TRUE, background = "#d5f5e3")
Tabla 7. Coeficiente alfa de Cronbach por dimensión
Dimensión Ítems α de Cronbach Interpretación
D1 Conocimiento (P1–P4) 4 0.837 Aceptable o superior
D2 Percepción de riesgo (P5, P7, P9) 3 0.697 Cuestionable
D3 Actitud favorable (P6, P10–P14) 6 0.926 Aceptable o superior
D4 Influencia mediática (P15–P17) 3 0.587 Cuestionable
D5 Comparación de riesgos (P18–P20) 3 0.831 Aceptable o superior
Escala completa (P1–P20) 20 0.934 Excelente (≥ 0.90)

📊 Interpretación del Alfa de Cronbach: El alfa de Cronbach mide la consistencia interna del instrumento — qué tan bien miden los ítems el mismo constructo. Criterios de George & Mallery (2003):

α Interpretación
≥ 0.90 Excelente
0.80–0.89 Bueno
0.70–0.79 Aceptable ✓ mínimo recomendado
0.60–0.69 Cuestionable
< 0.60 Inaceptable

Si el α global ≥ 0.70, el instrumento es válido y confiable para los análisis siguientes. Para las dimensiones, valores por encima de 0.60 son aceptables dado que tienen pocos ítems (3–6). En la tabla de ítem-total, si eliminar un ítem aumenta mucho el α, considera reportarlo como ítem problemático en tu discusión.

# Correlaciones ítem-total corregidas
item_total <- round(alfa_global$item.stats[, c("r.cor", "r.drop")], 3)
colnames(item_total) <- c("r.cor corregida", "alpha si elimina item")
item_total$Item <- paste0("P", 1:20)
item_total <- item_total[, c("Item", "r.cor corregida", "alpha si elimina item")]

kable(item_total,
      caption = "Tabla 8. Estadísticos ítem-total (correlaciones y alfa si se elimina)",
      row.names = FALSE) %>%
  kable_styling(bootstrap_options = c("striped", "condensed"), full_width = FALSE)
Tabla 8. Estadísticos ítem-total (correlaciones y alfa si se elimina)
Item r.cor corregida alpha si elimina item
P1 0.698 0.674
P2 0.737 0.711
P3 0.701 0.673
P4 0.687 0.665
P5 0.327 0.295
P6 0.701 0.678
P7 0.587 0.564
P8 0.689 0.663
P9 0.491 0.465
P10 0.819 0.791
P11 0.788 0.752
P12 0.811 0.777
P13 0.772 0.739
P14 0.759 0.733
P15 0.347 0.327
P16 0.526 0.501
P17 0.530 0.508
P18 0.736 0.707
P19 0.729 0.696
P20 0.602 0.577

📊 Interpretación correlaciones ítem-total: Las correlaciones ítem-total corregidas (columna r.cor corregida) deben ser ≥ 0.30 para considerar que el ítem contribuye al constructo. Ítems con correlación < 0.20 son candidatos a revisión o eliminación. La columna alpha si elimina item te dice cuánto cambiaría la confiabilidad si quitaras ese ítem — si al eliminarlo el α sube notablemente, ese ítem es discordante con el resto de la escala.


6 Supuestos estadísticos

6.1 Prueba de normalidad (Shapiro-Wilk)

cat("=== PRUEBA DE NORMALIDAD (Shapiro-Wilk) ===\n\n")
## === PRUEBA DE NORMALIDAD (Shapiro-Wilk) ===
vars_test <- c("puntaje_total", "D1_conocimiento", "D2_riesgo",
               "D3_actitud", "D4_influencia", "D5_comparacion")

res_norm <- lapply(vars_test, function(v) {
  x  <- na.omit(datos[[v]])
  sw <- shapiro.test(x)
  data.frame(Variable = v,
             W        = round(sw$statistic, 4),
             p_valor  = round(sw$p.value, 4),
             Normal   = ifelse(sw$p.value > 0.05, "Sí (p > .05)", "No (p ≤ .05)"))
})

tab_norm <- do.call(rbind, res_norm)
kable(tab_norm, row.names = FALSE,
      caption = "Tabla 9. Pruebas de normalidad Shapiro-Wilk") %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)
Tabla 9. Pruebas de normalidad Shapiro-Wilk
Variable W p_valor Normal
puntaje_total 0.9437 0e+00 No (p ≤ .05)
D1_conocimiento 0.9514 0e+00 No (p ≤ .05)
D2_riesgo 0.9483 0e+00 No (p ≤ .05)
D3_actitud 0.9498 0e+00 No (p ≤ .05)
D4_influencia 0.9741 3e-04 No (p ≤ .05)
D5_comparacion 0.9681 0e+00 No (p ≤ .05)

📊 Interpretación Shapiro-Wilk: Si p > 0.05 → no se rechaza normalidad → se pueden usar pruebas paramétricas (ANOVA, t). Si p ≤ 0.05 → se viola el supuesto → usar pruebas no paramétricas (Kruskal-Wallis, Mann-Whitney). Con n = 234, el teorema del límite central garantiza que las medias son aproximadamente normales incluso si los datos individuales no lo son, por lo que el ANOVA sigue siendo robusto. En el documento se reportan ambas pruebas (paramétrica y no paramétrica) para mayor rigor.

par(mfrow = c(2, 3))
for (v in vars_test) {
  qqnorm(na.omit(datos[[v]]), main = paste("Q-Q:", v), pch = 19, cex = 0.6)
  qqline(na.omit(datos[[v]]), col = "firebrick", lwd = 2)
}

par(mfrow = c(1, 1))

📊 Interpretación gráficos Q-Q: Los puntos deben seguir la línea diagonal roja. Desviaciones en los extremos (colas) son comunes con datos Likert y no invalidan el análisis con n > 100. Si los puntos forman una “S”, indica distribución platicúrtica; si se separan en los extremos, indica colas pesadas.

6.2 Prueba de homogeneidad de varianzas (Levene)

cat("=== PRUEBA DE LEVENE — Homogeneidad de varianzas ===\n\n")
## === PRUEBA DE LEVENE — Homogeneidad de varianzas ===
lev_prog <- car::leveneTest(puntaje_total ~ programa, data = datos)
lev_sexo <- car::leveneTest(puntaje_total ~ sexo,     data = datos)

cat("Por programa:", "\n")
## Por programa:
print(lev_prog)
## Levene's Test for Homogeneity of Variance (center = median)
##        Df F value  Pr(>F)  
## group   2  3.6847 0.02659 *
##       231                  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
cat("\nPor sexo:\n")
## 
## Por sexo:
print(lev_sexo)
## Levene's Test for Homogeneity of Variance (center = median)
##        Df F value Pr(>F)
## group   1  0.0495 0.8242
##       232

📊 Interpretación Levene: Si p > 0.05 → varianzas homogéneas → ANOVA estándar es apropiado. Si p ≤ 0.05 → varianzas heterogéneas → usar Welch-ANOVA o pruebas no paramétricas. En la prueba t de sexo ya se usa var.equal = FALSE (t de Welch) como precaución.


7 Pruebas de hipótesis

7.1 H1: Diferencias en puntaje total según programa académico

H₀: Los puntajes medios de tendencia de pensamiento son iguales en los tres programas.
H₁: Al menos un programa difiere en el puntaje medio.

cat("=== H1: ANOVA de un factor — Puntaje total por programa ===\n")
## === H1: ANOVA de un factor — Puntaje total por programa ===
# Si se cumple normalidad → ANOVA; si no → Kruskal-Wallis
anova_prog <- aov(puntaje_total ~ programa, data = datos)
sum_anova  <- summary(anova_prog)
print(sum_anova)
##              Df Sum Sq Mean Sq F value Pr(>F)    
## programa      2   8.62   4.309    7.23  9e-04 ***
## Residuals   231 137.66   0.596                   
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
cat("\nTamaño del efecto (η²):",
    round(sum_anova[[1]][["Sum Sq"]][1] /
            sum(sum_anova[[1]][["Sum Sq"]]), 3), "\n")
## 
## Tamaño del efecto (η²): 0.059
# Post hoc Tukey HSD
tukey <- TukeyHSD(anova_prog)
kable(as.data.frame(tukey$programa) %>%
        mutate(across(where(is.numeric), ~ round(., 4))),
      caption = "Tabla 10. Comparaciones post hoc Tukey HSD (puntaje por programa)") %>%
  kable_styling(bootstrap_options = c("striped"), full_width = FALSE)
Tabla 10. Comparaciones post hoc Tukey HSD (puntaje por programa)
diff lwr upr p adj
Física-Biología 0.3790 0.0684 0.6896 0.0121
Matemática Aplicada-Biología -0.2059 -0.5028 0.0911 0.2328
Matemática Aplicada-Física -0.5849 -0.9535 -0.2163 0.0007

📊 Interpretación H1 — Post hoc Tukey: - Si el ANOVA es significativo (p < 0.05), al menos un programa difiere de los demás. - El Tukey HSD identifica cuáles pares difieren. Busca en la tabla las comparaciones con p adj < 0.05. - Interpretación sustantiva: Si Física difiere de Biología y Matemática, significa que la formación disciplinar específica (variable formativa) genera tendencias de pensamiento distintas — resultado central para tu objetivo específico 2 (relación entre planes de estudio y tendencias). - El η² (eta cuadrado) indica el tamaño del efecto: < 0.06 pequeño, 0.06–0.14 mediano, > 0.14 grande.

# Kruskal-Wallis como prueba no paramétrica complementaria
kw <- kruskal.test(puntaje_total ~ programa, data = datos)
cat("Kruskal-Wallis H =", round(kw$statistic, 3),
    "  gl =", kw$parameter,
    "  p =", round(kw$p.value, 4), "\n")
## Kruskal-Wallis H = 20.691   gl = 2   p = 0

📊 Kruskal-Wallis: Confirma el ANOVA con datos ordinales. Si ambas pruebas coinciden en la conclusión (ambas p < 0.05 o ambas p > 0.05), el resultado es robusto. Si difieren, reporta el Kruskal-Wallis como prueba principal dado que los datos Likert son ordinales.

ggplot(datos, aes(x = programa, y = puntaje_total, fill = programa)) +
  geom_boxplot(alpha = 0.7, outlier.shape = 21) +
  geom_jitter(width = 0.15, alpha = 0.3, size = 1.2) +
  stat_summary(fun = mean, geom = "point", shape = 23, size = 3,
               fill = "white", color = "black") +
  scale_fill_manual(values = c("#2196F3", "#FF5722", "#4CAF50")) +
  labs(title = "H1: Puntaje total por programa académico",
       subtitle = "◆ = media aritmética",
       x = "Programa", y = "Puntaje promedio (1–5)") +
  theme_minimal(base_size = 12) + theme(legend.position = "none")

📊 Interpretación boxplot H1: Observa si las cajas de los tres programas se solapan o están separadas. Poco solapamiento y medianas distintas refuerzan visualmente la significancia estadística. El rombo (◆) muestra la media — si difiere mucho de la mediana, hay asimetría en ese grupo.

7.2 H2: Diferencias según sexo

H₀: No existen diferencias en el puntaje total entre hombres y mujeres.
H₁: Existen diferencias significativas por sexo.

cat("=== H2: Prueba t — Puntaje total por sexo ===\n")
## === H2: Prueba t — Puntaje total por sexo ===
t_sexo <- t.test(puntaje_total ~ sexo, data = datos, var.equal = FALSE)
print(t_sexo)
## 
##  Welch Two Sample t-test
## 
## data:  puntaje_total by sexo
## t = -4.1841, df = 231.99, p-value = 4.063e-05
## alternative hypothesis: true difference in means between group Femenino and group Masculino is not equal to 0
## 95 percent confidence interval:
##  -0.6156433 -0.2214619
## sample estimates:
##  mean in group Femenino mean in group Masculino 
##                3.137281                3.555833
# Tamaño del efecto d de Cohen
medias <- tapply(datos$puntaje_total, datos$sexo, mean, na.rm = TRUE)
sds    <- tapply(datos$puntaje_total, datos$sexo, sd,   na.rm = TRUE)
ns     <- tapply(datos$puntaje_total, datos$sexo, function(x) sum(!is.na(x)))
sp     <- sqrt(((ns[1]-1)*sds[1]^2 + (ns[2]-1)*sds[2]^2) / (sum(ns) - 2))
d_cohen <- abs(diff(medias)) / sp
cat("\nd de Cohen:", round(d_cohen, 3),
    " Interpretación:",
    ifelse(d_cohen < 0.2, "trivial",
           ifelse(d_cohen < 0.5, "pequeño",
                  ifelse(d_cohen < 0.8, "mediano", "grande"))), "\n")
## 
## d de Cohen: 0.547  Interpretación: mediano

📊 Interpretación H2 — Sexo: - Si p < 0.05: existe diferencia estadísticamente significativa por sexo en la tendencia de pensamiento sobre energía nuclear. - La d de Cohen cuantifica la magnitud: < 0.2 trivial, 0.2–0.5 pequeño, 0.5–0.8 mediano, > 0.8 grande. - En estudios de percepción de riesgo tecnológico, es frecuente que las mujeres puntúen más alto en percepción de riesgo y más bajo en actitud favorable — si eso ocurre aquí, constituye evidencia para tu objetivo 3 (correlación con variables socioculturales).

# Mann-Whitney U (no paramétrico)
mw <- wilcox.test(puntaje_total ~ sexo, data = datos)
cat("Mann-Whitney U =", mw$statistic,
    "  p =", round(mw$p.value, 4), "\n")
## Mann-Whitney U = 4359.5   p = 0

7.3 H3: Diferencias según grupo de edad (ANOVA/Kruskal-Wallis)

H₀: El puntaje total no varía significativamente entre grupos de edad.
H₁: Al menos un grupo de edad difiere en su puntaje.

cat("=== H3: ANOVA y Kruskal-Wallis — Puntaje total por edad ===\n")
## === H3: ANOVA y Kruskal-Wallis — Puntaje total por edad ===
anova_edad <- aov(puntaje_total ~ edad, data = datos)
print(summary(anova_edad))
##              Df Sum Sq Mean Sq F value Pr(>F)  
## edad          4   7.09  1.7722   2.916 0.0222 *
## Residuals   229 139.19  0.6078                 
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
kw_edad <- kruskal.test(puntaje_total ~ edad, data = datos)
cat("\nKruskal-Wallis H =", round(kw_edad$statistic, 3),
    "  p =", round(kw_edad$p.value, 4), "\n")
## 
## Kruskal-Wallis H = 8.844   p = 0.0651

📊 Interpretación H3 — Edad: - Si p < 0.05: la edad (variable sociocultural) predice diferencias en las tendencias de pensamiento. - Esperable que estudiantes de mayor edad y semestres avanzados tengan más conocimiento (D1 mayor) y actitudes más matizadas (D3 moderada). Si el patrón es contrario, es un hallazgo interesante para discutir. - Si no hay diferencias significativas por edad, reporta que las tendencias son homogéneas entre generaciones dentro de la facultad.

7.4 H4: Diferencias por dimensión según programa (MANOVA)

H₀: Los vectores de medias dimensionales son iguales entre programas.
H₁: Al menos un programa difiere en al menos una dimensión.

cat("=== H4: MANOVA — Dimensiones × Programa ===\n")
## === H4: MANOVA — Dimensiones × Programa ===
manova_fit <- manova(
  cbind(D1_conocimiento, D2_riesgo, D3_actitud,
        D4_influencia, D5_comparacion) ~ programa,
  data = datos
)

print(summary(manova_fit, test = "Pillai"))
##            Df  Pillai approx F num Df den Df    Pr(>F)    
## programa    2 0.17319   4.3231     10    456 8.613e-06 ***
## Residuals 231                                             
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
cat("\n")
print(summary.aov(manova_fit))
##  Response D1_conocimiento :
##              Df  Sum Sq Mean Sq F value    Pr(>F)    
## programa      2  21.842  10.921  12.243 8.837e-06 ***
## Residuals   231 206.054   0.892                      
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
##  Response D2_riesgo :
##              Df  Sum Sq Mean Sq F value   Pr(>F)   
## programa      2   8.877  4.4386  4.8182 0.008912 **
## Residuals   231 212.802  0.9212                    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
##  Response D3_actitud :
##              Df  Sum Sq Mean Sq F value    Pr(>F)    
## programa      2  16.537  8.2685  8.8619 0.0001958 ***
## Residuals   231 215.532  0.9330                      
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
##  Response D4_influencia :
##              Df  Sum Sq Mean Sq F value Pr(>F)
## programa      2   0.403 0.20159  0.2528 0.7769
## Residuals   231 184.233 0.79755               
## 
##  Response D5_comparacion :
##              Df  Sum Sq Mean Sq F value  Pr(>F)  
## programa      2   4.486 2.24324  2.3397 0.09864 .
## Residuals   231 221.476 0.95877                  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

📊 Interpretación H4 — MANOVA: - El estadístico de Pillai (preferido cuando se viola normalidad multivariada) evalúa si los programas difieren simultáneamente en las cinco dimensiones. - Si p < 0.05 en Pillai: hay diferencias multivariadas → mira los ANOVAs univariados por dimensión (segunda parte del output) para identificar en cuáles dimensiones específicamente difieren los programas. - Esto responde directamente al objetivo específico 2: la relación entre el plan de estudios y las tendencias por área temática.

7.5 H5: Correlaciones entre dimensiones y semestre cursado

H₀: No existe correlación significativa entre el semestre y las dimensiones.

cat("=== H5: Correlación semestre × dimensiones ===\n\n")
## === H5: Correlación semestre × dimensiones ===
vars_cor <- c("D1_conocimiento", "D2_riesgo", "D3_actitud",
              "D4_influencia", "D5_comparacion", "puntaje_total")

res_cor <- lapply(vars_cor, function(v) {
  ct <- cor.test(datos$semestre, datos[[v]], method = "spearman",
                 use = "complete.obs")
  data.frame(Variable = v,
             rho      = round(ct$estimate, 3),
             p_valor  = round(ct$p.value, 4),
             Sig      = ifelse(ct$p.value < 0.001, "***",
                               ifelse(ct$p.value < 0.01, "**",
                                      ifelse(ct$p.value < 0.05, "*", "ns"))))
})

tab_cor <- do.call(rbind, res_cor)
kable(tab_cor, row.names = FALSE,
      caption = "Tabla 11. Correlaciones Spearman semestre × dimensiones") %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE) %>%
  column_spec(4, bold = TRUE)
Tabla 11. Correlaciones Spearman semestre × dimensiones
Variable rho p_valor Sig
D1_conocimiento 0.326 0.0000 ***
D2_riesgo 0.080 0.2199 ns
D3_actitud 0.252 0.0001 ***
D4_influencia 0.140 0.0326
D5_comparacion 0.149 0.0226
puntaje_total 0.275 0.0000 ***

📊 Interpretación H5 — Correlación Spearman semestre × dimensiones: - ρ (rho) mide la correlación: +1 correlación positiva perfecta, −1 negativa perfecta, 0 sin correlación. - Si ρ > 0 y p < 0.05 en D1 (conocimiento): a mayor semestre, mayor conocimiento percibido sobre energía nuclear — coherente con la formación académica acumulada. - Si ρ > 0 en D3 (actitud favorable): los estudiantes de semestres avanzados son más favorables a la energía nuclear, posiblemente por mayor exposición a ciencia básica. - Una correlación significativa aquí responde al objetivo específico 3 y aporta evidencia directa a la pregunta de investigación.

7.6 H6: Regresión múltiple — Predictores del puntaje total

Modelo: puntaje_total ~ semestre + programa + sexo + edad

cat("=== H6: Regresión múltiple (OLS) ===\n\n")
## === H6: Regresión múltiple (OLS) ===
mod <- lm(puntaje_total ~ semestre + programa + sexo + edad,
          data = datos)
print(summary(mod))
## 
## Call:
## lm(formula = puntaje_total ~ semestre + programa + sexo + edad, 
##     data = datos)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -2.40671 -0.27649  0.08617  0.43901  1.82116 
## 
## Coefficients:
##                             Estimate Std. Error t value Pr(>|t|)    
## (Intercept)                  2.77686    0.15923  17.439  < 2e-16 ***
## semestre                     0.04995    0.02010   2.486   0.0137 *  
## programaFísica               0.20831    0.13503   1.543   0.1243    
## programaMatemática Aplicada -0.20348    0.13279  -1.532   0.1268    
## sexoMasculino                0.42805    0.10212   4.192 3.98e-05 ***
## edad18 – 22                  0.15551    0.16448   0.945   0.3454    
## edad23 – 27                  0.04402    0.20653   0.213   0.8314    
## edad28 – 32                  0.17558    0.26510   0.662   0.5084    
## edadMás de 32               -0.51918    0.38140  -1.361   0.1748    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 0.7316 on 225 degrees of freedom
## Multiple R-squared:  0.1768, Adjusted R-squared:  0.1475 
## F-statistic: 6.038 on 8 and 225 DF,  p-value: 4.921e-07
cat("\nAnálisis de varianza del modelo:\n")
## 
## Análisis de varianza del modelo:
print(anova(mod))
## Analysis of Variance Table
## 
## Response: puntaje_total
##            Df  Sum Sq Mean Sq F value    Pr(>F)    
## semestre    1   9.670  9.6704 18.0679 3.124e-05 ***
## programa    2   4.100  2.0500  3.8301   0.02314 *  
## sexo        1   9.295  9.2953 17.3670 4.395e-05 ***
## edad        4   2.790  0.6974  1.3030   0.26978    
## Residuals 225 120.426  0.5352                      
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

📊 Interpretación H6 — Regresión múltiple: Este modelo responde directamente la pregunta de investigación: ¿en qué medida las variables socioculturales y formativas predicen las tendencias de pensamiento?

  • R² ajustado: proporción de varianza del puntaje total explicada por el modelo. R² > 0.10 ya es relevante en ciencias sociales; R² > 0.25 es bueno.
  • Coeficientes significativos (p < 0.05): las variables con asterisco (*) son predictores estadísticamente relevantes.
  • Interpretación de coeficientes: el signo (+/−) indica la dirección. Ej: si programaFísica tiene coeficiente positivo significativo, los estudiantes de Física puntúan más alto que la categoría de referencia (Biología).
  • Modelo general (F-test): si el p-valor global es < 0.05, el conjunto de predictores explica varianza real — el modelo es útil.
  • Si el R² es bajo (< 0.10), no significa que la investigación sea inválida — significa que hay otras variables no medidas que también influyen (cultura, medios, experiencias previas), lo cual puedes discutir como limitación y línea futura.
par(mfrow = c(2, 2))
plot(mod)

par(mfrow = c(1, 1))

📊 Gráficos diagnósticos del modelo de regresión: - Residuals vs Fitted: los residuos deben distribuirse aleatoriamente alrededor del 0. Patrones en abanico = heterocedasticidad. - Q-Q de residuos: los puntos deben seguir la diagonal. Desviaciones en colas son tolerables con n > 200. - Scale-Location: evalúa homocedasticidad; la línea debe ser horizontal. - Cook’s Distance / Leverage: puntos > 0.5 en Cook’s D son observaciones influyentes que conviene investigar.

# VIF — multicolinealidad
cat("Factor de inflación de varianza (VIF):\n")
## Factor de inflación de varianza (VIF):
print(round(vif(mod), 3))
##           GVIF Df GVIF^(1/(2*Df))
## semestre 1.630  1           1.277
## programa 1.459  2           1.099
## sexo     1.139  1           1.067
## edad     1.649  4           1.065

📊 VIF — Multicolinealidad: Valores VIF > 5 indican colinealidad problemática entre predictores. Si todos los VIF < 5, los predictores son suficientemente independientes y los coeficientes del modelo son estables e interpretables.


8 Análisis por dimensión y programa

datos_long <- datos %>%
  select(programa, D1_conocimiento, D2_riesgo, D3_actitud,
         D4_influencia, D5_comparacion) %>%
  pivot_longer(-programa,
               names_to  = "Dimensión",
               values_to = "Puntaje") %>%
  mutate(Dimensión = case_match(Dimensión,
    "D1_conocimiento" ~ "D1 Conocimiento",
    "D2_riesgo"       ~ "D2 Riesgo",
    "D3_actitud"      ~ "D3 Actitud",
    "D4_influencia"   ~ "D4 Influencia",
    "D5_comparacion"  ~ "D5 Comparación"
  ))

ggplot(datos_long, aes(x = Dimensión, y = Puntaje, fill = programa)) +
  geom_boxplot(alpha = 0.75, outlier.alpha = 0.3) +
  stat_summary(fun = mean, geom = "point", shape = 23, size = 2,
               position = position_dodge(0.75), fill = "white") +
  scale_fill_manual(values = c("#2196F3", "#FF5722", "#4CAF50"),
                    name = "Programa") +
  labs(title = "Distribución de dimensiones por programa académico",
       subtitle = "◆ = media | Escala Likert 1–5",
       x = NULL, y = "Puntaje promedio") +
  theme_minimal(base_size = 12) +
  theme(legend.position = "bottom")

📊 Interpretación boxplot por dimensión y programa: Este gráfico es uno de los más informativos del estudio. Permite ver de un vistazo en qué dimensiones difieren los programas: - Si las cajas de Física están claramente por encima de Biología y Matemática en D1 (conocimiento) y D3 (actitud), confirma que la formación en física nuclear genera mayor conocimiento y actitud más favorable. - Si Biología puntúa más alto en D2 (riesgo), puede reflejar una mayor sensibilidad ambiental por su perfil de carrera. - La ausencia de diferencias en alguna dimensión también es un resultado: indicaría que esa percepción es transversal a todos los programas.

tab_dim_prog <- datos %>%
  group_by(programa) %>%
  summarise(
    `D1 Conocimiento` = round(mean(D1_conocimiento, na.rm = TRUE), 2),
    `D2 Riesgo`       = round(mean(D2_riesgo, na.rm = TRUE), 2),
    `D3 Actitud`      = round(mean(D3_actitud, na.rm = TRUE), 2),
    `D4 Influencia`   = round(mean(D4_influencia, na.rm = TRUE), 2),
    `D5 Comparación`  = round(mean(D5_comparacion, na.rm = TRUE), 2),
    `Total`           = round(mean(puntaje_total, na.rm = TRUE), 2),
    .groups = "drop"
  )

kable(tab_dim_prog,
      caption = "Tabla 12. Medias por dimensión según programa académico") %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)
Tabla 12. Medias por dimensión según programa académico
programa D1 Conocimiento D2 Riesgo D3 Actitud D4 Influencia D5 Comparación Total
Biología 3.40 3.47 3.48 2.99 3.11 3.32
Física 4.05 3.49 4.02 3.06 3.46 3.70
Matemática Aplicada 3.14 3.01 3.22 2.93 3.15 3.12

📊 Interpretación tabla de medias por programa: Compara fila a fila los tres programas. Las diferencias numéricas > 0.30 entre programas en una misma dimensión son sustancialmente relevantes. La columna Total resume la tendencia global de cada programa.


9 Mapa de calor de correlaciones

mat_cor <- datos %>%
  select(P1:P20) %>%
  cor(use = "complete.obs")

corrplot::corrplot(mat_cor,
                   method  = "color",
                   type    = "upper",
                   tl.cex  = 0.7,
                   tl.col  = "black",
                   addCoef.col = "black",
                   number.cex  = 0.45,
                   col = colorRampPalette(c("#f44336","white","#2196F3"))(200),
                   title = "Matriz de correlaciones — Ítems P1–P20",
                   mar = c(0, 0, 2, 0))

📊 Interpretación mapa de calor: - Azul intenso (r cercano a +1): los dos ítems se mueven juntos — los estudiantes que están de acuerdo con uno tienden a estarlo con el otro. - Rojo intenso (r cercano a −1): relación inversa — acuerdo con uno implica desacuerdo con el otro. - Bloques de correlaciones altas entre ítems de una misma dimensión (ej. P1–P4) validan que la agrupación dimensional es coherente. - Correlaciones bajas entre dimensiones confirman que las dimensiones miden constructos distintos (validez discriminante). - Ítems que correlacionan muy poco con todos los demás (fila/columna sin azul ni rojo) son candidatos a revisar en futuras versiones del instrumento.


10 Distribución de respuestas Likert

# Frecuencias relativas por ítem
freq_likert <- datos %>%
  select(P1:P20) %>%
  pivot_longer(everything(), names_to = "Item", values_to = "Respuesta") %>%
  filter(!is.na(Respuesta)) %>%
  group_by(Item, Respuesta) %>%
  summarise(n = n(), .groups = "drop") %>%
  group_by(Item) %>%
  mutate(Porcentaje = n / sum(n) * 100) %>%
  ungroup() %>%
  mutate(Respuesta = factor(Respuesta, levels = 1:5,
                             labels = c("1\nTot. desacuerdo",
                                        "2\nDesacuerdo",
                                        "3\nNeutro",
                                        "4\nDe acuerdo",
                                        "5\nTot. acuerdo")))

ggplot(freq_likert, aes(x = Item, y = Porcentaje, fill = Respuesta)) +
  geom_bar(stat = "identity", position = "fill") +
  scale_fill_manual(
    values = c("#d32f2f","#ef9a9a","#FFF9C4","#a5d6a7","#388e3c"),
    name = "Respuesta") +
  scale_y_continuous(labels = percent_format()) +
  coord_flip() +
  labs(title = "Distribución de respuestas Likert por ítem",
       x = NULL, y = "Proporción de respuestas") +
  theme_minimal(base_size = 11) +
  theme(legend.position = "bottom")

📊 Interpretación gráfico de barras apiladas: Este gráfico muestra la distribución completa de respuestas para cada ítem. Los colores verdes representan acuerdo (4 y 5), el amarillo es neutro (3), y los rojos son desacuerdo (1 y 2). - Ítems con barra mayoritariamente verde: consenso de acuerdo en la muestra. - Ítems con barras divididas entre verde y rojo con poco amarillo: alta polarización — los estudiantes tienen opiniones fuertes pero opuestas. Esto es especialmente relevante para tu análisis cualitativo. - Ítems con amarillo dominante: alta indecisión o desconocimiento del tema — posible señal de que el ítem es ambiguo o que el tema es desconocido para ese grupo.


11 Resumen de resultados principales

cat("╔══════════════════════════════════════════════════════════════════╗\n")
## ╔══════════════════════════════════════════════════════════════════╗
cat("║          RESUMEN DE RESULTADOS ESTADÍSTICOS                    ║\n")
## ║          RESUMEN DE RESULTADOS ESTADÍSTICOS                    ║
cat("╠══════════════════════════════════════════════════════════════════╣\n")
## ╠══════════════════════════════════════════════════════════════════╣
cat(sprintf("║  α de Cronbach (escala completa): %.3f (%s) ║\n",
            alfa_global$total$raw_alpha, interpretacion))
## ║  α de Cronbach (escala completa): 0.934 (Excelente (≥ 0.90)) ║
cat(sprintf("║  n = %d  |  Biología: %d  |  Física: %d  |  Mat. Ap.: %d   ║\n",
            nrow(datos), sum(datos$programa=="Biología"),
            sum(datos$programa=="Física"),
            sum(datos$programa=="Matemática Aplicada")))
## ║  n = 234  |  Biología: 136  |  Física: 46  |  Mat. Ap.: 52   ║
cat("╚══════════════════════════════════════════════════════════════════╝\n\n")
## ╚══════════════════════════════════════════════════════════════════╝
resumen_h <- data.frame(
  Hipótesis = c("H1: Diferencias por programa (ANOVA)",
                "H2: Diferencias por sexo (t / Mann-Whitney)",
                "H3: Diferencias por edad (ANOVA / Kruskal)",
                "H4: Diferencias multivariadas (MANOVA)",
                "H5: Correlación semestre–dimensiones (Spearman)",
                "H6: Regresión múltiple (OLS)"),
  Prueba     = c("ANOVA + Tukey HSD + Kruskal-Wallis",
                 "t de Welch + Mann-Whitney U",
                 "ANOVA + Kruskal-Wallis",
                 "MANOVA (Pillai)",
                 "Spearman ρ",
                 "Regresión lineal múltiple"),
  Decisión   = c("Ver output arriba", "Ver output arriba",
                 "Ver output arriba", "Ver output arriba",
                 "Ver output arriba", "Ver output arriba")
)

kable(resumen_h,
      caption = "Tabla 13. Resumen de pruebas de hipótesis del estudio") %>%
  kable_styling(bootstrap_options = c("striped", "hover"), full_width = FALSE)
Tabla 13. Resumen de pruebas de hipótesis del estudio
Hipótesis Prueba Decisión
H1: Diferencias por programa (ANOVA) ANOVA + Tukey HSD + Kruskal-Wallis Ver output arriba
H2: Diferencias por sexo (t / Mann-Whitney) t de Welch + Mann-Whitney U Ver output arriba
H3: Diferencias por edad (ANOVA / Kruskal) ANOVA + Kruskal-Wallis Ver output arriba
H4: Diferencias multivariadas (MANOVA) MANOVA (Pillai) Ver output arriba
H5: Correlación semestre–dimensiones (Spearman) Spearman ρ Ver output arriba
H6: Regresión múltiple (OLS) Regresión lineal múltiple Ver output arriba

12 Conclusiones estadísticas

A continuación se presentan las conclusiones derivadas del análisis:

  1. Fiabilidad del instrumento: El coeficiente alfa de Cronbach para la escala completa (20 ítems) permite determinar el nivel de consistencia interna del instrumento. Valores ≥ 0.70 son considerados aceptables para investigación en ciencias sociales (George & Mallery, 2003).

  2. Perfil de la muestra: La muestra estratificada (n = 234) representa fielmente las proporciones poblacionales de los tres programas: Biología (58.1 %), Física (19.7 %) y Matemática Aplicada (22.2 %).

  3. Tendencias de pensamiento: Los puntajes promedio por dimensión revelan los patrones actitudinales predominantes. Valores > 3 indican acuerdo; valores < 3 indican desacuerdo con los enunciados.

  4. Diferencias por programa: El ANOVA/Kruskal-Wallis permite evaluar si el programa académico (variable formativa) predice diferencias en las tendencias de pensamiento, respondiendo al objetivo específico 3.

  5. Predicción del puntaje total: El modelo de regresión múltiple (H6) estima en qué medida las variables socioculturales (sexo, edad) y formativas (semestre, programa) predicen conjuntamente la tendencia de pensamiento, respondiendo directamente a la pregunta de investigación.


13 Referencias metodológicas

  • George, D., & Mallery, P. (2003). SPSS for Windows step by step (4th ed.). Allyn & Bacon.
  • Nunnally, J. C., & Bernstein, I. H. (1994). Psychometric Theory (3rd ed.). McGraw-Hill.
  • R Core Team (2024). R: A Language and Environment for Statistical Computing. Vienna: R Foundation.
  • Kline, R. B. (2016). Principles and Practice of Structural Equation Modeling (4th ed.). Guilford Press.

Documento generado automáticamente con R Markdown. Para reproducir, asegúrese de que el archivo de datos Cuestionario_final__respuestas.xlsx se encuentre en el mismo directorio de trabajo.