Hierarchical Categorical Confirmation Factor Analysis - Private-Projects237/Statistics GitHub Wiki
Overview
This wikipage will go through an example of a hierarchical categorical confirmation factor analysis (CFA).
Step 1: Generating the data
# load in packages
library(MASS)
library(lavaan)
# Set seed
set.seed(321)
# Inputs (set the sample sizes and the factor loadings/betas)
N <- 500
beta <- c(0.80, 0.70, 0.60)
lambda_mat <- list(
F1 = c(1.00, 0.90, 0.80, 1.10, 1.00),
F2 = c(1.00, 1.10, 0.90, 1.00, 1.20),
F3 = c(1.00, 0.90, 1.20, 1.00, 1.00)
)
# Create a custom function to transform numeric values into categorical responses
thresholds <- c(-0.5, 0.5) # two cut-points → 3 categories (0,1,2)
make_ordinal <- function(z, thr = thresholds, labels = 0:2) {
cut(z, breaks = c(-Inf, thr, Inf), labels = labels, ordered_result = TRUE)
}
# Create a distribution for the hierarchical factor
G <- rnorm(N, 0, 1)
# Create the distributions for the first order factors
delta_sd <- sqrt(1 - beta^2)
F1 <- beta[1] * G + rnorm(N, 0, delta_sd[1])
F2 <- beta[2] * G + rnorm(N, 0, delta_sd[2])
F3 <- beta[3] * G + rnorm(N, 0, delta_sd[3])
# Genrating the responses for each items
gen_items <- function(theta, lambdas) {
mapply(function(lam) make_ordinal(lam * theta + rnorm(N)),
lam = lambdas,
SIMPLIFY = FALSE)
}
items <- data.frame(
# F1 items
gen_items(F1, lambda_mat$F1),
# F2 items
gen_items(F2, lambda_mat$F2),
# F3 items
gen_items(F3, lambda_mat$F3)
)
# Give the columns sensible names
names(items) <- paste0("item", 1:ncol(items))
Step 2: Specifying the model
# Set the hierarchical model
hier_model <- '
# first-order
F1 =~ 1*item1 + item2 + item3 + item4 + item5
F2 =~ 1*item6 + item7 + item8 + item9 + item10
F3 =~ 1*item11 + item12 + item13 + item14 + item15
# second-order
G =~ NA*F1 + F2 + F3
# fix variance of the second order factor
G ~~ 1*G
'
Step 3: Making Sense of the Model Output
summary(fit_hier, standardized = TRUE, fit.measures = TRUE)
parameterEstimates(fit_hier)
standardizedSolution(fit_hier)
inspect(fit_hier, "r2")
Step 4: Visualizing the Path Diagram
# Plot the path diagram
library(semPlot)
semPaths(fit_hier,
what = "std", # Standardized estimates
whatLabels = "std", # Show estimated values
layout = "tree", # Hierarchical layout
edge.label.cex = .9, # Edge label size
node.label.cex = 1, # Node label size
sizeMan = 7, # Size of item rectangles
sizeMan2 = 4,
sizeLat = 6, # Size of factor ovals
edge.color = "black", # Black edges for clarity
nodeLabels = c("Item 1", "Item 2", "Item 3", "Item 4", "Item 5",
"Item 6", "Item 7", "Item 8", "Item 9", "Item 10",
"Item 11", "Item 12", "Item 13", "Item 14", "Item 15",
"Factor 1", "Factor 2", "Factor 3", "G"), # Custom labels
residuals = TRUE, # Show residual variances
exoCov = TRUE, # Show factor correlations
intercepts = FALSE, # Exclude intercepts
title = FALSE, # Custom title added later
curve = 1, # Curved arrows for correlations
rotation = 2, # Vertical orientation for items
normalize = FALSE, # mitigates overlap between indicators
weighted = FALSE, # gets rid of dumb thickness in the lines
mar = c(3,9,3,10), # D L U R
)
The Path Diagram of the hierarchical categorical CFA (Standardized) |
---|