📚 Librería

library(readxl)
library(glue)
library(dplyr)
library(psych)
library(ggplot2)
library(knitr)
library(janitor)
library(nortest)
library(kableExtra)
library(tidyr)
library(ggrepel)
library(tidyverse)
library(effsize)
library(purrr)

❓Preguntas de investigación

Pregunta de investigación general

¿Qué relación existe entre la participación en un voluntariado curricular y el desarrollo de conductas prosociales en estudiantes universitarios?

Pregunta de investigación cuantitativa

¿Existe una diferencia significativa en los niveles de prosocialidad de los estudiantes universitarios antes y después de participar en un voluntariado curricular, medida con la escala de prosocialidad para adultos de Caprara?

📥 Importar y limpiar datos

# --- 1. Cargar el conjunto de datos ---
path_cuanti <- ("/Users/adrianaholguin/Desktop/Fase 2 cuanti.xlsx")
datos_pre_post_raw <- read_excel("/Users/adrianaholguin/Desktop/Fase 2 cuanti.xlsx")

# --- 2. Limpieza y Renombrado (transmute) ---
# (VERSIÓN FINAL: Solo importa los items. Los totales se calculan en el siguiente chunk)
datos_completos <- datos_pre_post_raw %>%
  transmute(
    Sujeto = as.character(Sujeto),
            
    # --- Sociodemográficas ---
    Edad = `X1..Edad`, Sexo = `X2..Sexo`, Estado_civil = `X3..Estado.civil`,
    Trabaja = `X4..Trabaja`, Residente = `X5..Residente`, Vive_con = `X6..Vive.con`,
    Grupo_vulnerabilidad = `X7..Grupo.de.vulnerabilidad`, Tipo_familia = `X8..Tipo.de.familia`,
    Num_personas_casa = `X9..Numero.de.personas.que.habitan.la.casa.familiar`,
    Nivel_socioeconomico = `X10..Nivel.socioeconomico.percibido`,
    Involucramiento_familiar = `X11..Involucramiento.familiar.con.la.comunidad.percibido`,
    Involucramiento_personal = `X12..Involucramiento.personal.con.su.comunidad.percibido`,
    Gusto_voluntariado = `X13..Le.gustaria.realizar.voluntariados.en.sus.materias`,
    Ha_voluntariado = `X15..Ha.realizado.voluntariados`,
            
    # --- Items PRE-TEST (A) - Convertidos a numérico ---
    A_item1 = as.numeric(`X27..A_Item1`), A_item2 = as.numeric(`X28..A_Item2`),
    A_item3 = as.numeric(`X29..A_Item3`), A_item4 = as.numeric(`X30..A_Item4`),
    A_item5 = as.numeric(`X31..A_Item5`), A_item6 = as.numeric(`X32..A_Item6`),
    A_item7 = as.numeric(`X33..A_Item7`), A_item8 = as.numeric(`X34..A_Item8`),
    A_item9 = as.numeric(`X35..A_Item9`), A_item10 = as.numeric(`X36..A_Item10`),
    A_item11 = as.numeric(`X37..A_Item11`), A_item12 = as.numeric(`X38..A_Item12`),
    A_item13 = as.numeric(`X39..A_Item13`), A_item14 = as.numeric(`X40..A_Item14`),
    A_item15 = as.numeric(`X41..A_Item15`), A_item16 = as.numeric(`X42..A_Item16`),
            
    # --- Items POST-TEST (B) - Convertidos a numérico ---
    B_item1 = as.numeric(`X48..B_Item1`), B_item2 = as.numeric(`X49..B_Item2`),
    B_item3 = as.numeric(`X50..B_Item3`), B_item4 = as.numeric(`X51..B_Item4`),
    B_item5 = as.numeric(`52..B_Item5`), B_item6 = as.numeric(`X53..B_Item6`),
    B_item7 = as.numeric(`X54..B_Item7`), B_item8 = as.numeric(`X55..B_Item8`),
    B_item9 = as.numeric(`X56..B_Item9`), B_item10 = as.numeric(`X57..B_Item10`),
    B_item11 = as.numeric(`X58..B_Item11`), B_item12 = as.numeric(`X59..B_Item12`),
    B_item13 = as.numeric(`X60..B_Item13`), B_item14 = as.numeric(`X61..B_Item14`),
    B_item15 = as.numeric(`X62..B_Item15`), B_item16 = as.numeric(`X63..B_Item16`)
  )

cat("--- Carga de Datos Fase 2 (Solo Items) Completa ---\n")
## --- Carga de Datos Fase 2 (Solo Items) Completa ---
cat(paste("Datos (datos_completos) cargados con", nrow(datos_completos), "filas.\n"))
## Datos (datos_completos) cargados con 42 filas.
## --- Recálculo de Totales (Pre y Post) CORREGIDO ---
## Subescalas (Ayudar, Compartir, Empatia) recalculadas según su definición.
## Totales (Total_A, Total_B) recalculados con ítems 1 al 14.

1. 📊 Fiabilidad de la Escala (Post-test)

# Dimensión 1: Ayudar (6 items)
items_ayudar_b <- datos_completos %>%
  select(B_item1, B_item3, B_item4, B_item6, B_item7, B_item13)

# Dimensión 2: Empatía (5 items)
items_empatia_b <- datos_completos %>%
  select(B_item5, B_item8, B_item10, B_item12, B_item16)

# Dimensión 3: Compartir (3 items)
items_compartir_b <- datos_completos %>%
  select(B_item2, B_item9, B_item14)

# Dimensión 4: Total (14 items)
items_total_b <- datos_completos %>%
  select(
    B_item1, B_item2, B_item3, B_item4, B_item5, B_item6, B_item7, B_item8, B_item9, B_item10, B_item11, B_item12, B_item13, B_item14                       # Compartir
  )

# --- 2. Calcular los 4 Alfas ---
alfa_ayudar <- psych::alpha(items_ayudar_b, check.keys = TRUE)
alfa_empatia <- psych::alpha(items_empatia_b, check.keys = TRUE)
alfa_compartir <- psych::alpha(items_compartir_b, check.keys = TRUE)
alfa_total <- psych::alpha(items_total_b, check.keys = TRUE)

# --- 3. Preparar la tabla para imprimir (con las 4 filas) ---
tabla_para_imprimir_alfa_post <- data.frame(
  Dimension = c("Ayudar (Post)", "Empatía (Post)", "Compartir (Post)", "Escala Total (Post)"),
  N_Items = c(
    ncol(items_ayudar_b),
    ncol(items_empatia_b),
    ncol(items_compartir_b),
    ncol(items_total_b)
  ),
  Alfa_Cronbach = c(
    alfa_ayudar$total$raw_alpha,
    alfa_empatia$total$raw_alpha,
    alfa_compartir$total$raw_alpha,
    alfa_total$total$raw_alpha
  )
)
Fiabilidad de la Escala (Alfa de Cronbach) - Post-test
Dimensión N de Ítems Alfa de Cronbach
Ayudar (Post) 6 0.633
Empatía (Post) 5 0.599
Compartir (Post) 3 0.357
Escala Total (Post) 14 0.801


1.1 📈 Gráficos QQ-Plot de normalidad de la escala de prosocialidad

# --- 1. Crear el dataframe de diferencias ---
# (Se usa 'datos_completos' del chunk 'recalcular_totales')
datos_diferencias <- datos_completos %>%
  mutate(
    Dif_Ayudar = Ayudar_B - Ayudar_A,
    Dif_Compartir = Compartir_B - Compartir_A,
    Dif_Empatia = Empatia_B - Empatia_A,
    Dif_Total = Total_B - Total_A
  ) %>%
  select(Dif_Ayudar, Dif_Compartir, Dif_Empatia, Dif_Total)

# --- 2. Pivotar a formato largo para ggplot ---
datos_diferencias_largos <- datos_diferencias %>%
  pivot_longer(
    cols = everything(),
    names_to = "Dimension",
    values_to = "Diferencia"
  ) %>%
  # Limpiar nombres para las etiquetas
  mutate(Dimension = str_replace(Dimension, "Dif_", "Diferencia en ")) %>%
  # Quitar NAs para que el gráfico no de warnings
  filter(!is.na(Diferencia))

# --- 3. Crear los 4 gráficos Q-Q Plot ---
ggplot(datos_diferencias_largos, aes(sample = Diferencia)) +
  # stat_qq() dibuja los puntos del Q-Q plot
  stat_qq() +
  # stat_qq_line() dibuja la línea de referencia roja
  stat_qq_line(color = "red", linetype = "dashed") +
  
  # Dividir en una cuadrícula de 2x2
  facet_wrap(~ Dimension, scales = "free") +
  
  # Títulos (sin emojis)
  labs(
    title = "Gráficos Q-Q Plot de las Diferencias (Post - Pre)",
    subtitle = "Los puntos deben seguir la línea roja para la normalidad",
    x = "Cuantiles Teóricos (Normal)",
    y = "Cuantiles de la Muestra"
  ) +
  theme_minimal()

2. ⚖️ Análisis Inferencial (Prueba de Wilcoxon)

# (Asegúrate de que 'rstatix', 'dplyr' y 'tidyr' estén en 'setup_librerias')

# --- 1. Crear el dataframe de diferencias ---
datos_diferencias <- datos_completos %>%
  mutate(
    Ayudar = Ayudar_B - Ayudar_A,
    Compartir = Compartir_B - Compartir_A,
    Empatia = Empatia_B - Empatia_A,
    Total = Total_B - Total_A
  ) %>%
  select(Ayudar, Compartir, Empatia, Total)

# --- 2. Pivotar a formato largo ---
datos_diferencias_largo <- datos_diferencias %>%
  pivot_longer(
    cols = everything(),
    names_to = "Dimension",
    values_to = "Diferencia"
  ) %>%
  # Importante: quitar los NAs
  filter(!is.na(Diferencia))

# --- 3. Calcular Pruebas de Wilcoxon (Método de 1-muestra sobre la diferencia) ---
wilcox_resultados <- datos_diferencias_largo %>%
  group_by(Dimension) %>%
  rstatix::wilcox_test(Diferencia ~ 1, mu = 0, detailed = TRUE) %>%
  select(Dimension, statistic, p)

# --- 4. Calcular Tamaño del Efecto (r) ---
effect_size_resultados <- datos_diferencias_largo %>%
  group_by(Dimension) %>%
  rstatix::wilcox_effsize(Diferencia ~ 1, mu = 0) %>%
  select(Dimension, effsize, magnitude)

# --- 5. Unir y traducir tablas ---
tabla_inferencia_final <- left_join(wilcox_resultados, effect_size_resultados, by = "Dimension") %>%
  select(Dimension, statistic, p, effsize, magnitude) %>%
  arrange(factor(Dimension, levels = c("Ayudar", "Compartir", "Empatia", "Total"))) %>%
  
  # --- TRADUCCIÓN DE MAGNITUD (¡CORREGIDA!) ---
  mutate(magnitude = case_when(
    magnitude == "small" ~ "Pequeño",
    magnitude == "moderate" ~ "Mediano",
    magnitude == "large" ~ "Grande",
    TRUE ~ magnitude # 
  ))
Resultados de las Pruebas de Hipótesis (Wilcoxon Pre vs. Post)
Dimensión Estadístico (W) p-value Efecto (r) Magnitud
Ayudar 576 0.000 0.602 Grande
Compartir 86 0.345 0.098 Pequeño
Empatia 460 0.005 0.428 Mediano
Total 740 0.000 0.624 Grande

Interpretación: Un p-value menor a 0.05 indica que el cambio entre el Pre-test y el Post-test es estadísticamente significativo.


📊 Visualización de Resultados (Gráficos Boxplot)

# (Versión Corregida: se añade factor() y se cambia el nombre del dataframe)

# --- 1.A. Crear datos largos (NUEVO NOMBRE) ---
datos_largos_LIMPIO <- datos_completos %>%
  select(
    Sujeto,
    Ayudar_A, Ayudar_B,
    Compartir_A, Compartir_B,
    Empatia_A, Empatia_B,
    Total_A, Total_B
  ) %>%
  pivot_longer(
    cols = -Sujeto,
    names_to = c("Dimension", "Momento"),
    names_pattern = "(.*)_(.)",
    values_to = "Puntaje"
  ) %>%
  
  # --- 1.B. Limpiar y ORDENAR etiquetas ---
  mutate(
    Momento = recode(Momento, "A" = "Pre-test", "B" = "Post-test"),
    # --- ¡LÍNEA AÑADIDA! ---
    # Forzamos el orden correcto del eje X
    Momento = factor(Momento, levels = c("Pre-test", "Post-test")), 
    Dimension = factor(Dimension, levels = c("Ayudar", "Compartir", "Empatia", "Total"))
  )

# --- 3. Crear los 4 gráficos (VERSIÓN LIMPIA) ---
# (Usando el nuevo dataframe 'datos_largos_LIMPIO')
ggplot(datos_largos_LIMPIO, aes(x = Momento, y = Puntaje, fill = Momento)) +
  
  # --- ÚNICAMENTE EL BOXPLOT ---
  geom_boxplot(alpha = 0.7) +
  
  # 4. Facet (divide en 4 gráficos)
  facet_wrap(~ Dimension, scales = "free_y") +
  
  # 5. Títulos y Estilos
  labs(
    title = "Comparación de Puntajes Pre-test vs. Post-test",
    subtitle = "Después de la intervención (voluntariado)",
    x = "Momento de Medición",
    y = "Puntaje Obtenido"
  ) +
  theme_minimal() +
  theme(
    legend.position = "none", # Quitar la leyenda (es redundante)
    strip.text = element_text(size = 12, face = "bold") # Títulos de facetas
  )

3. 📊 Estadística Descriptiva Comparativa (Pre vs. Post)

# 1. Calcular descriptivos del PRE-TEST (A)
#    (Usará los datos recalculados de 'datos_completos')
desc_pre <- datos_completos %>%
  rstatix::get_summary_stats(
    Ayudar_A, Compartir_A, Empatia_A, Total_A,
    type = "full"
  ) %>%
  select(variable, n, mean, sd, median, min, max) %>%
  mutate(Dimension = str_remove(variable, "_A")) %>%
  rename(
    N_A = n, Media_A = mean, DE_A = sd,
    Mediana_A = median, Min_A = min, Max_A = max
  ) %>%
  select(-variable)

# 2. Calcular descriptivos del POST-TEST (B)
desc_post <- datos_completos %>%
  rstatix::get_summary_stats(
    Ayudar_B, Compartir_B, Empatia_B, Total_B,
    type = "full"
  ) %>%
  select(variable, n, mean, sd, median, min, max) %>%
  mutate(Dimension = str_remove(variable, "_B")) %>%
  rename(
    N_B = n, Media_B = mean, DE_B = sd,
    Mediana_B = median, Min_B = min, Max_B = max
  ) %>%
  select(-variable)

# 3. Unir las tablas Pre y Post por la 'Dimension'
tabla_descriptivos_comparativos <- left_join(desc_pre, desc_post, by = "Dimension") %>%
  arrange(factor(Dimension, levels = c("Ayudar", "Compartir", "Empatia", "Total")))

# 4. Dividir en dos tablas
tabla_desc_comp_1 <- tabla_descriptivos_comparativos %>%
  select(Dimension, N_A, N_B, Media_A, Media_B, DE_A, DE_B)
tabla_desc_comp_2 <- tabla_descriptivos_comparativos %>%
  select(Dimension, Mediana_A, Mediana_B, Min_A, Min_B, Max_A, Max_B)
Estadística Descriptiva (Pre vs. Post): Tendencia Central
Dimensión N (Pre) N (Post) Media (Pre) Media (Post) DE (Pre) DE (Post)
Ayudar 42 42 21.93 23.29 3.54 2.61
Compartir 42 42 12.52 12.64 1.63 1.32
Empatia 42 42 20.02 20.74 2.78 2.39
Total 42 42 53.59 56.02 7.32 5.43

Estadística Descriptiva (Pre vs. Post): Distribución
Dimensión Mediana (Pre) Mediana (Post) Mín (Pre) Mín (Post) Máx (Pre) Máx (Post)
Ayudar 22 23.0 15 19 28 28
Compartir 12 12.5 8 10 15 15
Empatia 20 21.0 15 16 24 25
Total 53 56.0 37 45 67 66


4.📍 Identificación de Casos Atípicos

# (Versión "A prueba de fantasmas" - Nombres de variables cambiados)
# (Asegúrate de que 'ggrepel', 'ggplot2', 'dplyr' y 'tidyr' estén en 'setup_librerias')

# --- 1. Preparar los datos largos (NUEVO NOMBRE) ---
datos_largos_FINAL <- datos_completos %>%
  select(
    Sujeto,
    Ayudar_A, Ayudar_B,
    Compartir_A, Compartir_B,
    Empatia_A, Empatia_B,
    Total_A, Total_B
  ) %>%
  pivot_longer(
    cols = -Sujeto,
    names_to = c("Dimension", "Momento"),
    names_pattern = "(.*)_(.)",
    values_to = "Puntaje"
  ) %>%
  
  # --- 1.B. Limpiar y ORDENAR etiquetas ---
  mutate(
    Momento = recode(Momento, "A" = "Pre-test", "B" = "Post-test"),
    # Forzamos el orden correcto del eje X
    Momento = factor(Momento, levels = c("Pre-test", "Post-test")), 
    Dimension = factor(Dimension, levels = c("Ayudar", "Compartir", "Empatia", "Total"))
  )

# --- 2. Definir entrevistados y marcar los datos (NUEVO NOMBRE) ---
sujetos_entrevistados <- c("5", "36", "6", "40", "20", "8")

datos_hibrido_FINAL <- datos_largos_FINAL %>%
  mutate(
    Entrevistado = ifelse(Sujeto %in% sujetos_entrevistados, "Sí", "No")
  )

# --- 3. Filtrar solo los datos de los entrevistados (NUEVO NOMBRE) ---
datos_resaltados_FINAL <- datos_hibrido_FINAL %>%
  filter(Entrevistado == "Sí")

# --- 4. Crear el gráfico (usando los dataframes NUEVOS) ---
ggplot(datos_hibrido_FINAL, aes(x = Momento, y = Puntaje)) +
  
  geom_boxplot(fill = "grey90", alpha = 0.5, outlier.shape = NA) +
  
  geom_jitter(
    aes(color = Entrevistado), 
    width = 0.25,
    alpha = 0.5,
    size = 1.5
  ) +
  
  scale_color_manual(values = c("Sí" = "#E74C3C", "No" = "#7F8C8D")) +

  geom_line(
    data = datos_resaltados_FINAL, # <-- Usando nombre nuevo
    aes(group = Sujeto), 
    color = "#E74C3C", 
    linewidth = 0.6,
    alpha = 0.8
  ) +
  
  geom_text_repel(
    data = datos_resaltados_FINAL, # <-- Usando nombre nuevo
    aes(label = Sujeto), 
    color = "black",
    size = 3,
    max.overlaps = 15 
  ) +
  
  facet_wrap(~ Dimension, scales = "free_y") +
  labs(
    title = "Comparación Pre vs. Post (Estilo Jitter)",
    subtitle = "Todos los sujetos mostrados como puntos. Entrevistados (ID) en rojo.",
    x = "Momento de Medición",
    y = "Puntaje Obtenido"
  ) +
  theme_minimal() +
  theme(
    legend.position = "none", 
    strip.text = element_text(size = 12, face = "bold")
  )