Module 5 case review activity: Factor Analysis

Author

Elizabeth Cloude

Published

June 5, 2025

In this code-along, you’ll learn how to perform Confirmatory Factor Analysis (CFA) and Exploratory Factor Analysis (EFA) on the Academic Motivation Scale (AMS). We will replicate what (guay2015application?) did in their paper, by specifically following Study 1, where they compared the fit between CFA and exploratory structural equation modeling. For purposes of this code along, we will focus on running CFA and EFA as methods that help us either identify or confirm whether the underlying factor structure of motivation aligns with theoretical models like Deci and Ryan’s Self-Determination Theory (SDT).

Motivation is defined as a multidimensional concept that varies in terms of quality. SDT proposes different types of motivation that reflect different levels of self-determination (i.e., the extent to which behavior originates from the self) (deci2012self?). SDT outlines several different types of motivation: intrinsic, extrinsix, and amotivation.

  1. Intrinsic motivation is the most self-determined form of motivation, and occurs when a person engages in an activity for its own sake, for the pleasure and satisfaction derived, which can be broken down into further categories:
    • To know: pleasure and satisfaction in learning, exploring, and trying to understand something new,
    • To experimence simulation: sensations, excitement, or aesthetic enjoyment associated with the activity, and
    • To accomplish: satisfaction and pleasure derived from trying to surpass oneself or to accomplish or create something.
  2. Extrinsic motivation involves engaging in an activity as a mean to an end rather than for its intrinsic qualities, which can be broken down into further categories:
    • Identified: occurs when behaviors are performed by choice, because the individual considers them important,
    • Introjected: when behaviors are partly internalized, but not fully coherent with other aspects of the self, and
    • External: refers to behaviors that are not self-determined, and are instead regulated by external means such as rewards and constraints.
  3. Amotivation: characterized by a lack of intentionality, or a relative lack of motivation (intrinsic or extrinsic).

Motivation types are expected to show a simplex like patterns of correlations, with stronger positive correlations between adjacent than distant motivations (ryan1989perceived?). These patterns of correlations are frequently used to test the convergent and divergent validity of scores of motivational instruments developed in light of SDT.

CFA and EFA are distinct from each other in that, CFA is built to confirm the factors that we indicate are present, whereas EFA will estimate freely, such that items can load onto multiple factors. In this way, with CFA, we are testing a hypothesized factor structure, whereas with EFA, we are discovering underlying factor structures.

Before we get started, let’s make sure we have the right packages installed and loaded.

# Load required libraries
#install.packages("lavaan") ensure this package is downloaded.
library(lavaan)
This is lavaan 0.6-19
lavaan is FREE software! Please report any bugs.
library(psych)

Attaching package: 'psych'
The following object is masked from 'package:lavaan':

    cor2cov
if (!require("polycor")) {
  install.packages("polycor", repos = "https://cloud.r-project.org") # download packaged from this source.
}
Loading required package: polycor

Attaching package: 'polycor'
The following object is masked from 'package:psych':

    polyserial
library(polycor)
library(tidyverse)
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.4     ✔ readr     2.1.5
✔ forcats   1.0.0     ✔ stringr   1.5.1
✔ ggplot2   3.5.1     ✔ tibble    3.2.1
✔ lubridate 1.9.4     ✔ tidyr     1.3.1
✔ purrr     1.0.4     
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ ggplot2::%+%()   masks psych::%+%()
✖ ggplot2::alpha() masks psych::alpha()
✖ dplyr::filter()  masks stats::filter()
✖ dplyr::lag()     masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(MASS)  # for mvrnorm

Attaching package: 'MASS'

The following object is masked from 'package:dplyr':

    select
library(corrplot)
corrplot 0.95 loaded

Next, we need to generate data with a similar structure as the AMS scale, representing 28 items with 1,416 responses.

set.seed(123)

n <- 1416  # number of participants from Study 1

n_factors <- 7
items_per_factor <- 4

# Create a correlation matrix: only F1 and F2 correlated
latent_cor <- diag(n_factors)
latent_cor[1, 2] <- 0.4
latent_cor[2, 1] <- 0.4

# Simulate latent variables
latent_factors <- MASS::mvrnorm(n, mu = rep(0, n_factors), Sigma = latent_cor)

# Simulate 28 items (4 per factor)
items <- list()
for (f in 1:n_factors) {
  for (i in 1:items_per_factor) {
    # Generate item response from latent factor + noise
    signal <- latent_factors[, f] + rnorm(n, 0, 0.6)
    
    # Convert to Likert-scale (1–7)
    item <- cut(signal,
                breaks = quantile(signal, probs = seq(0, 1, length.out = 8), na.rm = TRUE),
                include.lowest = TRUE,
                labels = FALSE)
    
    items[[length(items) + 1]] <- item
  }
}

# Assemble into a dataframe
ams_data <- as.data.frame(items)
colnames(ams_data) <- paste0("Q", 1:(n_factors * items_per_factor))

# Convert to ordered for CFA/EFA
ams_ord <- ams_data %>%
  mutate(across(everything(), ordered))
head(ams_data)
  Q1 Q2 Q3 Q4 Q5 Q6 Q7 Q8 Q9 Q10 Q11 Q12 Q13 Q14 Q15 Q16 Q17 Q18 Q19 Q20 Q21
1  3  2  2  4  2  5  6  2  3   6   5   5   6   4   6   5   4   5   4   4   1
2  3  4  1  2  5  5  5  4  2   2   1   1   2   3   6   2   3   4   2   3   4
3  7  7  7  6  6  6  5  6  1   1   1   1   4   7   7   7   2   6   5   6   3
4  5  6  3  3  2  3  4  6  6   7   7   6   6   5   5   5   6   4   3   4   3
5  5  7  1  3  5  5  4  6  5   5   5   3   3   1   1   1   6   6   6   6   7
6  7  6  6  6  6  6  7  6  2   2   1   3   7   7   6   5   4   4   6   3   4
  Q22 Q23 Q24 Q25 Q26 Q27 Q28
1   2   2   1   6   5   4   5
2   2   5   2   5   1   6   2
3   2   5   2   7   6   5   7
4   2   5   1   3   4   6   5
5   7   6   7   3   3   3   3
6   5   4   4   5   5   4   7
head(ams_ord)
  Q1 Q2 Q3 Q4 Q5 Q6 Q7 Q8 Q9 Q10 Q11 Q12 Q13 Q14 Q15 Q16 Q17 Q18 Q19 Q20 Q21
1  3  2  2  4  2  5  6  2  3   6   5   5   6   4   6   5   4   5   4   4   1
2  3  4  1  2  5  5  5  4  2   2   1   1   2   3   6   2   3   4   2   3   4
3  7  7  7  6  6  6  5  6  1   1   1   1   4   7   7   7   2   6   5   6   3
4  5  6  3  3  2  3  4  6  6   7   7   6   6   5   5   5   6   4   3   4   3
5  5  7  1  3  5  5  4  6  5   5   5   3   3   1   1   1   6   6   6   6   7
6  7  6  6  6  6  6  7  6  2   2   1   3   7   7   6   5   4   4   6   3   4
  Q22 Q23 Q24 Q25 Q26 Q27 Q28
1   2   2   1   6   5   4   5
2   2   5   2   5   1   6   2
3   2   5   2   7   6   5   7
4   2   5   1   3   4   6   5
5   7   6   7   3   3   3   3
6   5   4   4   5   5   4   7

Now we will build our 7-factor CFA model, the one that does not account for cross-factor loadings. Below, we indicate which questionnaire items should load onto each factor. You can see that each factor had four items each. For CFA, we tell the model which factors we have and we use it to confirm the factor structure.

ams_model <- '
Intrinsic_Motivation_to_Know =~ Q1 + Q2 + Q3 + Q4
Intrinsic_Motivation_to_Accomplish =~ Q5 + Q6 + Q7 + Q8
Intrinsic_Stimulation =~ Q9 + Q10 + Q11 + Q12
Identified_Regulation =~ Q13 + Q14 + Q15 + Q16
Introjected_Regulation =~ Q17 + Q18 + Q19 + Q20
External_Regulation =~ Q21 + Q22 + Q23 + Q24
Amotivation =~ Q25 + Q26 + Q27 + Q28
'

When running CFA on ordinal (Likert-type) data, especially when using WLSMV estimation, the estimator for categorical variables. The data we have imply order, but the distances between them aren’t equal (e.g., the psychological distance between 2 and 3 may not be the same as between 6 and 7 universally). So, treating our data as interval/continuous (like standard Pearson correlations assume) can distort the relationships among items. Instead, we use polychoric correlations, which estimate the correlation between underlying continuous latent variables assumed to drive the ordinal responses.

Now we will estimate the polychoric correlation matrix.

# Get polychoric correlation matrix
poly_cor <- psych::polychoric(ams_ord)$rho
Converted non-numeric input to numeric
# Visualize using corrplot
corrplot::corrplot(
  poly_cor,
  method = "color",
  type = "upper",
  order = "hclust",
  tl.col = "black",
  tl.cex = 0.6,
  addCoef.col = "black",
  number.cex = 0.5
)

Notice the dark blue patterns on the edge of the scatterplot. You will noticed that each of the four items, that are separated across factors, are highly correlated with other items in the same factor. This may suggest that there are no cross-loadings in these instances, however, there appears to be a correlation between items in one factor (items 5-8) with items in another factor (items 9-12). We also see relatively weak negative correlations between some of the items with other items in different factors.

To get a better sense, let’s also check correlations between the average of each factor, when we average the underlying items together, and assess whether there may be correlations between the factors at the scale level.

# Convert ordered factors to numeric for averaging
ams_numeric <- ams_ord %>% mutate(across(everything(), ~ as.numeric(as.character(.))))

# Define subscale (factor) names and item mappings
factor_map <- list(
  Intrinsic_Know = paste0("Q", 1:4),
  Intrinsic_Accomplish = paste0("Q", 5:8),
  Intrinsic_Stimulation = paste0("Q", 9:12),
  Identified_Regulation = paste0("Q", 13:16),
  Introjected_Regulation = paste0("Q", 17:20),
  External_Regulation = paste0("Q", 21:24),
  Amotivation = paste0("Q", 25:28)
)

# Create new dataframe with average scores per factor
ams_subscales <- lapply(factor_map, function(items) {
  rowMeans(ams_numeric[, items])
}) %>% as.data.frame()
# Run Pearson correlation
subscale_corr <- cor(ams_subscales[,-1])

corrplot(subscale_corr,
         method = "color",
         type = "upper",
         order = "hclust",
         addCoef.col = "black",
         tl.cex = 0.8)

Take note that the averaged items within factors demonstrate some weak correlations when aggregated by item averages. But the correlations do not appear to be too strong. Let’s proceed with CFA followed by EFA.

CFA

Now we will fit our initial CFA model to assess the goodness-of-fit, without accounting for the cross-loadings.

cfa_fit <- lavaan::cfa(
  model = ams_model,
  data = ams_ord,
  estimator = "WLSMV",
  ordered = colnames(ams_ord),
  std.lv = TRUE
)

summary(cfa_fit, fit.measures = TRUE, standardized = TRUE)
lavaan 0.6-19 ended normally after 14 iterations

  Estimator                                       DWLS
  Optimization method                           NLMINB
  Number of model parameters                       217

  Number of observations                          1416

Model Test User Model:
                                              Standard      Scaled
  Test Statistic                               144.515     336.165
  Degrees of freedom                               329         329
  P-value (Chi-square)                           1.000       0.381
  Scaling correction factor                                  0.636
  Shift parameter                                          109.006
    simple second-order correction                                

Model Test Baseline Model:

  Test statistic                            119159.887   47816.265
  Degrees of freedom                               378         378
  P-value                                        0.000       0.000
  Scaling correction factor                                  2.504

User Model versus Baseline Model:

  Comparative Fit Index (CFI)                    1.000       1.000
  Tucker-Lewis Index (TLI)                       1.002       1.000
                                                                  
  Robust Comparative Fit Index (CFI)                         0.999
  Robust Tucker-Lewis Index (TLI)                            0.999

Root Mean Square Error of Approximation:

  RMSEA                                          0.000       0.004
  90 Percent confidence interval - lower         0.000       0.000
  90 Percent confidence interval - upper         0.000       0.011
  P-value H_0: RMSEA <= 0.050                    1.000       1.000
  P-value H_0: RMSEA >= 0.080                    0.000       0.000
                                                                  
  Robust RMSEA                                               0.008
  90 Percent confidence interval - lower                     0.000
  90 Percent confidence interval - upper                     0.015
  P-value H_0: Robust RMSEA <= 0.050                         1.000
  P-value H_0: Robust RMSEA >= 0.080                         0.000

Standardized Root Mean Square Residual:

  SRMR                                           0.017       0.017

Parameter Estimates:

  Parameterization                               Delta
  Standard errors                           Robust.sem
  Information                                 Expected
  Information saturated (h1) model        Unstructured

Latent Variables:
                                        Estimate  Std.Err  z-value  P(>|z|)
  Intrinsic_Motivation_to_Know =~                                          
    Q1                                     0.870    0.010   89.068    0.000
    Q2                                     0.858    0.010   84.488    0.000
    Q3                                     0.844    0.011   78.839    0.000
    Q4                                     0.850    0.010   82.962    0.000
  Intrinsic_Motivation_to_Accomplish =~                                    
    Q5                                     0.858    0.010   85.787    0.000
    Q6                                     0.856    0.010   87.405    0.000
    Q7                                     0.852    0.010   82.921    0.000
    Q8                                     0.854    0.010   82.838    0.000
  Intrinsic_Stimulation =~                                                 
    Q9                                     0.856    0.010   84.809    0.000
    Q10                                    0.869    0.009   93.960    0.000
    Q11                                    0.854    0.010   84.208    0.000
    Q12                                    0.873    0.010   90.336    0.000
  Identified_Regulation =~                                                 
    Q13                                    0.858    0.010   82.508    0.000
    Q14                                    0.860    0.010   85.468    0.000
    Q15                                    0.852    0.010   82.509    0.000
    Q16                                    0.851    0.011   80.494    0.000
  Introjected_Regulation =~                                                
    Q17                                    0.847    0.011   79.842    0.000
    Q18                                    0.863    0.010   88.288    0.000
    Q19                                    0.854    0.011   79.477    0.000
    Q20                                    0.858    0.010   82.643    0.000
  External_Regulation =~                                                   
    Q21                                    0.845    0.011   76.938    0.000
    Q22                                    0.842    0.011   78.796    0.000
    Q23                                    0.849    0.011   80.641    0.000
    Q24                                    0.875    0.010   91.927    0.000
  Amotivation =~                                                           
    Q25                                    0.858    0.010   88.457    0.000
    Q26                                    0.855    0.010   87.193    0.000
    Q27                                    0.847    0.010   81.648    0.000
    Q28                                    0.873    0.009   92.003    0.000
   Std.lv  Std.all
                  
    0.870    0.870
    0.858    0.858
    0.844    0.844
    0.850    0.850
                  
    0.858    0.858
    0.856    0.856
    0.852    0.852
    0.854    0.854
                  
    0.856    0.856
    0.869    0.869
    0.854    0.854
    0.873    0.873
                  
    0.858    0.858
    0.860    0.860
    0.852    0.852
    0.851    0.851
                  
    0.847    0.847
    0.863    0.863
    0.854    0.854
    0.858    0.858
                  
    0.845    0.845
    0.842    0.842
    0.849    0.849
    0.875    0.875
                  
    0.858    0.858
    0.855    0.855
    0.847    0.847
    0.873    0.873

Covariances:
                                        Estimate  Std.Err  z-value  P(>|z|)
  Intrinsic_Motivation_to_Know ~~                                          
    Intrnsc_Mtv__A                         0.416    0.025   16.498    0.000
    Intrnsc_Stmltn                         0.036    0.030    1.208    0.227
    Identifd_Rgltn                        -0.014    0.030   -0.468    0.640
    Intrjctd_Rgltn                         0.016    0.030    0.547    0.584
    External_Rgltn                         0.009    0.030    0.305    0.760
    Amotivation                           -0.003    0.030   -0.096    0.924
  Intrinsic_Motivation_to_Accomplish ~~                                    
    Intrnsc_Stmltn                         0.051    0.029    1.725    0.085
    Identifd_Rgltn                        -0.028    0.030   -0.937    0.349
    Intrjctd_Rgltn                         0.054    0.030    1.830    0.067
    External_Rgltn                         0.019    0.030    0.644    0.520
    Amotivation                           -0.005    0.030   -0.183    0.855
  Intrinsic_Stimulation ~~                                                 
    Identifd_Rgltn                        -0.041    0.030   -1.385    0.166
    Intrjctd_Rgltn                        -0.010    0.030   -0.350    0.726
    External_Rgltn                        -0.006    0.030   -0.198    0.843
    Amotivation                           -0.023    0.030   -0.762    0.446
  Identified_Regulation ~~                                                 
    Intrjctd_Rgltn                        -0.021    0.030   -0.716    0.474
    External_Rgltn                        -0.024    0.030   -0.785    0.433
    Amotivation                           -0.008    0.030   -0.278    0.781
  Introjected_Regulation ~~                                                
    External_Rgltn                        -0.005    0.030   -0.177    0.859
    Amotivation                            0.037    0.030    1.217    0.224
  External_Regulation ~~                                                   
    Amotivation                            0.008    0.030    0.277    0.782
   Std.lv  Std.all
                  
    0.416    0.416
    0.036    0.036
   -0.014   -0.014
    0.016    0.016
    0.009    0.009
   -0.003   -0.003
                  
    0.051    0.051
   -0.028   -0.028
    0.054    0.054
    0.019    0.019
   -0.005   -0.005
                  
   -0.041   -0.041
   -0.010   -0.010
   -0.006   -0.006
   -0.023   -0.023
                  
   -0.021   -0.021
   -0.024   -0.024
   -0.008   -0.008
                  
   -0.005   -0.005
    0.037    0.037
                  
    0.008    0.008

Thresholds:
                   Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.all
    Q1|t1            -1.065    0.041  -25.865    0.000   -1.065   -1.065
    Q1|t2            -0.565    0.035  -15.996    0.000   -0.565   -0.565
    Q1|t3            -0.180    0.034   -5.364    0.000   -0.180   -0.180
    Q1|t4             0.180    0.034    5.364    0.000    0.180    0.180
    Q1|t5             0.565    0.035   15.996    0.000    0.565    0.565
    Q1|t6             1.065    0.041   25.865    0.000    1.065    1.065
    Q2|t1            -1.065    0.041  -25.865    0.000   -1.065   -1.065
    Q2|t2            -0.565    0.035  -15.996    0.000   -0.565   -0.565
    Q2|t3            -0.180    0.034   -5.364    0.000   -0.180   -0.180
    Q2|t4             0.180    0.034    5.364    0.000    0.180    0.180
    Q2|t5             0.565    0.035   15.996    0.000    0.565    0.565
    Q2|t6             1.065    0.041   25.865    0.000    1.065    1.065
    Q3|t1            -1.065    0.041  -25.865    0.000   -1.065   -1.065
    Q3|t2            -0.565    0.035  -15.996    0.000   -0.565   -0.565
    Q3|t3            -0.180    0.034   -5.364    0.000   -0.180   -0.180
    Q3|t4             0.180    0.034    5.364    0.000    0.180    0.180
    Q3|t5             0.565    0.035   15.996    0.000    0.565    0.565
    Q3|t6             1.065    0.041   25.865    0.000    1.065    1.065
    Q4|t1            -1.065    0.041  -25.865    0.000   -1.065   -1.065
    Q4|t2            -0.565    0.035  -15.996    0.000   -0.565   -0.565
    Q4|t3            -0.180    0.034   -5.364    0.000   -0.180   -0.180
    Q4|t4             0.180    0.034    5.364    0.000    0.180    0.180
    Q4|t5             0.565    0.035   15.996    0.000    0.565    0.565
    Q4|t6             1.065    0.041   25.865    0.000    1.065    1.065
    Q5|t1            -1.065    0.041  -25.865    0.000   -1.065   -1.065
    Q5|t2            -0.565    0.035  -15.996    0.000   -0.565   -0.565
    Q5|t3            -0.180    0.034   -5.364    0.000   -0.180   -0.180
    Q5|t4             0.180    0.034    5.364    0.000    0.180    0.180
    Q5|t5             0.565    0.035   15.996    0.000    0.565    0.565
    Q5|t6             1.065    0.041   25.865    0.000    1.065    1.065
    Q6|t1            -1.065    0.041  -25.865    0.000   -1.065   -1.065
    Q6|t2            -0.565    0.035  -15.996    0.000   -0.565   -0.565
    Q6|t3            -0.180    0.034   -5.364    0.000   -0.180   -0.180
    Q6|t4             0.180    0.034    5.364    0.000    0.180    0.180
    Q6|t5             0.565    0.035   15.996    0.000    0.565    0.565
    Q6|t6             1.065    0.041   25.865    0.000    1.065    1.065
    Q7|t1            -1.065    0.041  -25.865    0.000   -1.065   -1.065
    Q7|t2            -0.565    0.035  -15.996    0.000   -0.565   -0.565
    Q7|t3            -0.180    0.034   -5.364    0.000   -0.180   -0.180
    Q7|t4             0.180    0.034    5.364    0.000    0.180    0.180
    Q7|t5             0.565    0.035   15.996    0.000    0.565    0.565
    Q7|t6             1.065    0.041   25.865    0.000    1.065    1.065
    Q8|t1            -1.065    0.041  -25.865    0.000   -1.065   -1.065
    Q8|t2            -0.565    0.035  -15.996    0.000   -0.565   -0.565
    Q8|t3            -0.180    0.034   -5.364    0.000   -0.180   -0.180
    Q8|t4             0.180    0.034    5.364    0.000    0.180    0.180
    Q8|t5             0.565    0.035   15.996    0.000    0.565    0.565
    Q8|t6             1.065    0.041   25.865    0.000    1.065    1.065
    Q9|t1            -1.065    0.041  -25.865    0.000   -1.065   -1.065
    Q9|t2            -0.565    0.035  -15.996    0.000   -0.565   -0.565
    Q9|t3            -0.180    0.034   -5.364    0.000   -0.180   -0.180
    Q9|t4             0.180    0.034    5.364    0.000    0.180    0.180
    Q9|t5             0.565    0.035   15.996    0.000    0.565    0.565
    Q9|t6             1.065    0.041   25.865    0.000    1.065    1.065
    Q10|t1           -1.065    0.041  -25.865    0.000   -1.065   -1.065
    Q10|t2           -0.565    0.035  -15.996    0.000   -0.565   -0.565
    Q10|t3           -0.180    0.034   -5.364    0.000   -0.180   -0.180
    Q10|t4            0.180    0.034    5.364    0.000    0.180    0.180
    Q10|t5            0.565    0.035   15.996    0.000    0.565    0.565
    Q10|t6            1.065    0.041   25.865    0.000    1.065    1.065
    Q11|t1           -1.065    0.041  -25.865    0.000   -1.065   -1.065
    Q11|t2           -0.565    0.035  -15.996    0.000   -0.565   -0.565
    Q11|t3           -0.180    0.034   -5.364    0.000   -0.180   -0.180
    Q11|t4            0.180    0.034    5.364    0.000    0.180    0.180
    Q11|t5            0.565    0.035   15.996    0.000    0.565    0.565
    Q11|t6            1.065    0.041   25.865    0.000    1.065    1.065
    Q12|t1           -1.065    0.041  -25.865    0.000   -1.065   -1.065
    Q12|t2           -0.565    0.035  -15.996    0.000   -0.565   -0.565
    Q12|t3           -0.180    0.034   -5.364    0.000   -0.180   -0.180
    Q12|t4            0.180    0.034    5.364    0.000    0.180    0.180
    Q12|t5            0.565    0.035   15.996    0.000    0.565    0.565
    Q12|t6            1.065    0.041   25.865    0.000    1.065    1.065
    Q13|t1           -1.065    0.041  -25.865    0.000   -1.065   -1.065
    Q13|t2           -0.565    0.035  -15.996    0.000   -0.565   -0.565
    Q13|t3           -0.180    0.034   -5.364    0.000   -0.180   -0.180
    Q13|t4            0.180    0.034    5.364    0.000    0.180    0.180
    Q13|t5            0.565    0.035   15.996    0.000    0.565    0.565
    Q13|t6            1.065    0.041   25.865    0.000    1.065    1.065
    Q14|t1           -1.065    0.041  -25.865    0.000   -1.065   -1.065
    Q14|t2           -0.565    0.035  -15.996    0.000   -0.565   -0.565
    Q14|t3           -0.180    0.034   -5.364    0.000   -0.180   -0.180
    Q14|t4            0.180    0.034    5.364    0.000    0.180    0.180
    Q14|t5            0.565    0.035   15.996    0.000    0.565    0.565
    Q14|t6            1.065    0.041   25.865    0.000    1.065    1.065
    Q15|t1           -1.065    0.041  -25.865    0.000   -1.065   -1.065
    Q15|t2           -0.565    0.035  -15.996    0.000   -0.565   -0.565
    Q15|t3           -0.180    0.034   -5.364    0.000   -0.180   -0.180
    Q15|t4            0.180    0.034    5.364    0.000    0.180    0.180
    Q15|t5            0.565    0.035   15.996    0.000    0.565    0.565
    Q15|t6            1.065    0.041   25.865    0.000    1.065    1.065
    Q16|t1           -1.065    0.041  -25.865    0.000   -1.065   -1.065
    Q16|t2           -0.565    0.035  -15.996    0.000   -0.565   -0.565
    Q16|t3           -0.180    0.034   -5.364    0.000   -0.180   -0.180
    Q16|t4            0.180    0.034    5.364    0.000    0.180    0.180
    Q16|t5            0.565    0.035   15.996    0.000    0.565    0.565
    Q16|t6            1.065    0.041   25.865    0.000    1.065    1.065
    Q17|t1           -1.065    0.041  -25.865    0.000   -1.065   -1.065
    Q17|t2           -0.565    0.035  -15.996    0.000   -0.565   -0.565
    Q17|t3           -0.180    0.034   -5.364    0.000   -0.180   -0.180
    Q17|t4            0.180    0.034    5.364    0.000    0.180    0.180
    Q17|t5            0.565    0.035   15.996    0.000    0.565    0.565
    Q17|t6            1.065    0.041   25.865    0.000    1.065    1.065
    Q18|t1           -1.065    0.041  -25.865    0.000   -1.065   -1.065
    Q18|t2           -0.565    0.035  -15.996    0.000   -0.565   -0.565
    Q18|t3           -0.180    0.034   -5.364    0.000   -0.180   -0.180
    Q18|t4            0.180    0.034    5.364    0.000    0.180    0.180
    Q18|t5            0.565    0.035   15.996    0.000    0.565    0.565
    Q18|t6            1.065    0.041   25.865    0.000    1.065    1.065
    Q19|t1           -1.065    0.041  -25.865    0.000   -1.065   -1.065
    Q19|t2           -0.565    0.035  -15.996    0.000   -0.565   -0.565
    Q19|t3           -0.180    0.034   -5.364    0.000   -0.180   -0.180
    Q19|t4            0.180    0.034    5.364    0.000    0.180    0.180
    Q19|t5            0.565    0.035   15.996    0.000    0.565    0.565
    Q19|t6            1.065    0.041   25.865    0.000    1.065    1.065
    Q20|t1           -1.065    0.041  -25.865    0.000   -1.065   -1.065
    Q20|t2           -0.565    0.035  -15.996    0.000   -0.565   -0.565
    Q20|t3           -0.180    0.034   -5.364    0.000   -0.180   -0.180
    Q20|t4            0.180    0.034    5.364    0.000    0.180    0.180
    Q20|t5            0.565    0.035   15.996    0.000    0.565    0.565
    Q20|t6            1.065    0.041   25.865    0.000    1.065    1.065
    Q21|t1           -1.065    0.041  -25.865    0.000   -1.065   -1.065
    Q21|t2           -0.565    0.035  -15.996    0.000   -0.565   -0.565
    Q21|t3           -0.180    0.034   -5.364    0.000   -0.180   -0.180
    Q21|t4            0.180    0.034    5.364    0.000    0.180    0.180
    Q21|t5            0.565    0.035   15.996    0.000    0.565    0.565
    Q21|t6            1.065    0.041   25.865    0.000    1.065    1.065
    Q22|t1           -1.065    0.041  -25.865    0.000   -1.065   -1.065
    Q22|t2           -0.565    0.035  -15.996    0.000   -0.565   -0.565
    Q22|t3           -0.180    0.034   -5.364    0.000   -0.180   -0.180
    Q22|t4            0.180    0.034    5.364    0.000    0.180    0.180
    Q22|t5            0.565    0.035   15.996    0.000    0.565    0.565
    Q22|t6            1.065    0.041   25.865    0.000    1.065    1.065
    Q23|t1           -1.065    0.041  -25.865    0.000   -1.065   -1.065
    Q23|t2           -0.565    0.035  -15.996    0.000   -0.565   -0.565
    Q23|t3           -0.180    0.034   -5.364    0.000   -0.180   -0.180
    Q23|t4            0.180    0.034    5.364    0.000    0.180    0.180
    Q23|t5            0.565    0.035   15.996    0.000    0.565    0.565
    Q23|t6            1.065    0.041   25.865    0.000    1.065    1.065
    Q24|t1           -1.065    0.041  -25.865    0.000   -1.065   -1.065
    Q24|t2           -0.565    0.035  -15.996    0.000   -0.565   -0.565
    Q24|t3           -0.180    0.034   -5.364    0.000   -0.180   -0.180
    Q24|t4            0.180    0.034    5.364    0.000    0.180    0.180
    Q24|t5            0.565    0.035   15.996    0.000    0.565    0.565
    Q24|t6            1.065    0.041   25.865    0.000    1.065    1.065
    Q25|t1           -1.065    0.041  -25.865    0.000   -1.065   -1.065
    Q25|t2           -0.565    0.035  -15.996    0.000   -0.565   -0.565
    Q25|t3           -0.180    0.034   -5.364    0.000   -0.180   -0.180
    Q25|t4            0.180    0.034    5.364    0.000    0.180    0.180
    Q25|t5            0.565    0.035   15.996    0.000    0.565    0.565
    Q25|t6            1.065    0.041   25.865    0.000    1.065    1.065
    Q26|t1           -1.065    0.041  -25.865    0.000   -1.065   -1.065
    Q26|t2           -0.565    0.035  -15.996    0.000   -0.565   -0.565
    Q26|t3           -0.180    0.034   -5.364    0.000   -0.180   -0.180
    Q26|t4            0.180    0.034    5.364    0.000    0.180    0.180
    Q26|t5            0.565    0.035   15.996    0.000    0.565    0.565
    Q26|t6            1.065    0.041   25.865    0.000    1.065    1.065
    Q27|t1           -1.065    0.041  -25.865    0.000   -1.065   -1.065
    Q27|t2           -0.565    0.035  -15.996    0.000   -0.565   -0.565
    Q27|t3           -0.180    0.034   -5.364    0.000   -0.180   -0.180
    Q27|t4            0.180    0.034    5.364    0.000    0.180    0.180
    Q27|t5            0.565    0.035   15.996    0.000    0.565    0.565
    Q27|t6            1.065    0.041   25.865    0.000    1.065    1.065
    Q28|t1           -1.065    0.041  -25.865    0.000   -1.065   -1.065
    Q28|t2           -0.565    0.035  -15.996    0.000   -0.565   -0.565
    Q28|t3           -0.180    0.034   -5.364    0.000   -0.180   -0.180
    Q28|t4            0.180    0.034    5.364    0.000    0.180    0.180
    Q28|t5            0.565    0.035   15.996    0.000    0.565    0.565
    Q28|t6            1.065    0.041   25.865    0.000    1.065    1.065

Variances:
                   Estimate  Std.Err  z-value  P(>|z|)   Std.lv  Std.all
   .Q1                0.243                               0.243    0.243
   .Q2                0.264                               0.264    0.264
   .Q3                0.287                               0.287    0.287
   .Q4                0.277                               0.277    0.277
   .Q5                0.263                               0.263    0.263
   .Q6                0.267                               0.267    0.267
   .Q7                0.275                               0.275    0.275
   .Q8                0.271                               0.271    0.271
   .Q9                0.268                               0.268    0.268
   .Q10               0.245                               0.245    0.245
   .Q11               0.271                               0.271    0.271
   .Q12               0.237                               0.237    0.237
   .Q13               0.263                               0.263    0.263
   .Q14               0.260                               0.260    0.260
   .Q15               0.274                               0.274    0.274
   .Q16               0.275                               0.275    0.275
   .Q17               0.283                               0.283    0.283
   .Q18               0.255                               0.255    0.255
   .Q19               0.270                               0.270    0.270
   .Q20               0.265                               0.265    0.265
   .Q21               0.286                               0.286    0.286
   .Q22               0.292                               0.292    0.292
   .Q23               0.280                               0.280    0.280
   .Q24               0.235                               0.235    0.235
   .Q25               0.264                               0.264    0.264
   .Q26               0.270                               0.270    0.270
   .Q27               0.282                               0.282    0.282
   .Q28               0.238                               0.238    0.238
    Intrnsc_Mtv__K    1.000                               1.000    1.000
    Intrnsc_Mtv__A    1.000                               1.000    1.000
    Intrnsc_Stmltn    1.000                               1.000    1.000
    Identifd_Rgltn    1.000                               1.000    1.000
    Intrjctd_Rgltn    1.000                               1.000    1.000
    External_Rgltn    1.000                               1.000    1.000
    Amotivation       1.000                               1.000    1.000

The output for CFA is quite extensive, but provide lots of detailed information such that we can determine the fit of the model. We can first reference the Latent Varialbes output, where we can gather information on the factor loadings. Generally, it is good practice to set a threshold for loadings as such:

  • = .7 is a strong loading,

  • .69 - .4 is a moderate loading, and

  • < .4 is a weak loading.

We can see that across all of the items for each factor demonstrate factor loadings > .84, suggesting that each of the items assigned to the factor demonstrate strong loadings.

To evaluate the goodness-of-fit, researchers often standard metrics that we have already talked about thus far (AIC, RMSEA, BIC). In the case of CFA, we also have additional metrics that are useful (which are not influenced by the sample size; see below):

  • comparative fit index (CFI),
  • Tucker-Lewis Index (TLI), and
  • Root mean square error of approximation (RMSEA).

Values greater than .9 for CFI and TLI are considered to be indicative of good model fit. Values smaller than .08 or .06 for the RMSEA support respectively acceptable, good model fit. Let’s see how our model does by running the code chunk below.

fitMeasures(cfa_fit, c("cfi", "tli", "rmsea", "srmr", "aic", "bic")) # AIC and BIC are less informative under WLSMW estimation.
  cfi   tli rmsea  srmr   aic   bic 
1.000 1.002 0.000 0.017    NA    NA 

We see that the model demonstrate good fit with CFI/TFI scores above or equal to 1. Furthermore, we see that RMSEA is 0 and SRMR is nearing 0, and lower than the threshold of .06 for an acceptable fit.

It is important to note that this is a very clean factor structure, likely due to the fact that we simulated random data, instead of utilizing real data.

EFA

Now we will run the same data using EFA, but in this analysis, we will directly input the polychoric correlations matrix into the equation to account for cross-factor loadings. Specifically, we are using principal axis factoring (fm = “pa”) and oblimin rotation methods.

# Compute polychoric correlation matrix
poly_efa <- psych::polychoric(ams_ord)
Converted non-numeric input to numeric
# Run EFA with 7 factors using oblimin rotation (as in Study 1)
efa_result <- psych::fa(r = poly_efa$rho, nfactors = 7, fm = "pa", rotate = "oblimin")
Loading required namespace: GPArotation
print(efa_result)
Factor Analysis using method =  pa
Call: psych::fa(r = poly_efa$rho, nfactors = 7, rotate = "oblimin", 
    fm = "pa")
Standardized loadings (pattern matrix) based upon correlation matrix
     PA6   PA5   PA7   PA3   PA2   PA1   PA4   h2   u2 com
1   0.02  0.01  0.87 -0.01  0.00 -0.01  0.00 0.76 0.24   1
2  -0.01  0.01  0.85 -0.03  0.01  0.02  0.00 0.73 0.27   1
3  -0.01  0.00  0.85  0.05 -0.02 -0.01  0.01 0.72 0.28   1
4   0.01 -0.01  0.85 -0.01  0.01  0.01 -0.01 0.72 0.28   1
5   0.00  0.00  0.01  0.01  0.00  0.85 -0.02 0.74 0.26   1
6   0.00  0.02 -0.03 -0.01 -0.02  0.88  0.01 0.75 0.25   1
7   0.01  0.00  0.02 -0.01  0.00  0.84  0.01 0.72 0.28   1
8  -0.01 -0.02  0.01  0.01  0.02  0.84  0.01 0.73 0.27   1
9   0.86  0.01 -0.01  0.02  0.00  0.01 -0.02 0.74 0.26   1
10  0.87 -0.01  0.00  0.00  0.00  0.01  0.02 0.75 0.25   1
11  0.86  0.00  0.00 -0.02  0.01 -0.03  0.00 0.73 0.27   1
12  0.87 -0.01  0.01  0.00 -0.01  0.01 -0.01 0.76 0.24   1
13 -0.02 -0.03  0.03  0.86 -0.01 -0.03  0.02 0.74 0.26   1
14  0.00  0.01  0.00  0.86  0.01  0.00 -0.01 0.74 0.26   1
15  0.01  0.00 -0.03  0.85  0.01  0.01  0.01 0.73 0.27   1
16  0.00  0.01  0.00  0.85 -0.01  0.01 -0.02 0.72 0.28   1
17 -0.02 -0.01 -0.01  0.00  0.85  0.01  0.01 0.72 0.28   1
18  0.02 -0.01 -0.01 -0.01  0.86  0.01  0.01 0.75 0.25   1
19 -0.01 -0.01  0.01  0.00  0.86 -0.02 -0.02 0.73 0.27   1
20  0.01  0.03  0.00  0.01  0.86  0.01 -0.01 0.74 0.26   1
21  0.02  0.02  0.00  0.01  0.00  0.03  0.84 0.72 0.28   1
22 -0.02  0.00 -0.02 -0.01 -0.02 -0.03  0.84 0.71 0.29   1
23  0.01 -0.01  0.01 -0.02 -0.01  0.00  0.85 0.72 0.28   1
24  0.00 -0.01  0.01  0.02  0.02  0.00  0.88 0.77 0.23   1
25 -0.03  0.85  0.00  0.02  0.01  0.00  0.01 0.73 0.27   1
26  0.01  0.86 -0.01  0.01 -0.02  0.02 -0.01 0.73 0.27   1
27  0.00  0.85 -0.01 -0.01 -0.01  0.01 -0.01 0.72 0.28   1
28  0.02  0.87  0.02 -0.02  0.02 -0.03  0.01 0.76 0.24   1

                       PA6  PA5  PA7  PA3  PA2  PA1  PA4
SS loadings           2.98 2.95 2.94 2.94 2.93 2.93 2.91
Proportion Var        0.11 0.11 0.10 0.10 0.10 0.10 0.10
Cumulative Var        0.11 0.21 0.32 0.42 0.53 0.63 0.74
Proportion Explained  0.15 0.14 0.14 0.14 0.14 0.14 0.14
Cumulative Proportion 0.15 0.29 0.43 0.57 0.72 0.86 1.00

 With factor correlations of 
      PA6   PA5   PA7   PA3   PA2   PA1   PA4
PA6  1.00 -0.02  0.04 -0.04 -0.01  0.05 -0.01
PA5 -0.02  1.00  0.00 -0.01  0.04  0.00  0.01
PA7  0.04  0.00  1.00 -0.01  0.02  0.41  0.01
PA3 -0.04 -0.01 -0.01  1.00 -0.02 -0.03 -0.02
PA2 -0.01  0.04  0.02 -0.02  1.00  0.05  0.00
PA1  0.05  0.00  0.41 -0.03  0.05  1.00  0.02
PA4 -0.01  0.01  0.01 -0.02  0.00  0.02  1.00

Mean item complexity =  1
Test of the hypothesis that 7 factors are sufficient.

df null model =  378  with the objective function =  20.16
df of  the model are 203  and the objective function was  0.23 

The root mean square of the residuals (RMSR) is  0.01 
The df corrected root mean square of the residuals is  0.01 

Fit based upon off diagonal values = 1
Measures of factor score adequacy             
                                                   PA6  PA5  PA7  PA3  PA2  PA1
Correlation of (regression) scores with factors   0.96 0.96 0.96 0.96 0.96 0.96
Multiple R square of scores with factors          0.92 0.92 0.92 0.92 0.92 0.92
Minimum correlation of possible factor scores     0.84 0.84 0.84 0.83 0.83 0.84
                                                   PA4
Correlation of (regression) scores with factors   0.96
Multiple R square of scores with factors          0.92
Minimum correlation of possible factor scores     0.83

We can see that the output is identifying 7 factors, similar to our initial structure informed by SDT and confirmed by CFA.

First, we want to interpret the standardized loading form the output. For the PA values, factor loadings close to 1 mean there is a strong loading on that factor. We can see which items load well onto certain factors (e.g., PA6 has strong loadings for item 9-12, but low loadings for the remaining items).

The ‘h2’, ‘u2’, and ‘com’ variables indicate other metrics.

  • h2: communality, which is the proportion of variance in that item explained by all factors.
  • u2: uniqueness, such that 1-h2 is the left over item variance left unexplained.
  • com: complexity, where the # of factors an item meaningfully loads on.

From the ‘com’ variable alone, we can see that each item loads onto 1 factor. Across all items, they explained a high degree of variance, ranging from .7-.77 of variability by all factors, with as low as .23 variance left unexplained by all factors for each

Question: To what extent do the EFA results differ from the CFA results?

But again, it is important to note that these data have a very clean factor structure, likely due to the fact that we simulated random data, instead of utilizing real data.

Question: Reflect on an example case where you will use CFA over EFA? Now EFA over CFA? What are the benefits and limitations of each approach?