1 0. Paquetes requeridos

packs <- c("psych", "dplyr", "tidyr", "ggplot2", "lavaan", "lavaanPlot")
to_install <- packs[!packs %in% installed.packages()[,1]]
if(length(to_install)) install.packages(to_install)
lapply(packs, library, character.only = TRUE)
## [[1]]
## [1] "psych"     "stats"     "graphics"  "grDevices" "utils"     "datasets" 
## [7] "methods"   "base"     
## 
## [[2]]
## [1] "dplyr"     "psych"     "stats"     "graphics"  "grDevices" "utils"    
## [7] "datasets"  "methods"   "base"     
## 
## [[3]]
##  [1] "tidyr"     "dplyr"     "psych"     "stats"     "graphics"  "grDevices"
##  [7] "utils"     "datasets"  "methods"   "base"     
## 
## [[4]]
##  [1] "ggplot2"   "tidyr"     "dplyr"     "psych"     "stats"     "graphics" 
##  [7] "grDevices" "utils"     "datasets"  "methods"   "base"     
## 
## [[5]]
##  [1] "lavaan"    "ggplot2"   "tidyr"     "dplyr"     "psych"     "stats"    
##  [7] "graphics"  "grDevices" "utils"     "datasets"  "methods"   "base"     
## 
## [[6]]
##  [1] "lavaanPlot" "lavaan"     "ggplot2"    "tidyr"      "dplyr"     
##  [6] "psych"      "stats"      "graphics"   "grDevices"  "utils"     
## [11] "datasets"   "methods"    "base"

2 1. Diccionario de variables

diccionario_bfi <- data.frame(
  variable = c(paste0("A", 1:5), paste0("C", 1:5), paste0("E", 1:5),
               paste0("N", 1:5), paste0("O", 1:5), "gender", "education", "age"),
  descripcion = c(
    "Amabilidad: es considerado y amable con casi todo el mundo",
    "Amabilidad: tiene una naturaleza de confianza",
    "Amabilidad: es cooperativo",
    "Amabilidad: está dispuesto a perdonar",
    "Amabilidad: es generoso con los demás",
    "Conciencia: hace las tareas de forma eficiente",
    "Conciencia: cumple sus compromisos",
    "Conciencia: es ordenado",
    "Conciencia: es meticuloso",
    "Conciencia: es fiable",
    "Extraversión: es comunicativo",
    "Extraversión: es sociable",
    "Extraversión: está lleno de energía",
    "Extraversión: le gusta estar con gente",
    "Extraversión: tiene entusiasmo",
    "Neuroticismo: se siente inseguro",
    "Neuroticismo: se preocupa con facilidad",
    "Neuroticismo: se siente nervioso",
    "Neuroticismo: se deprime fácilmente",
    "Neuroticismo: se siente triste con frecuencia",
    "Apertura: tiene imaginación activa",
    "Apertura: valora el arte",
    "Apertura: tiene muchas ideas",
    "Apertura: es original",
    "Apertura: aprecia la belleza",
    "Género del encuestado (1 = Hombre, 2 = Mujer)",
    "Nivel educativo (1 = menos educación, 6 = más educación)",
    "Edad del encuestado en años"
  ),
  grupo = c(rep("Amabilidad", 5), rep("Conciencia", 5),
            rep("Extraversión", 5), rep("Neuroticismo", 5),
            rep("Apertura", 5), "Demográfico", "Demográfico", "Demográfico"),
  stringsAsFactors = FALSE
)
View(diccionario_bfi)

3 2. Limpieza de datos

data(bfi, package = "psych")
invertidos <- c("A4", "C4", "C5", "E3", "E4", "E5", "N1", "N2", "N4", "N5")
bfi_clean <- bfi |>
  mutate(across(all_of(invertidos), ~ 7 - .x),
         A1 = NULL, O2 = NULL, O4 = NULL, O5 = NULL) |>
  drop_na()

4 3 Descripción de la base y aportes del presente análisis

La base de datos utilizada en este análisis es bfi, incluida en el paquete psych de R. Esta base fue desarrollada con fines educativos y de demostración psicométrica por el Dr. William Revelle (Northwestern University), y contiene respuestas auto-reportadas sobre 25 ítems diseñados para evaluar los cinco grandes factores de personalidad: Amabilidad (A), Conciencia (C), Extraversión (E), Neuroticismo (N) y Apertura a la experiencia (O). Cada ítem está codificado en una escala Likert de 1 a 6. Además, la base incluye tres variables sociodemográficas: gender (1 = Hombre, 2 = Mujer), education (escala de 1 a 6) y age (en años).

Diversos estudios y ejercicios de clase han empleado esta base para ilustrar análisis factoriales exploratorios (EFA), confirmatorios (CFA), evaluaciones de fiabilidad y modelos de ecuaciones estructurales (SEM). Sin embargo, la mayoría de estos análisis usan la base completa sin realizar ajustes finos sobre la selección de ítems ni incorporar predictores sociodemográficos de forma estructurada.

En el presente taller se realiza un enfoque diferenciado que incluye:

  • La depuración del instrumento a 21 ítems (se excluyen A1, O2, O4 y O5) para mejorar ajuste y simplicidad del modelo.
  • La inversión automatizada de 10 ítems formulados en sentido negativo.
  • La estimación de un modelo CFA de cinco factores con correlaciones residuales parciales justificadas teóricamente.
  • La integración de un modelo SEM incorporando las covariables age y education centradas, permitiendo evaluar sus efectos sobre los rasgos de personalidad.
  • La visualización avanzada de resultados, incluyendo diagramas SEM con coeficientes estandarizados, histogramas por ítem y comparaciones gráficas por género.
  • La interpretación aplicada de los resultados, identificando fortalezas (buena estructura factorial, fiabilidad aceptable en 4 factores), debilidades (baja fiabilidad en Apertura), y líneas de mejora metodológica.

En conjunto, este análisis no solo valida empíricamente la estructura Big Five, sino que también aporta una mirada más integrada y pedagógica al uso de SEM en psicometría aplicada.

5 3.1 Estadística descriptiva

A continuación, se resumen los valores medios, desviaciones estándar, mínimos y máximos de los ítems. Se observan altos puntajes en Amabilidad y Conciencia, mientras que Extraversión muestra puntajes bajos. Los ítems presentan adecuada dispersión.

tabla_resumen <- bfi_clean |>
  summarise(across(everything(),
                   list(media = mean, sd = sd, min = min, max = max),
                   .names = "{.col}_{.fn}")) |>
  pivot_longer(everything(),
               names_to = c("variable",".value"),
               names_sep = "_")
print(tabla_resumen)
## # A tibble: 24 × 5
##    variable media    sd   min   max
##    <chr>    <dbl> <dbl> <dbl> <dbl>
##  1 A2        4.83  1.16     1     6
##  2 A3        4.63  1.29     1     6
##  3 A4        2.26  1.45     1     6
##  4 A5        4.59  1.25     1     6
##  5 C1        4.56  1.22     1     6
##  6 C2        4.40  1.31     1     6
##  7 C3        4.32  1.29     1     6
##  8 C4        4.50  1.36     1     6
##  9 C5        3.74  1.63     1     6
## 10 E1        2.96  1.62     1     6
## # ℹ 14 more rows

6 4. Distribución de ítems por factor

Los histogramas muestran una tendencia alta en Amabilidad y Conciencia, baja en Extraversión, y dispersión adecuada en el resto.

plot_items <- function(prefijo, titulo) {
  cols <- grep(paste0("^", prefijo), names(bfi_clean), value = TRUE)
  ggplot(pivot_longer(bfi_clean, all_of(cols), names_to = "item"),
         aes(value)) +
    geom_histogram(binwidth = 1, fill = "steelblue", colour = "white") +
    facet_wrap(~item, ncol = 2) +
    labs(title = titulo,
         x = "Valor (escala 1-6)", y = "Frecuencia") +
    theme_minimal(base_size = 10)
}
prefijos <- c(A = "Amabilidad", C = "Conciencia", E = "Extraversión",
              N = "Neuroticismo", O = "Apertura")

for(pf in names(prefijos)) {
  g <- plot_items(pf, paste("Distribución de ítems –", prefijos[pf]))
  print(g)
}

7 5. Comparación por género

Las mujeres tienden a puntuar más alto en Amabilidad, Conciencia y Apertura. Los hombres puntúan levemente más en Extraversión y Neuroticismo.

bfi_segmentado <- bfi_clean |>
  mutate(
    Amabilidad   = rowMeans(across(starts_with("A")), na.rm = TRUE),
    Conciencia   = rowMeans(across(starts_with("C")), na.rm = TRUE),
    Extraversion = rowMeans(across(starts_with("E")), na.rm = TRUE),
    Neuroticismo = rowMeans(across(starts_with("N")), na.rm = TRUE),
    Apertura     = rowMeans(across(starts_with("O")), na.rm = TRUE),
    genero       = factor(gender, levels = c(1,2), labels = c("Hombre","Mujer"))
  )
bfi_largo <- pivot_longer(bfi_segmentado,
                          Amabilidad:Apertura,
                          names_to  = "factor",
                          values_to = "puntaje")
g_genero <- ggplot(bfi_largo,
                   aes(genero, puntaje, fill = genero)) +
  geom_boxplot(alpha = .70, outlier.size = 1.2) +
  facet_wrap(~factor, scales = "free", nrow = 2) +
  scale_fill_manual(values = c("#F8766D","#00BFC4")) +
  labs(title = "Comparación de factores de personalidad por género",
       x = "Género", y = "Puntaje promedio por factor") +
  theme_minimal(base_size = 10) +
  theme(legend.position = "none")
print(g_genero)

8 6. Fiabilidad de los factores

Se evalúa la consistencia interna mediante alfa de Cronbach (α). Cuatro factores muestran valores aceptables (> .70), excepto Apertura (α = .56), lo que sugiere revisión de ítems.

factores <- list(
  Amabilidad   = grep("^A", names(bfi_clean), value = TRUE),
  Conciencia   = grep("^C", names(bfi_clean), value = TRUE),
  Extraversion = grep("^E", names(bfi_clean), value = TRUE),
  Neuroticismo = grep("^N", names(bfi_clean), value = TRUE),
  Apertura     = grep("^O", names(bfi_clean), value = TRUE)
)
lapply(factores, function(v) psych::alpha(bfi_clean[, v], check.keys = TRUE)$total$raw_alpha)
## $Amabilidad
## [1] 0.721423
## 
## $Conciencia
## [1] 0.7312899
## 
## $Extraversion
## [1] 0.7691843
## 
## $Neuroticismo
## [1] 0.8156476
## 
## $Apertura
## [1] 0.5634645

9 7. Análisis factorial confirmatorio (CFA)

El modelo CFA muestra ajuste aceptable pero no óptimo. CFI y TLI son cercanos a .90, y RMSEA indica ajuste moderado. La estructura de cinco factores se mantiene.

model_bfi <- '
  Amabilidad   =~ A2 + A3 + A4 + A5
  Conciencia   =~ C1 + C2 + C3 + C4 + C5
  Extraversion =~ E1 + E2 + E3 + E4 + E5
  Neuroticismo =~ N1 + N2 + N3 + N4 + N5
  Apertura     =~ O1 + O3
  C1 ~~ C2
  N1 ~~ N2
  N3 ~~ N4
'
fit_cfa <- cfa(model_bfi, data = bfi_clean,
               estimator = "WLSMV",
               ordered   = grep('^[ACENOP]', names(bfi_clean), value = TRUE),
               std.lv    = TRUE)
fitMeasures(fit_cfa)[c("cfi.scaled","tli.scaled","rmsea.scaled","srmr")]
##   cfi.scaled   tli.scaled rmsea.scaled         srmr 
##   0.88177439   0.85893535   0.09046218   0.07087932

10 8. Modelo SEM con edad y educación

Se incluye edad y educación como covariables. La estructura factorial se conserva y los efectos son pequeños pero significativos en algunos factores.

bfi_sem <- bfi_clean |>
  mutate(age_c       = scale(age, TRUE, FALSE)[,1],
         education_c = scale(education, TRUE, FALSE)[,1])
sem_bfi <- paste(model_bfi, "
  Amabilidad   ~ age_c + education_c
  Conciencia   ~ age_c + education_c
  Extraversion ~ age_c + education_c
  Neuroticismo ~ age_c + education_c
  Apertura     ~ age_c + education_c
")
fit_sem <- sem(sem_bfi, data = bfi_sem,
               estimator = "WLSMV",
               ordered   = grep('^[ACENOP]', names(bfi_sem), value = TRUE),
               std.lv    = TRUE)

10.1 8.1 Índices de ajuste SEM

round(fitMeasures(fit_sem)[c("cfi.scaled","tli.scaled","rmsea.scaled","srmr")], 3)
##   cfi.scaled   tli.scaled rmsea.scaled         srmr 
##        0.876        0.875        0.085        0.071

10.2 8.2 Coeficientes estandarizados (betas)

parameterEstimates(fit_sem, standardized = TRUE) |>
  filter(op == "~") |>
  select(Factor = lhs, Predictor = rhs, Beta = std.all, p = pvalue)

10.3 8.3 R² de los factores

lavInspect(fit_sem, "rsquare")
##           A2           A3           A4           A5           C1           C2 
##        0.409        0.580        0.293        0.620        0.257        0.290 
##           C3           C4           C5           E1           E2           E3 
##        0.308        0.565        0.547        0.290        0.529        0.493 
##           E4           E5           N1           N2           N3           N4 
##        0.589        0.386        0.428        0.390        0.729        0.694 
##           N5           O1           O3   Amabilidad   Conciencia Extraversion 
##        0.338        0.371        0.557        0.019        0.015        0.005 
## Neuroticismo     Apertura 
##        0.015        0.012

11 9. Diagrama SEM final

El diagrama ilustra cargas factoriales y efectos de edad y educación en los cinco factores.

lavaanPlot(model = fit_sem, stand = TRUE, coef = TRUE,
           graph_options = list(rankdir = "LR", layout = "dot", splines = "polyline"),
           node_options  = list(shape = "box", fontsize = 12, width = 1.2, height = 0.6, fixedsize = FALSE),
           edge_options  = list(fontsize = 10, minlen = 2, arrowsize = 0.6))

12 Conclusiones generales

  • La estructura del Big Five se sostiene con buena fiabilidad general.
  • La variable Apertura presenta menor consistencia (α = .56).
  • Edad influye levemente en Amabilidad, Conciencia, Neuroticismo y Extraversión.
  • Educación se asocia principalmente con Apertura.
  • Los efectos son pequeños (R² < 2 %), sugiriendo explorar más predictores.