📚 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 <- readxl::read_excel(path_cuanti)
# --- 2. Limpieza y Renombrado (UN solo transmute, sin anidar) ---
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) ---
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) ---
B_item1 = as.numeric(`X47..B_Item1`),
B_item2 = as.numeric(`X48..B_Item2`),
B_item3 = as.numeric(`X49..B_Item3`),
B_item4 = as.numeric(`X50..B_Item4`),
B_item5 = as.numeric(`X51..B_Item5`),
B_item6 = as.numeric(`X52..B_Item6`),
B_item7 = as.numeric(`X53..B_Item7`),
B_item8 = as.numeric(`X54..B_Item8`),
B_item9 = as.numeric(`X55..B_Item9`),
B_item10 = as.numeric(`X56..B_Item10`),
B_item11 = as.numeric(`X57..B_Item11`),
B_item12 = as.numeric(`X58..B_Item12`),
B_item13 = as.numeric(`X59..B_Item13`),
B_item14 = as.numeric(`X60..B_Item14`),
B_item15 = as.numeric(`X61..B_Item15`),
B_item16 = as.numeric(`X62..B_Item16`)
)
# --- Mensaje de confirmación ---
cat("--- Carga y limpieza Fase 2 COMPLETA ---\n")
## --- Carga y limpieza Fase 2 COMPLETA ---
cat("Filas cargadas:", nrow(datos_completos), "\n")
## Filas cargadas: 39
## --- Recálculo de subescalas y totales COMPLETO ---
## Ayudar, Compartir y Empatía recalculadas (A y B) según definición.
## Totales (A y B)
📊 Fiabilidad de la Escala (Post-test)
# Dimensión 1: Ayudar
items_ayudar_b <- datos_completos %>%
select(B_item1, B_item3, B_item4, B_item6, B_item7, B_item13)
# Dimensión 2: Empatía
items_empatia_b <- datos_completos %>%
select(B_item5, B_item8, B_item10, B_item12, B_item16)
# Dimensión 3: Compartir
items_compartir_b <- datos_completos %>%
select(B_item2, B_item9, B_item14)
# Dimensión 4: Total
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
)
# --- 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.625
|
|
Empatía (Post)
|
5
|
0.570
|
|
Compartir (Post)
|
3
|
0.322
|
|
Escala Total (Post)
|
14
|
0.788
|
📈 Gráficos QQ-Plot de normalidad de la escala de prosocialidad
# --- 1. Crear el dataframe de diferencias ---
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))
# --- Etiquetas personalizadas para las facetas ---
facet_labels <- c(
"Diferencia en Ayudar" = "Ayudar",
"Diferencia en Compartir" = "Compartir",
"Diferencia en Empatia" = "Empatía",
"Diferencia en Total" = "Total Escala"
)
# --- Gráficos Q-Q Plot con formato uniforme ---
ggplot(datos_diferencias_largos, aes(sample = Diferencia)) +
# Puntos con color vivo y transparencia
geom_qq(color = "#1ABC9C", size = 2, alpha = 0.8) +
# Línea de referencia en gris oscuro
geom_qq_line(color = "gray30", linetype = "dashed", linewidth = 1) +
# Facetas con etiquetas personalizadas
facet_wrap(~ Dimension, scales = "free", labeller = as_labeller(facet_labels)) +
# Títulos y etiquetas
labs(
title = "Q-Q Plots de Normalidad (Fase 2 - Diferencias Post - Pre)",
x = "Cuantiles teóricos",
y = "Cuantiles observados"
) +
# Tema con más contraste
theme_bw(base_size = 13) +
theme(
strip.background = element_rect(fill = "#34495E", color = NA), # fondo oscuro
strip.text = element_text(face = "bold", size = 12, color = "white"), # texto blanco
plot.title = element_text(face = "bold", hjust = 0.5, size = 14)
)

⚖️ Análisis Inferencial (Prueba de Wilcoxon)
# --- 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"
) %>%
filter(!is.na(Diferencia))
# --- 3. Pruebas de Wilcoxon (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. 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 ---
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"))) %>%
mutate(
Dimension = recode(Dimension, "Empatia" = "Empatía"),
p = ifelse(p < 0.001, "< .001", round(p, 3)),
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
|
484.5
|
< .001
|
0.603
|
Grande
|
|
Compartir
|
59.5
|
0.669
|
0.018
|
Pequeño
|
|
Empatía
|
377.5
|
0.01
|
0.413
|
Mediano
|
|
Total
|
622.0
|
< .001
|
0.590
|
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. Además, el
tamaño del efecto (r) indica la magnitud práctica del cambio: pequeño,
mediano o grande.
📊 Visualización de Resultados (Gráficos Boxplot)
# 1.A. Crear datos largos
datos_largos_para_grafico <- 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. Etiquetas y orden correctos
mutate(
Momento = recode(Momento, "A" = "Pre-test", "B" = "Post-test"),
Momento = factor(Momento, levels = c("Pre-test", "Post-test")), # orden temporal
Dimension = factor(Dimension, levels = c("Ayudar", "Compartir", "Empatia", "Total"))
)
# --- 2. Crear los 4 gráficos (VERSIÓN LIMPIA) ---
ggplot(datos_largos_para_grafico, aes(x = Momento, y = Puntaje, fill = Momento)) +
geom_boxplot(alpha = 0.7) +
facet_wrap(~ Dimension, scales = "free_y") +
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"
) +
scale_fill_manual(values = c("Pre-test" = "#7FB3D5", "Post-test" = "#1F618D")) + # opcional, colores consistentes
theme_minimal() +
theme(
legend.position = "none",
strip.text = element_text(size = 12, face = "bold")
)

📊 Estadística Descriptiva Comparativa (Pre vs. Post)
# 1. Calcular descriptivos del PRE-TEST (A)
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"))) %>%
mutate(Dimension = recode(Dimension, "Empatia" = "Empatía"))
# 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
|
39
|
39
|
22.05
|
23.39
|
3.49
|
2.61
|
|
Compartir
|
39
|
39
|
12.72
|
12.77
|
1.47
|
1.27
|
|
Empatía
|
39
|
39
|
20.28
|
20.95
|
2.71
|
2.32
|
|
Total
|
39
|
39
|
54.15
|
56.46
|
7.23
|
5.29
|
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
|
15
|
19
|
28
|
28
|
|
Compartir
|
13
|
13
|
9
|
10
|
15
|
15
|
|
Empatía
|
21
|
21
|
15
|
17
|
24
|
25
|
|
Total
|
53
|
56
|
37
|
48
|
67
|
66
|
Interpretación: Estas tablas muestran cómo cambian las
medidas de tendencia central y distribución entre el Pre-test y el
Post-test. La comparación permite observar tanto el promedio y la
dispersión como la forma de la distribución en cada dimensión.
📍 Identificación de Casos Atípicos
# --- 1. Preparar datos largos ---
datos_largos_para_grafico <- 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"
) %>%
mutate(
Momento = recode(Momento, "A" = "Pre-test", "B" = "Post-test"),
Momento = factor(Momento, levels = c("Pre-test", "Post-test")),
Dimension = recode(Dimension, "Empatia" = "Empatía")
) %>%
filter(!is.na(Puntaje))
# --- 2. Sujetos entrevistados ---
sujetos_entrevistados <- c("5", "36", "6", "40", "20", "2")
datos_resaltados <- datos_largos_para_grafico %>%
filter(Sujeto %in% sujetos_entrevistados)
# --- 3. Gráfico spaghetti con todos en gris y entrevistados en color ---
ggplot(datos_largos_para_grafico, aes(x = Momento, y = Puntaje, group = Sujeto)) +
# Todos los sujetos en gris tenue
geom_line(color = "gray80", linewidth = 0.3, alpha = 0.4) +
# Sujetos entrevistados resaltados
geom_line(data = datos_resaltados, aes(color = Sujeto), linewidth = 0.8) +
geom_point(data = datos_resaltados, aes(color = Sujeto), size = 2) +
# Etiqueta discreta para el sujeto 20
ggrepel::geom_text_repel(
data = datos_resaltados %>% filter(Sujeto == "20"),
aes(label = Sujeto),
color = "gray40",
size = 3 # más pequeño y en gris
) +
facet_wrap(~ Dimension, scales = "free_y") +
labs(
title = "Trayectorias individuales Pre-test vs. Post-test",
subtitle = "Sujetos entrevistados resaltados en color; resto en gris tenue",
x = "Momento de Medición",
y = "Puntaje Obtenido"
) +
theme_minimal() +
theme(
legend.position = "bottom",
strip.text = element_text(size = 12, face = "bold")
)
