# se non avete il pacchetto -> install.packages("nomepacchetto")
# e poi...
library(psych)
library(corrplot)
library(ggplot2)
library(patchwork)
library(tidyverse)
library(lavaan)
# impostazione grafica
set_theme(theme_bw(base_size = 14))Analisi Fattoriale Esplorativa
Test per le organizzazioni - A.A. 2025/2026
Nella prima parte della lezione faremo un recap degli argomenti trattati la volta scorsa (con qualche approfondimento), nella seconda parte proveremo a svolgere l’analisi fattoriale esplorativa attraverso il pacchetto lavaan.
Parte della lezione è stata adattata dai seguenti materiali disponibili online:
Dispensa Testing psicologico by Corrado Caudek
Brown, Anna. (2023). Psychometrics in Exercises using R and RStudio. Textbook and data resource. Available from https://bookdown.org/annabrown/psychometricsR.
Lezione: Modulo 6a: Exploratory Factor Analysis - EFA
Altri riferimenti utili sono:
Petersen, I. T. (2026). Principles of psychological assessment: With applied examples in R. Version 1.0.9. University of Iowa Libraries. https://isaactpetersen.github.io/Principles-Psychological-Assessment. https://doi.org/10.25820/work.007199
Martinková, P., & Hladká, A. (2023). Computational Aspects of Psychometric Methods: With R (1st ed.). Chapman and Hall/CRC. https://doi.org/10.1201/9781003054313
| Simbolo | Significato |
|---|---|
| \(n\) | Numero di soggetti |
| \(s\) | Indice del soggetto (\(s = 1, \ldots, n\)) |
| \(p\) | Numero di item (variabili osservate) |
| \(i\) | Indice dell’item generico (\(i = 1, \ldots, p\)) |
| \(k\) | Secondo indice di item, usato nelle formule di covarianza tra coppie (\(k \neq i\)) |
| \(Y_{si}\) | Risposta del soggetto \(s\) all’item \(i\) |
| \(m\) | Numero di fattori comuni (\(m \ll p\)) |
| \(j\) | Indice del fattore (\(j = 1, \ldots, m\)) |
| \(\mu_i\) | Intercetta (media) dell’item \(i\) |
| \(\theta_{sj}\) | Punteggio latente del soggetto \(s\) sul fattore \(j\) |
| \(\lambda_{ij}\) | Saturazione fattoriale dell’item \(i\) sul fattore \(j\) |
| \(\varepsilon_{si}\) | Errore specifico del soggetto \(s\) sull’item \(i\) |
| \(\psi_i\) | Varianza dell’errore specifico dell’item \(i\) (unicità) |
| \(h_i^2\) | Comunalità dell’item \(i\) |
| \(\mathbf{R}\) | Matrice di correlazione osservata (\(p \times p\)) |
| \(\hat{\mathbf{R}}\) | Matrice di correlazione riprodotta dal modello |
| \(\boldsymbol{\Lambda}\) | Matrice dei loading (\(p \times m\)) |
| \(\boldsymbol{\Phi}\) | Matrice di correlazione tra i fattori (\(m \times m\); \(= \mathbf{I}\) se ortogonali) |
| \(\boldsymbol{\Psi}\) | Matrice diagonale delle unicità (\(p \times p\)) |
1 Introduzione
La matrice di correlazione policorica dei 25 item mostra una struttura a blocchi: gli item della stessa scala correlano molto tra loro, mentre le correlazioni tra scale diverse sono più basse.
La domanda centrale è: perché questi blocchi emergono?
L’analisi fattoriale esplorativa parte da una matrice di correlazioni \(p \times p\) tra \(p\) variabili osservate e cerca una matrice \(p \times m\) di saturazioni fattoriali (\(\lambda\)) che spieghi le correlazioni tramite \(m \ll p\) fattori comuni latenti.
2 Il modello monofattoriale
Gli item non correlano direttamente tra loro, ma perché sono tutti influenzati da una stessa variabile latente (il fattore \(\theta\)).
Per \(i = 1, \ldots, p\) item e \(s = 1, \ldots, n\) soggetti, il modello monofattoriale è:
\[ Y_{si} = \mu_i + \lambda_i \,\theta_s + \varepsilon_{si} \]
dove:
- \(\mu_i\) è l’intercetta dell’item \(i\);
- \(\theta_s\) è il punteggio latente del soggetto \(s\) sul fattore comune;
- \(\lambda_i\) è la saturazione fattoriale dell’item \(i\): indica quanto fortemente il fattore influenza quell’item;
- \(\varepsilon_{si}\) è l’errore specifico (tutto ciò che non appartiene al fattore comune).
| Assunzione | Notazione |
|---|---|
| (Convenzione) Item centrati e standardizzati | \(\mathbb{E}(Y_i) = 0\) |
| Il fattore comune è standardizzato | \(\mathbb{E}(\theta) = 0\), \(\mathbb{V}(\theta) = 1\) |
| Gli errori hanno media nulla e varianza \(\psi_i\) | \(\mathbb{E}(\varepsilon_i) = 0\), \(\mathbb{V}(\varepsilon_i) = \psi_i\) |
| Errori tra loro incorrelati | \(\mathrm{Cov}(\varepsilon_i, \varepsilon_k) = 0\) per \(i \neq k\) |
| Errori incorrelati con il fattore | \(\mathrm{Cov}(\varepsilon_i, \theta) = 0\) |
Date queste ipotesi, l’interdipendenza (cioè le correlazioni) fra le variabili osservate è interamente spiegata dal singolo fattore (indipendenza locale/indipendenza condizionale): una volta noto il valore del fattore \(\theta\), le risposte agli item non si influenzano a vicenda, \[P(Y_i, Y_k \mid \theta) = P(Y_i \mid \theta) \cdot P(Y_k \mid \theta).\]
La correlazione tra due item è spuria: nasce perché entrambi dipendono da \(\theta\).
La relazione tra consumo di gelati e violenza, ad esempio, è dovuta alla causa comune “temperatura”, non a un legame diretto.
2.1 Comunalità e unicità
Sotto le assunzioni del modello, la varianza di \(Y_i\) si scompone in due parti:
\[ \underbrace{\mathbb{V}(Y_i)}_{= 1 \text{ se std.}} = \underbrace{h_i^2}_{\text{comunalità}} + \underbrace{\psi_i}_{\text{unicità}} \]
Unicità. Varianza non spiegata dai fattori comuni: \(\psi_i = 1 - h_i^2\)
Comunalità. Varianza spiegata dai fattori comuni: \(h_i^2 = \lambda_i^2\)
- Con \(m\) fattori ortogonali: \(h_i^2 = \sum_{j=1}^m \lambda_{ij}^2\).
- Con \(m\) fattori correlati: \(h_i^2 = \boldsymbol{\lambda}_i \,\boldsymbol{\Phi}\, \boldsymbol{\lambda}_i^\mathsf{T},\)
con \({\lambda}_i = ({\lambda}_{i1},{\lambda}_{i2}, \dots, {\lambda}_{im})\) e \(\mathbf{\Phi}\) (matrice di correlazione \(m \times m\))
2.2 La tetrade
Spearman osservò che le prestazioni scolastiche (Classics, English, Math, …) correlano tutte tra loro, quindi ipotizzò l’estistenza di un fattore generale \(g\) (intelligenza) latente…
\[ \begin{array}{ccccc} \hline & y_c & y_e & y_m & y_p \\ \hline y_c & 1.00 & 0.78 & 0.70 & 0.66 \\ y_e & & 1.00 & 0.64 & 0.54 \\ y_m & & & 1.00 & 0.45 \\ y_p & & & & 1.00 \\ \hline \end{array} \]
Se esiste un fattore comune \(\theta\), allora \(y_i\) e \(y_k\), una volta controllato \(\theta\), devono risultare condizionalmente indipendenti. La correlazione parziale vale zero quando:
\[ r_{ik} = r_{i\theta} \cdot r_{k\theta} = \lambda_i \cdot \lambda_k \]
Questa condizione implica che ogni correlazione osservata è scomponibile come prodotto di due saturazioni.
set.seed(123)
n <- 1000
f <- rnorm(n, 24, 12) # fattore latente
y1 <- 10 + 7 * f + rnorm(n, 0, 50) # osservate funzione della latente
y2 <- 3 + 2 * f + rnorm(n, 0, 50)
Y <- cbind(y1, y2, f) #variabili osservate e latente
round(cor(Y), 3) # correlazioni semplici y1 y2 f
y1 1.000 0.380 0.867
y2 0.380 1.000 0.423
f 0.867 0.423 1.000
fm1 <- lm(y1 ~ f) # controllo per il fattore
fm2 <- lm(y2 ~ f)
round(cor(fm1$res, fm2$res), 3) # correlazione parziale[1] 0.028
La correlazione tra \(y_1\) e \(y_2\) era interamente dovuta all’effetto condiviso di \(f\).
Senza bisogno di guardare i residui, avendo le correlazioni tra una variabile comune \(f\) e tra le \(y\), la correlazione parziale si può ottenere:
\[ r_{12 \mid f} = \frac{r_{12} - r_{1f}\,r_{2f}}{\sqrt{(1 - r_{1f}^2)(1 - r_{2f}^2)}} \]
R <- cor(Y)
R y1 y2 f
y1 1.0000000 0.3799708 0.8673960
y2 0.3799708 1.0000000 0.4233576
f 0.8673960 0.4233576 1.0000000
# formula
(R[1, 2] - R[1, 3] * R[2, 3]) /
sqrt((1 - R[1, 3]^2) * (1- R[2, 3]^2)) [1] 0.02828618
Se \(r_{ij} = \lambda_i \lambda_j\) per ogni coppia, possiamo ricavare i loading dalle sole correlazioni osservate.
\[ \begin{array}{ccccc} \hline & y_c & y_e & y_m & y_p \\ \hline y_c & 1.00 & 0.78 & 0.70 & 0.66 \\ y_e & & 1.00 & 0.64 & 0.54 \\ y_m & & & 1.00 & 0.45 \\ y_p & & & & 1.00 \\ \hline \end{array} \]
Per tre variabili \(c\), \(e\), \(m\):
\[ \lambda_m = \sqrt{\frac{r_{cm} \cdot r_{em}}{r_{ce}}} \]
Applicando questa formula con diverse terne si ottengono stime multiple dello stesso loading:
\[ \hat\lambda_m = \sqrt{\frac{0.70 \times 0.64}{0.78}} \approx 0.76, \qquad \hat\lambda_m = \sqrt{\frac{0.78 \times 0.45}{0.66}} \approx 0.69, \qquad \hat\lambda_m = \sqrt{\frac{0.64 \times 0.45}{0.54}} \approx 0.73 \]
Se tutte le stime sono coerenti, il modello a un fattore è plausibile. Se divergono, servono almeno due fattori.
Assumi tre variabili \(c,e,m\). Dal modello a un fattore:
\[ r_{cm}=\lambda_c\lambda_m,\qquad r_{em}=\lambda_e\lambda_m,\qquad r_{ce}=\lambda_c\lambda_e. \]
Moltiplica le prime due:
\[ r_{cm}r_{em} = (\lambda_c\lambda_m)(\lambda_e\lambda_m) = \lambda_c\lambda_e\lambda_m^2. \]
Ora dividi per la terza:
\[ \frac{r_{cm}r_{em}}{r_{ce}} = \frac{\lambda_c\lambda_e\lambda_m^2}{\lambda_c\lambda_e} = \lambda_m^2, \]
quindi
\[ \lambda_m=\sqrt{\frac{r_{cm}r_{em}}{r_{ce}}}. \]
2.2.1 Struttura dei loadings
Formalmente, se hai \(p\) item e 1 fattore, la matrice dei loadings è un vettore colonna:
\[ \Lambda = \begin{bmatrix} \lambda_1\\ \lambda_2\\ \vdots\\ \lambda_p \end{bmatrix} \]
e quindi
\[ \Lambda \Lambda^\mathsf{T} = \begin{bmatrix} \lambda_1^2 & \lambda_1\lambda_2 & \cdots & \lambda_1\lambda_p\\ \lambda_2\lambda_1 & \lambda_2^2 & \cdots & \lambda_2\lambda_p\\ \vdots & \vdots & \ddots & \vdots\\ \lambda_p\lambda_1 & \lambda_p\lambda_2 & \cdots & \lambda_p^2 \end{bmatrix}. \]
La diagonale contiene le comunalità degli item, mentre fuori diagonale compaiono le covarianze riprodotte tra item.
Per ottenere la matrice di covarianza teorica del modello bisogna aggiungere la matrice delle unicità \(\Psi = \operatorname{diag}(\psi_1, \psi_2, \ldots, \psi_p)\):
\[ \Sigma = \Lambda \Lambda^\mathsf{T} + \Psi = \begin{bmatrix} \lambda_1^2 + \psi_1 & \lambda_1\lambda_2 & \cdots & \lambda_1\lambda_p\\ \lambda_2\lambda_1 & \lambda_2^2 + \psi_2 & \cdots & \lambda_2\lambda_p\\ \vdots & \vdots & \ddots & \vdots\\ \lambda_p\lambda_1 & \lambda_p\lambda_2 & \cdots & \lambda_p^2 + \psi_p \end{bmatrix}. \]
Il termine \(\psi_i\) rappresenta la varianza specifica (o unicità) dell’item \(i\), cioè la quota di varianza non spiegata dal fattore comune.
| Elemento | Formula | Interpretazione |
|---|---|---|
| Diagonale | \(\lambda_i^2 + \psi_i\) | Varianza totale = comunalità + unicità |
| Fuori diagonale | \(\lambda_i \lambda_j\) | Covarianza riprodotta tra item \(i\) e \(j\) |
Quindi \(\Lambda\Lambda^\mathsf{T}\) da sola riproduce correttamente le covarianze fuori diagonale, ma sulla diagonale contiene solo le comunalità \(\lambda_i^2\), ovvero la quota di varianza spiegata dal fattore comune. Aggiungere \(\Psi\) completa la decomposizione: varianza totale = parte comune + parte specifica.
Dato che le variabili sono standardizzate (varianza = 1), la matrice di correlazione riprodotta dal modello è:
\[ R = \Lambda \Lambda^\mathsf{T} + \Psi \]
con \(\psi_i = 1 - \lambda_i^2\) sulla diagonale, così che \(\sigma_{i} = \lambda_i^2 + (1 - \lambda_i^2) = 1\). Le correlazioni riprodotte fuori diagonale sono semplicemente \(\hat{r}_{ij} = \lambda_i \lambda_j\).
Spearman <- matrix(c(
1.00, 0.78, 0.70, 0.66,
0.78, 1.00, 0.64, 0.54,
0.70, 0.64, 1.00, 0.45,
0.66, 0.54, 0.45, 1.00
), byrow = TRUE, ncol = 4,
dimnames = list(c("C","E","M","P"), c("C","E","M","P")))
Spearman C E M P
C 1.00 0.78 0.70 0.66
E 0.78 1.00 0.64 0.54
M 0.70 0.64 1.00 0.45
P 0.66 0.54 0.45 1.00
# funzione del pacchetto stats R base
fm <- factanal(covmat = Spearman, factors = 1) #specifico matrice e fattori
fm
Call:
factanal(factors = 1, covmat = Spearman)
Uniquenesses:
C E M P
0.086 0.329 0.460 0.539
Loadings:
Factor1
C 0.956
E 0.819
M 0.735
P 0.679
Factor1
SS loadings 2.587
Proportion Var 0.647
The degrees of freedom for the model is 2 and the fit was 0.023
La somma dei quadrati delle saturazioni fornisce la varianza totale spiegata dal fattore:
\[ \sum_i \lambda_i^2 = \text{SS loadings} = 2.587 \]
Ciascun \(\lambda_i^2\) è la comunalità del singolo item: \(C^2 + E^2 + M^2 + P^2\), il risultato è visualizzato in SS loadings 2.587.
# loadings
C <- 0.956
E <- 0.819
M <- 0.735
P <- 0.679
# total variance
C^2 + E^2 + M^2 + P^2[1] 2.585963
La Proportion Var ci dice quanto della varianza è spiegata dal fattore. Assumendo variabili standardizzate, la varianza totale attesa è \(4\) e quindi \(2.587 / 4 \approx 0.647\).
# proportion of variance
(C^2 + E^2 + M^2 + P^2)/4[1] 0.6464908
La comunalità di ciascun item è \(h_i^2 = 1 - \text{uniqueness}\), cioè la quota di varianza spiegata dal/i fattore/i comuni.
Nel caso monofattoriale, coincide con \(\lambda_i^2\), quindi il loading si recupera come radice quadrata della comunalità.
comm <- 1 - fm$uniquenesses # comunalità: quanto il fattore spiega quell'item?
tab <- data.frame(
loading = sqrt(comm), # solo con 1 fattore!
communality = comm, # h² = λ² (quota spiegata)
uniqueness = fm$uniquenesses # ψ = 1 - h² (quota residua)
)
tab$prop_var_item <- comm / 4 # contributo di ciascun item
# alla Proportion Var totale
tab loading communality uniqueness prop_var_item
C 0.9562592 0.9144316 0.08556841 0.2286079
E 0.8193894 0.6713990 0.32860098 0.1678498
M 0.7350297 0.5402686 0.45973140 0.1350671
P 0.6790257 0.4610759 0.53892412 0.1152690
# se sommo i contributi ho la varianza totale spiegata dal fattore
sum(tab$prop_var_item) [1] 0.6467938
Si può anche ricostruire esplicitamente la matrice di correlazione riprodotta \(\hat{R} = \Lambda\Lambda^\mathsf{T} + \Psi\) e confrontarla con quella osservata:
lambda <- sqrt(comm) # vettore dei loadings (1 fattore)
Psi <- diag(fm$uniquenesses) # matrice diagonale delle unicità
R_hat <- lambda %*% t(lambda) + Psi # matrice riprodotta
# aggiungo i nomi alle colonne e righe
rownames(R_hat) <- colnames(R_hat) <- c("C","E","M","P")
round(R_hat, 3)# correlazioni riprodotte dal modello C E M P
C 1.000 0.784 0.703 0.649
E 0.784 1.000 0.602 0.556
M 0.703 0.602 1.000 0.499
P 0.649 0.556 0.499 1.000
round(Spearman - R_hat, 3) # residui (differenze dalla matrice osservata) C E M P
C 0.000 -0.004 -0.003 0.011
E -0.004 0.000 0.038 -0.016
M -0.003 0.038 0.000 -0.049
P 0.011 -0.016 -0.049 0.000
3 Il modello multifattoriale
Con \(m\) fattori comuni e \(p\) variabili, il modello è:
\[ \mathbf{Y}_s = \boldsymbol{\mu} + \boldsymbol{\Lambda}\,\boldsymbol{\theta}_s + \boldsymbol{\varepsilon}_s \]
In forma scalare: \[ Y_{si} = \mu_i + \lambda_{i1}\theta_{s1} + \cdots + \lambda_{im}\theta_{sm} + \varepsilon_{si} \]
La matrice di covarianza teorica risulta:
Fattori ortogonali (\(\boldsymbol{\Phi} = \mathbf{I}\)): \(\boldsymbol{\Sigma} = \boldsymbol{\Lambda}\boldsymbol{\Lambda}^\mathsf{T} + \boldsymbol{\Psi}\)
Fattori obliqui (\(\boldsymbol{\Phi} \neq \mathbf{I}\)): \(\boldsymbol{\Sigma} = \boldsymbol{\Lambda}\boldsymbol{\Phi}\boldsymbol{\Lambda}^\mathsf{T} + \boldsymbol{\Psi}\)
dove \(\boldsymbol{\Phi}\) è la matrice di correlazioni tra i fattori, e \(\boldsymbol{\Psi}\) la matrice diagonale delle unicità (\(p \times p\)).
3.1 Esempio applicato
Dati di 250 pazienti con 4 scale di Neuroticismo (N1–N4) e 4 di Estroversione (E1–E4).
Codice
varnames <- c("N1","N2","N3","N4","E1","E2","E3","E4")
cors <- '
1.000
0.767 1.000
0.731 0.709 1.000
0.778 0.738 0.762 1.000
-0.351 -0.302 -0.356 -0.318 1.000
-0.316 -0.280 -0.300 -0.267 0.675 1.000
-0.296 -0.289 -0.297 -0.296 0.634 0.651 1.000
-0.282 -0.254 -0.292 -0.245 0.534 0.593 0.566 1.000
'
psychot_cor_mat <- getCov(cors, names = varnames)
psychot_cor_mat N1 N2 N3 N4 E1 E2 E3 E4
N1 1.000 0.767 0.731 0.778 -0.351 -0.316 -0.296 -0.282
N2 0.767 1.000 0.709 0.738 -0.302 -0.280 -0.289 -0.254
N3 0.731 0.709 1.000 0.762 -0.356 -0.300 -0.297 -0.292
N4 0.778 0.738 0.762 1.000 -0.318 -0.267 -0.296 -0.245
E1 -0.351 -0.302 -0.356 -0.318 1.000 0.675 0.634 0.534
E2 -0.316 -0.280 -0.300 -0.267 0.675 1.000 0.651 0.593
E3 -0.296 -0.289 -0.297 -0.296 0.634 0.651 1.000 0.566
E4 -0.282 -0.254 -0.292 -0.245 0.534 0.593 0.566 1.000
3.1.1 EFA a 2 fattori con rotazione ortogonale
n_brown <- 250
efa_ort <- factanal(
covmat = psychot_cor_mat,
factors = 2,
rotation = "varimax",
n.obs = n_brown
)
efa_ort
Call:
factanal(factors = 2, covmat = psychot_cor_mat, n.obs = n_brown, rotation = "varimax")
Uniquenesses:
N1 N2 N3 N4 E1 E2 E3 E4
0.219 0.280 0.289 0.217 0.362 0.293 0.381 0.511
Loadings:
Factor1 Factor2
N1 0.854 -0.228
N2 0.826 -0.194
N3 0.811 -0.233
N4 0.865 -0.186
E1 -0.202 0.773
E2 -0.139 0.829
E3 -0.158 0.771
E4 -0.147 0.684
Factor1 Factor2
SS loadings 2.923 2.526
Proportion Var 0.365 0.316
Cumulative Var 0.365 0.681
Test of the hypothesis that 2 factors are sufficient.
The chi square statistic is 9.58 on 13 degrees of freedom.
The p-value is 0.728
Partendo dai loading calcola con R (o con la calcolatrice o a mano) le quantità:
SS loadings,Proportion VarCumulative Varcommunalità(vedi sopra)unicità(controlla che il risultato sia come quello riportato inefa_ort$uniquenesses)
lambda <- efa_ort$loadings[1:8,1:2]
lambda Factor1 Factor2
N1 0.8537641 -0.2277964
N2 0.8257412 -0.1944553
N3 0.8105499 -0.2334530
N4 0.8651568 -0.1860795
E1 -0.2015257 0.7729335
E2 -0.1387371 0.8294011
E3 -0.1584101 0.7707741
E4 -0.1467635 0.6837448
# ...Matrice riprodotta e residui
# loadings * trasposto(loadings) + diagonale unicità
Rr <- lambda %*% t(lambda) + diag(efa_ort$uniqueness)
round(Rr, 2) N1 N2 N3 N4 E1 E2 E3 E4
N1 1.00 0.75 0.75 0.78 -0.35 -0.31 -0.31 -0.28
N2 0.75 1.00 0.71 0.75 -0.32 -0.28 -0.28 -0.25
N3 0.75 0.71 1.00 0.74 -0.34 -0.31 -0.31 -0.28
N4 0.78 0.75 0.74 1.00 -0.32 -0.27 -0.28 -0.25
E1 -0.35 -0.32 -0.34 -0.32 1.00 0.67 0.63 0.56
E2 -0.31 -0.28 -0.31 -0.27 0.67 1.00 0.66 0.59
E3 -0.31 -0.28 -0.31 -0.28 0.63 0.66 1.00 0.55
E4 -0.28 -0.25 -0.28 -0.25 0.56 0.59 0.55 1.00
round(psychot_cor_mat - Rr, 3) # residui: idealmente prossimi a 0 N1 N2 N3 N4 E1 E2 E3 E4
N1 0.000 0.018 -0.014 -0.003 -0.003 -0.009 0.015 -0.001
N2 0.018 0.000 -0.006 -0.013 0.015 -0.004 -0.008 0.000
N3 -0.014 -0.006 0.000 0.017 -0.012 0.006 0.011 -0.013
N4 -0.003 -0.013 0.017 0.000 0.000 0.007 -0.016 0.009
E1 -0.003 0.015 -0.012 0.000 0.000 0.006 0.006 -0.024
E2 -0.009 -0.004 0.006 0.007 0.006 0.000 -0.010 0.006
E3 0.015 -0.008 0.011 -0.016 0.006 -0.010 0.000 0.016
E4 -0.001 0.000 -0.013 0.009 -0.024 0.006 0.016 0.000
Visualizzaione:
fa.diagram(lambda)3.1.2 EFA con rotazione obliqua
efa_obl <- fa(psychot_cor_mat, nfactors = 2, n.obs = n_brown,
rotate = "oblimin")efa_oblFactor Analysis using method = minres
Call: fa(r = psychot_cor_mat, nfactors = 2, n.obs = n_brown, rotate = "oblimin")
Standardized loadings (pattern matrix) based upon correlation matrix
MR1 MR2 h2 u2 com
N1 0.88 -0.02 0.78 0.22 1
N2 0.85 0.01 0.72 0.28 1
N3 0.83 -0.04 0.71 0.29 1
N4 0.90 0.03 0.78 0.22 1
E1 -0.05 0.77 0.63 0.37 1
E2 0.03 0.86 0.71 0.29 1
E3 0.00 0.79 0.63 0.37 1
E4 -0.01 0.70 0.49 0.51 1
MR1 MR2
SS loadings 3.00 2.45
Proportion Var 0.37 0.31
Cumulative Var 0.37 0.68
Proportion Explained 0.55 0.45
Cumulative Proportion 0.55 1.00
With factor correlations of
MR1 MR2
MR1 1.00 -0.43
MR2 -0.43 1.00
Mean item complexity = 1
Test of the hypothesis that 2 factors are sufficient.
df null model = 28 with the objective function = 5.02 with Chi Square = 1231.22
df of the model are 13 and the objective function was 0.04
The root mean square of the residuals (RMSR) is 0.01
The df corrected root mean square of the residuals is 0.02
The harmonic n.obs is 250 with the empirical chi square 1.73 with prob < 1
The total n.obs was 250 with Likelihood Chi Square = 9.65 with prob < 0.72
Tucker Lewis Index of factoring reliability = 1.006
RMSEA index = 0 and the 90 % confidence intervals are 0 0.047
BIC = -62.12
Fit based upon off diagonal values = 1
Measures of factor score adequacy
MR1 MR2
Correlation of (regression) scores with factors 0.96 0.94
Multiple R square of scores with factors 0.93 0.87
Minimum correlation of possible factor scores 0.85 0.75
Il modello è stato stimato con il metodo minres (minimum residual) su una matrice di correlazione (psychot_cor_mat), con 2 fattori e 250 osservatori. La rotazione usata è oblimin, una rotazione obliqua che permette ai fattori di essere correlati tra loro.
Pattern Matrix (Carichi Fattoriali)
La tabella mostra i carichi standardizzati (pattern matrix) degli 8 item sui 2 fattori. La struttura è estremamente semplice: ogni item carica quasi esclusivamente su un solo fattore.
| Item | MR1 | MR2 | h² | u² |
|---|---|---|---|---|
| N1 | 0.88 | −0.02 | 0.78 | 0.22 |
| N2 | 0.85 | 0.01 | 0.72 | 0.28 |
| N3 | 0.83 | −0.04 | 0.71 | 0.29 |
| N4 | 0.90 | 0.03 | 0.78 | 0.22 |
| E1 | −0.05 | 0.77 | 0.63 | 0.37 |
| E2 | 0.03 | 0.86 | 0.71 | 0.29 |
| E3 | 0.00 | 0.79 | 0.63 | 0.37 |
| E4 | −0.01 | 0.70 | 0.49 | 0.51 |
MR1 cattura gli item N1–N4 (probabilmente Nevroticismo), MR2 cattura E1–E4 (probabilmente Estroversione).
- h² (communality): quota di varianza dell’item spiegata dai fattori
- u² (uniqueness): varianza residua non spiegata (= 1 − h²)
- com (complexity): tutti = 1, ogni item satura puramente su un solo fattore
Varianza Spiegata
| Indice | MR1 | MR2 |
|---|---|---|
| SS Loadings | 3.00 | 2.45 |
| Proportion Var | 0.37 | 0.31 |
| Cumulative Var | 0.37 | 0.68 |
| Proportion Explained | 0.55 | 0.45 |
| Cumulative Proportion | 0.55 | 1.00 |
I due fattori spiegano congiuntamente il 68% della varianza totale degli item.
Correlazione tra Fattori
\[r_{\text{MR1, MR2}} = -0.43\]
I fattori risultano correlati negativamente, il che è teoricamente sensato per Nevroticismo ed Estroversione.
Indici di Fit del Modello
Tutti gli indici indicano un ottimo adattamento del modello ai dati:
| Indice | Valore | Soglia consigliata |
|---|---|---|
| RMSR | 0.01 | < 0.05 |
| Likelihood \(\chi^2\) | 9.65 (p = 0.72) | p > 0.05 |
| TLI | 1.006 | > 0.95 |
| RMSEA | 0.00 [90% CI: 0, 0.047] | < 0.05 |
| BIC | −62.12 | Più basso = meglio |
Il test \(\chi^2\) non significativo indica che il modello a 2 fattori non viene rifiutato: i residui sono compatibili con l’errore casuale.
Correlazione tra i fattori:
round(efa_obl$Phi, 3) MR1 MR2
MR1 1.000 -0.431
MR2 -0.431 1.000
Phi <- efa_obl$PhiLamdba e unicità:
lambda_obl <- matrix(efa_obl$loadings[, 1:2], nrow = 8)
lambda_obl [,1] [,2]
[1,] 0.877075569 -0.01577815
[2,] 0.852280802 0.01128419
[3,] 0.826584447 -0.03684789
[4,] 0.898762806 0.03121279
[5,] -0.048589010 0.77186847
[6,] 0.034700239 0.85566012
[7,] 0.002815265 0.79291602
[8,] -0.007884591 0.69545191
Psi_obl <- diag(efa_obl$uniquenesses)
Psi_obl [,1] [,2] [,3] [,4] [,5] [,6] [,7]
[1,] 0.2185506 0.0000000 0.0000000 0.000000 0.0000000 0.0000000 0.0000000
[2,] 0.0000000 0.2817872 0.0000000 0.000000 0.0000000 0.0000000 0.0000000
[3,] 0.0000000 0.0000000 0.2891237 0.000000 0.0000000 0.0000000 0.0000000
[4,] 0.0000000 0.0000000 0.0000000 0.215453 0.0000000 0.0000000 0.0000000
[5,] 0.0000000 0.0000000 0.0000000 0.000000 0.3695024 0.0000000 0.0000000
[6,] 0.0000000 0.0000000 0.0000000 0.000000 0.0000000 0.2922572 0.0000000
[7,] 0.0000000 0.0000000 0.0000000 0.000000 0.0000000 0.0000000 0.3732021
[8,] 0.0000000 0.0000000 0.0000000 0.000000 0.0000000 0.0000000 0.0000000
[,8]
[1,] 0.0000000
[2,] 0.0000000
[3,] 0.0000000
[4,] 0.0000000
[5,] 0.0000000
[6,] 0.0000000
[7,] 0.0000000
[8,] 0.5115539
Matrice riprodotta:
R_hat_obl <- lambda_obl %*% Phi %*% t(lambda_obl) + Psi_obl
round(R_hat_obl, 2) [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,] 1.00 0.75 0.75 0.78 -0.35 -0.31 -0.31 -0.28
[2,] 0.75 1.00 0.71 0.75 -0.32 -0.28 -0.28 -0.25
[3,] 0.75 0.71 1.00 0.74 -0.34 -0.31 -0.31 -0.28
[4,] 0.78 0.75 0.74 1.00 -0.32 -0.27 -0.28 -0.25
[5,] -0.35 -0.32 -0.34 -0.32 1.00 0.67 0.63 0.55
[6,] -0.31 -0.28 -0.31 -0.27 0.67 1.00 0.67 0.59
[7,] -0.31 -0.28 -0.31 -0.28 0.63 0.67 1.00 0.55
[8,] -0.28 -0.25 -0.28 -0.25 0.55 0.59 0.55 1.00
Residui
round(psychot_cor_mat - R_hat_obl, 2) N1 N2 N3 N4 E1 E2 E3 E4
N1 0.00 0.02 -0.01 0.00 0.00 -0.01 0.01 0.00
N2 0.02 0.00 0.00 -0.01 0.01 0.00 -0.01 0.00
N3 -0.01 0.00 0.00 0.02 -0.01 0.01 0.01 -0.01
N4 0.00 -0.01 0.02 0.00 0.00 0.01 -0.02 0.01
E1 0.00 0.01 -0.01 0.00 0.00 0.01 0.01 -0.02
E2 -0.01 0.00 0.01 0.01 0.01 0.00 -0.01 0.01
E3 0.01 -0.01 0.01 -0.02 0.01 -0.01 0.00 0.01
E4 0.00 0.00 -0.01 0.01 -0.02 0.01 0.01 0.00
Visualizzazione
fa.diagram(efa_obl) # qui al posto di lambda mettiamo il modello4 Determinare il numero di fattori
L’EFA è esplorativa: non impone a priori quanti fattori estrarre.
4.1 Autovalori e Scree plot
Prima di stimare il modello EFA si analizza la matrice di correlazione \(\mathbf{R}\) per capire quanta struttura latente contiene. Uno strumento utile è la sua scomposizione in autovalori e autovettori:
\[\mathbf{R}\,\mathbf{v} = e\,\mathbf{v}\]
dove \(\mathbf{v}\) è un autovettore (una direzione nello spazio degli item lungo cui la matrice si limita a scalare i vettori senza ruotarli) e \(e\) è il corrispondente autovalore, il fattore di scala: ci dice quanta varianza totale è concentrata lungo quella direzione. Per una matrice di correlazione la somma di tutti gli autovalori è uguale a \(p\) (uno per item standardizzato).
Gli autovettori individuano le direzioni di massima varianza in ordine decrescente: il primo autovettore punta nella direzione in cui i dati variano di più (il “fattore generale” comune a tutti gli item), il secondo nella direzione di massima varianza residua ortogonale al primo, e così via.
Per capire meglio è utile rappresentarli geometricamente, consideriamo il caso più semplice: 2 item e correlazione variabile. Ogni partecipante è un punto nello spazio bidimensionale definito dai due item; la forma di questa nuvola dipende interamente dalla correlazione \(r\).
L’Asse 1 (rosso) cattura ciò che i due item hanno in comune: punta sempre lungo la diagonale positiva quando \(r > 0\), lungo quella negativa quando \(r < 0\). L’Asse 2 (arancione) è sempre ortogonale al primo e cattura la varianza residua non condivisa. Con \(r = 0.95\) l’Asse 2 è quasi scomparso (\(e_2 = 0.05\)): un solo fattore basterebbe a descrivere quasi tutta la struttura.
Gli autovalori ci dicono quindi quanti fattori estrarre.
4.1.1 Criterio di Kaiser
Trattenere i fattori con autovalore \(\geq 1\) (cioè che spiegano più varianza di un singolo item standardizzato). Utile come prima indicazione, ma tende a sovrastimare il numero di fattori.
Lo scree plot mostra il “gomito” dopo il quale gli autovalori calano gradualmente: si trattengono i fattori prima del gomito.
4.1.2 Parallel Analysis
Confronta gli autovalori osservati con la distribuzione degli autovalori attesi da dati completamente casuali (stessa dimensione del dataset). Si trattengono solo i fattori il cui autovalore reale supera il 95° percentile della distribuzione casuale:
\[ \text{soglia}_k = \hat{q}_{0.95} \!\left(\lambda^{\text{rand}}_{k,1}, \ldots, \lambda^{\text{rand}}_{k,B}\right) \]
4.1.3 Minimum Average Partial (MAP)
Il MAP misura la correlazione residua media rimasta tra gli item dopo aver rimosso via via 1, 2, 3, … fattori:
\[MAP(f) = \dfrac{1}{p(p-1)} \sum_{i \neq j} {r_{ij}^{(f)}}^2\]
\[f^* = \arg \min_f MAP(f)\]
\(p(p-1)\): Numero di coppie di variabili
\(r_{ij}^{(f)}\) correlazione parziale tra ogni coppia di variabili dopo aver estratto \(f\) fattori
Si sceglie \(f\) che minimizza MAP(\(f\)): troppo pochi fattori → correlazioni residue ancora alte; troppi fattori → i nuovi fattori inseguono rumore e MAP risale.
| Criterio | Logica | Tendenza |
|---|---|---|
| Kaiser (\(\lambda \geq 1\)) | Autovalore ≥ varianza di 1 item | Sovrastima |
| Parallel Analysis | Autovalore reale > autovalore casuale (95°pct) | Più conservativo |
| MAP | Minimizza la correlazione residua | Generalmente accurato |
In pratica, usarli insieme: se concordano, la scelta è robusta.
5 Estrazione e rotazione
5.1 L’estrazione: dalla matrice \(\mathbf{R}\) ai loadings
Estrarre i fattori significa trovare \(\boldsymbol{\Lambda}\) che minimizza la differenza tra \(\mathbf{R}\) osservata e la matrice ricostruita dal modello \(\hat{\mathbf{R}}\).
5.1.1 I loadings: cosa sono geometricamente
Una volta estratti, i loadings descrivono la struttura: quanto ciascun item è correlato con ciascun fattore latente. Geometricamente, si rappresentano gli item come punti in uno spazio dove gli assi sono i fattori. Con 1 fattore lo spazio è monodimensionale: il loading è semplicemente la coordinata dell’item su quell’unico asse.
Con 2 fattori lo spazio diventa bidimensionale (F1 \(\times\) F2): ogni item ha due coordinate, e la proiezione ortogonale del punto su ciascun asse dà il loading corrispondente. Un loading alto su F1 significa che il punto cade vicino all’asse F1 (e lontano da F2); un cross-loading si verifica quando un punto è equidistante da entrambi gli assi.
Gli autovalori iniziali (scree plot, Kaiser) sono proprietà della matrice \(\mathbf{R}\) prima della stima del modello. I loadings stimati misurano l’associazione tra ogni item e il fattore; la loro somma dei quadrati (SS Loadings = \(\sum_i \hat{\lambda}_{ik}^2\)) indica quanta varianza comune cattura ciascun fattore.
5.2 Rotazione
Lavoriamo sugli item E + N del dataset bfi:
fit_efa_EN <- fa(R_EN, nfactors = 2, fm = "minres",
rotate = "none", n.obs = n_obs)
round(fit_efa_EN$loadings[,], 3) MR1 MR2
E1 -0.398 0.501
E2 -0.640 0.458
E3 -0.380 0.467
E4 -0.536 0.479
E5 -0.344 0.465
N1 0.661 0.501
N2 0.649 0.480
N3 0.659 0.422
N4 0.681 0.088
N5 0.525 0.203
Prima della rotazione, il primo fattore tende ad essere generale (tutti gli item caricano nella stessa direzione); il secondo separa parzialmente i cluster, ma gli assi non sono ancora allineati ai dati.
La soluzione non ruotata è spesso difficile da interpretare. La rotazione trasforma gli assi per ottenere la simple structure: ogni item carica alto su un solo fattore e vicino a zero sugli altri. Concretamente, ruotare gli assi equivale a cambiare il sistema di riferimento: i punti non si spostano, ma le loro coordinate (= i loadings) cambiano.
data.frame(item = c("E1","E2","E3","E4","E5","N1","N2","N3","N4","N5"),
orto = unname(fit_varimax$loadings[,]),
obli = unname(fit_oblimin$loadings[,])) item orto.1 orto.2 obli.1 obli.2
1 E1 -0.027089709 0.639785522 0.08835104 0.654370957
2 E2 -0.248418033 0.746620903 -0.11589160 0.752709875
3 E3 -0.032168309 0.601427011 0.07628341 0.614799996
4 E4 -0.151197447 0.702607959 -0.02564875 0.712501774
5 E5 -0.004451518 0.578385566 0.10011297 0.592581647
6 N1 0.829313831 0.015594220 0.84051647 0.057799840
7 N2 0.807017875 0.005902044 0.81624219 0.046741777
8 N3 0.781040964 -0.046263437 0.78056783 -0.008034159
9 N4 0.602064742 -0.329252928 0.54859984 -0.307103846
10 N5 0.543706187 -0.144682669 0.52303366 -0.120874443
Con una rotazione ortogonale (es. varimax) i fattori sono incorrelati per costruzione: esiste una sola matrice di loadings. Con una rotazione obliqua (es. oblimin) i fattori possono correlare tra loro, e questo introduce tre quantità distinte:
- \(\boldsymbol{\Lambda}\) (\(p \times m\)) — pattern matrix: l’effetto diretto del fattore \(j\) sull’item \(i\), al netto degli altri fattori
- \(\boldsymbol{\Phi}\) (\(m \times m\)) — matrice di correlazione tra fattori: quanto i fattori si assomigliano tra loro
- \(\boldsymbol{S} = \boldsymbol{\Lambda}\boldsymbol{\Phi}\) (\(p \times m\)) — structure matrix: la correlazione totale tra item \(i\) e fattore \(j\)
\(\boldsymbol{\Phi}\) ha 1 sulla diagonale e correlazioni \(\phi_{jj'}\) fuori diagonale. Con rotazione ortogonale \(\boldsymbol{\Phi} = \mathbf{I}\) per costruzione.
5.2.1 Structure matrix \(\boldsymbol{S}\)
Ogni elemento \(s_{ij}\) è la correlazione totale tra l’item \(i\) e il fattore \(j\). Risponde alla domanda:
“Quanto si muove insieme l’item \(i\) con il fattore \(j\), considerando anche le relazioni tra i fattori?”
\[\boldsymbol{S} = \boldsymbol{\Lambda}\,\boldsymbol{\Phi}\]
L’elemento \(s_{ij}\) include due contributi: l’effetto diretto del fattore \(j\) sull’item \(i\) (il pattern loading \(\lambda_{ij}\)) più gli effetti indiretti degli altri fattori \(j'\), mediati dalla loro correlazione \(\phi_{jj'}\) con il fattore \(j\):
\[s_{ij} = \lambda_{ij} + \sum_{j' \neq j} \lambda_{ij'}\,\phi_{j'j}\]
Se \(\boldsymbol{\Phi} = \mathbf{I}\) (fattori ortogonali), \(\boldsymbol{S} = \boldsymbol{\Lambda}\): le due matrici coincidono.
5.2.2 Esempio con i dati E + N
fit_oblimin <- fa(R_EN, nfactors = 2, fm = "minres",
rotate = "oblimin", n.obs = n_obs)
# Pattern matrix — effetti diretti, output di default di fa()
L_pattern <- fit_oblimin$loadings[,]
round(L_pattern, 3) MR1 MR2
E1 0.088 0.654
E2 -0.116 0.753
E3 0.076 0.615
E4 -0.026 0.713
E5 0.100 0.593
N1 0.841 0.058
N2 0.816 0.047
N3 0.781 -0.008
N4 0.549 -0.307
N5 0.523 -0.121
# Phi — correlazione tra i fattori (m × m)
round(fit_oblimin$Phi, 3) MR1 MR2
MR1 1.000 -0.224
MR2 -0.224 1.000
# Structure matrix — correlazioni totali item-fattore (p × m)
L_structure <- L_pattern %*% fit_oblimin$Phi
round(L_structure, 3) MR1 MR2
E1 -0.058 0.635
E2 -0.285 0.779
E3 -0.062 0.598
E4 -0.186 0.718
E5 -0.033 0.570
N1 0.828 -0.131
N2 0.806 -0.136
N3 0.782 -0.183
N4 0.618 -0.430
N5 0.550 -0.238
6 Esercitazione pratica
Adattato dal libro: Brown, Anna. (2023). Psychometrics in Exercises using R and RStudio. Textbook and data resource. Available from https://bookdown.org/annabrown/psychometricsR.
L’obiettivo di questo esercizio è condurre un’Analisi Fattoriale Esplorativa (EFA) su risposte politomiche utilizzando il pacchetto lavaan.
6.1 Il questionario CHI-ESQ (versione genitori)
Nel 2002, la Commission for Health Improvement nel Regno Unito ha sviluppato l’Experience of Service Questionnaire (CHI-ESQ) per misurare le esperienze degli utenti con i Servizi di Salute Mentale dell’Infanzia e dell’Adolescenza (CAMHS). Il questionario esiste in due versioni: una per ragazzi più grandi e adolescenti, e una per genitori/caregiver di bambini che hanno ricevuto trattamento. Utilizzeremo la versione per genitori/caregiver.
La versione parentale del CHI-ESQ è composta da 12 domande:
- I feel that the people who have seen my child listened to me
- It was easy to talk to the people who have seen my child
- I was treated well by the people who have seen my child
- My views and worries were taken seriously
- I feel the people here know how to help with the problem I came for
- I have been given enough explanation about the help available here
- I feel that the people who have seen my child are working together to help with the problem(s)
- The facilities here are comfortable (e.g. waiting area)
- The appointments are usually at a convenient time (e.g. don’t interfere with work, school)
- It is quite easy to get to the place where the appointments are
- If a friend needed similar help, I would recommend that he or she come here
- Overall, the help I have received here is good
Le risposte utilizzano tre categorie ordinate: “Certamente vero” — “Parzialmente vero” — “Non vero” (codificate 1–2–3).
Il campione è composto da N = 530 genitori che riportano esperienze con un singolo servizio CAMHS (Brown, Ford, Deighton & Wolpert, 2014).
6.1.1 Passo 0. Carica pacchetti e dati
Scarica il file CHI_ESQ.RData. Crea un nuovo script in cui digiterai tutti i comandi.
# pacchetti
library(lavaan)
library(psych)
# dati
load("~/test-organizzioni-fisppa/slides/06-EFA/data/CHI_ESQ.RData")
dat <- CHI_ESQ # rinomino6.1.2 Passo 1. Esame dell’idoneità dei dati all’analisi fattoriale
Prima di svolgere l’EFA, è sempre utile esaminare le correlazioni tra le variabili.
polychoric(dat)Call: polychoric(x = dat)
Polychoric correlations
es_01 es_02 es_03 es_04 es_05 es_06 es_07 es_08 es_09 es_10 es_11
esqp_01 1.00
esqp_02 0.85 1.00
esqp_03 0.86 0.85 1.00
esqp_04 0.93 0.83 0.83 1.00
esqp_05 0.81 0.71 0.73 0.82 1.00
esqp_06 0.71 0.69 0.66 0.71 0.79 1.00
esqp_07 0.74 0.66 0.75 0.76 0.83 0.80 1.00
esqp_08 0.27 0.38 0.33 0.36 0.18 0.43 0.35 1.00
esqp_09 0.37 0.41 0.33 0.27 0.18 0.31 0.24 0.46 1.00
esqp_10 0.29 0.40 0.38 0.22 0.20 0.24 0.25 0.51 0.44 1.00
esqp_11 0.79 0.70 0.75 0.74 0.77 0.68 0.74 0.32 0.32 0.36 1.00
esqp_12 0.89 0.79 0.81 0.87 0.90 0.84 0.84 0.40 0.24 0.29 0.86
[1] 1.00
with tau of
1 2
esqp_01 0.93 2.2
esqp_02 0.99 2.2
esqp_03 1.30 2.5
esqp_04 0.87 1.9
esqp_05 0.44 1.6
esqp_06 0.42 1.5
esqp_07 0.61 1.6
esqp_08 0.70 2.0
esqp_09 0.22 1.2
esqp_10 0.70 1.5
esqp_11 0.97 1.8
esqp_12 0.99 1.8
Esamina attentamente le correlazioni, cosa noti?
Calcola ora l’indice Kaiser-Meyer-Olkin (KMO), la misura di adeguatezza campionaria (MSA dei dati per l’analisi fattoriale prendendo in considerazione le correlazioni parziali degli item):
KMO(dat)Kaiser-Meyer-Olkin factor adequacy
Call: KMO(r = dat)
Overall MSA = 0.91
MSA for each item =
esqp_01 esqp_02 esqp_03 esqp_04 esqp_05 esqp_06 esqp_07 esqp_08 esqp_09 esqp_10
0.90 0.94 0.94 0.91 0.93 0.92 0.93 0.74 0.79 0.77
esqp_11 esqp_12
0.94 0.93
Interpreta il risultato.
6.1.3 Passo 2. Determinazione del numero di fattori
Per determinare il numero di fattori, utilizziamo la parallel analysis del pacchetto psych come strumento esplorativo, con il metodo di stima predefinito (fm = "minres") e visualizzando gli autovalori.
fa.parallel(dat, fa = "fa")Parallel analysis suggests that the number of factors = 3 and the number of components = NA
Esamina lo scree plot. Cosa suggerisce? Perchè lo suggerisce? E se invece guardassimo alla soglia di Keiser?
E se guardassimo i MAP?
R <- polychoric(dat)$rho
VSS(R, plot = FALSE, n.obs = nrow(dat), n = 3,
rotate = "oblimin")
Very Simple Structure
Call: vss(x = x, n = n, rotate = rotate, diagonal = diagonal, fm = fm,
n.obs = n.obs, plot = plot, title = title, use = use, cor = cor)
VSS complexity 1 achieves a maximimum of 0.94 with 1 factors
VSS complexity 2 achieves a maximimum of 0.92 with 2 factors
The Velicer MAP achieves a minimum of 0.07 with 2 factors
BIC achieves a minimum of 685.8 with 3 factors
Sample Size adjusted BIC achieves a minimum of 790.56 with 3 factors
Statistics by number of factors
vss1 vss2 map dof chisq prob sqresid fit RMSEA BIC SABIC complex
1 0.94 0.00 0.072 54 1886 0.0e+00 3.8 0.94 0.25 1547 1718 1.0
2 0.88 0.92 0.069 43 1450 6.9e-276 5.3 0.92 0.25 1180 1316 1.0
3 0.88 0.89 0.077 33 893 3.2e-166 5.2 0.92 0.22 686 791 1.1
eChisq SRMR eCRMS eBIC
1 590 0.092 0.101 251
2 123 0.042 0.052 -147
3 44 0.025 0.036 -163
6.1.4 Passo 3. Modello EFA a 1 fattore
In lavaan, l’EFA si specifica con la funzione efa(), per dati ordinali è importante aggiungere l’argomento ordered = TRUE.
# Modello EFA a 1 fattore
fit1 <- efa(data = dat,
nfactors = 1,
ordered = TRUE)
summary(fit1, fit.measures = TRUE)This is lavaan 0.6-21 -- running exploratory factor analysis
Estimator DWLS
Rotation method GEOMIN OBLIQUE
Geomin epsilon 0.001
Rotation algorithm (rstarts) GPA (30)
Standardized metric TRUE
Row weights None
Number of observations 530
Fit measures:
chisq df pvalue cfi rmsea
nfactors = 1 331.028 54 0 0.81 0.228
Eigenvalues correlation matrix:
ev1 ev2 ev3 ev4 ev5 ev6 ev7 ev8
7.7468 1.5687 0.6617 0.5845 0.4428 0.2878 0.2223 0.1920
ev9 ev10 ev11 ev12
0.1177 0.0971 0.0603 0.0182
Standardized loadings: (* = significant at 1% level)
f1 unique.var communalities
esqp_01 0.959* 0.081 0.919
esqp_02 0.872* 0.240 0.760
esqp_03 0.890* 0.207 0.793
esqp_04 0.941* 0.115 0.885
esqp_05 0.901* 0.189 0.811
esqp_06 0.840* 0.295 0.705
esqp_07 0.870* 0.244 0.756
esqp_08 0.435* 0.810 0.190
esqp_09 0.378* 0.857 0.143
esqp_10 0.385* 0.852 0.148
esqp_11 0.849* 0.279 0.721
esqp_12 0.957* 0.084 0.916
f1
Sum of squared loadings 7.745
Proportion of total 1.000
Proportion var 0.645
Cumulative var 0.645
Sulla base degli indici di fit, il modello a 1 fattore si adatta adeguatamente ai dati? Quali indici suggeriscono un adattamento accettabile e quali lo rifiutano?
Guarda anche gli Eigenvalues, cosa potresti aggiungere all’interpretazione?
6.1.5 Passo 4. Modello EFA a 2 fattori
# Modello EFA a 2 fattori (rotazione obliqua oblimin, default)
fit2 <- efa(data = dat,
nfactors = 2,
rotation = "oblimin",
ordered = TRUE)
summary(fit2, fit.measures = TRUE)This is lavaan 0.6-21 -- running exploratory factor analysis
Estimator DWLS
Rotation method OBLIMIN OBLIQUE
Oblimin gamma 0
Rotation algorithm (rstarts) GPA (30)
Standardized metric TRUE
Row weights None
Number of observations 530
Fit measures:
chisq df pvalue cfi rmsea
nfactors = 2 138.405 43 0 0.869 0.212
Eigenvalues correlation matrix:
ev1 ev2 ev3 ev4 ev5 ev6 ev7 ev8
7.7468 1.5687 0.6617 0.5845 0.4428 0.2878 0.2223 0.1920
ev9 ev10 ev11 ev12
0.1177 0.0971 0.0603 0.0182
Standardized loadings: (* = significant at 1% level)
f1 f2 unique.var communalities
esqp_01 0.869* .* 0.071 0.929
esqp_02 0.718* 0.323* 0.197 0.803
esqp_03 0.764* .* 0.186 0.814
esqp_04 0.873* .* 0.111 0.889
esqp_05 1.010* .* 0.112 0.888
esqp_06 0.854* 0.290 0.710
esqp_07 0.916* . 0.226 0.774
esqp_08 . 0.614* 0.549 0.451
esqp_09 0.603* 0.599 0.401
esqp_10 0.661* 0.543 0.457
esqp_11 0.833* 0.275 0.725
esqp_12 0.992* 0.064 0.936
f1 f2 total
Sum of sq (obliq) loadings 7.097 1.681 8.778
Proportion of total 0.808 0.192 1.000
Proportion var 0.591 0.140 0.731
Cumulative var 0.591 0.731 0.731
Factor correlations: (* = significant at 1% level)
f1 f2
f1 1.000
f2 0.394* 1.000
Ora confronta gli indici dei due modelli:
fit <- efa(data = dat, nfactors = 1:2, ordered = TRUE, rotation = "oblimin")
summary(fit)This is lavaan 0.6-21 -- running exploratory factor analysis
Estimator DWLS
Rotation method OBLIMIN OBLIQUE
Oblimin gamma 0
Rotation algorithm (rstarts) GPA (30)
Standardized metric TRUE
Row weights None
Number of observations 530
Overview models:
chisq df pvalue cfi rmsea
nfactors = 1 331.028 54 0 0.810 0.228
nfactors = 2 138.405 43 0 0.869 0.212
Eigenvalues correlation matrix:
ev1 ev2 ev3 ev4 ev5 ev6 ev7 ev8
7.7468 1.5687 0.6617 0.5845 0.4428 0.2878 0.2223 0.1920
ev9 ev10 ev11 ev12
0.1177 0.0971 0.0603 0.0182
Number of factors: 1
Standardized loadings: (* = significant at 1% level)
f1 unique.var communalities
esqp_01 0.959* 0.081 0.919
esqp_02 0.872* 0.240 0.760
esqp_03 0.890* 0.207 0.793
esqp_04 0.941* 0.115 0.885
esqp_05 0.901* 0.189 0.811
esqp_06 0.840* 0.295 0.705
esqp_07 0.870* 0.244 0.756
esqp_08 0.435* 0.810 0.190
esqp_09 0.378* 0.857 0.143
esqp_10 0.385* 0.852 0.148
esqp_11 0.849* 0.279 0.721
esqp_12 0.957* 0.084 0.916
f1
Sum of squared loadings 7.745
Proportion of total 1.000
Proportion var 0.645
Cumulative var 0.645
Number of factors: 2
Standardized loadings: (* = significant at 1% level)
f1 f2 unique.var communalities
esqp_01 0.869* .* 0.071 0.929
esqp_02 0.718* 0.323* 0.197 0.803
esqp_03 0.764* .* 0.186 0.814
esqp_04 0.873* .* 0.111 0.889
esqp_05 1.010* .* 0.112 0.888
esqp_06 0.854* 0.290 0.710
esqp_07 0.916* . 0.226 0.774
esqp_08 . 0.614* 0.549 0.451
esqp_09 0.603* 0.599 0.401
esqp_10 0.661* 0.543 0.457
esqp_11 0.833* 0.275 0.725
esqp_12 0.992* 0.064 0.936
f1 f2 total
Sum of sq (obliq) loadings 7.097 1.681 8.778
Proportion of total 0.808 0.192 1.000
Proportion var 0.591 0.140 0.731
Cumulative var 0.591 0.731 0.731
Factor correlations: (* = significant at 1% level)
f1 f2
f1 1.000
f2 0.394* 1.000
Confronta gli indici di fit del modello a 2 fattori con quelli del modello a 1 fattore.
Per valutare la buona fit di un modello fattoriale esplorativo vanno tenuti a mente anche i principi di:
- Causazione: Varianza spiegata da/dai fattore/i latenti
- Parsimonia: Non aggiungere fattori non necessari
- Struttura semplice: Almeno 3 item per fattore e nessun cross-loading
Quali item caricano prevalentemente sul Fattore 1 e quali sul Fattore 2? Proponi un’etichetta interpretativa per ciascun fattore, considerando il contenuto degli item. Interpreta poi la correlazione tra i fattori latenti: cosa implica riguardo alla struttura della soddisfazione misurata dal CHI-ESQ?
6.1.6 Passo 5. Confronto con la rotazione ortogonale (varimax)
Per confronto, specifica una rotazione ortogonale varimax, che vincola i fattori a essere non correlati:
fit2_varimax <- efa(data = CHI_ESQ,
nfactors = 2,
ordered = TRUE,
rotation = "varimax")
summary(fit2_varimax)This is lavaan 0.6-21 -- running exploratory factor analysis
Estimator DWLS
Rotation method VARIMAX ORTHOGONAL
Rotation algorithm (rstarts) GPA (30)
Standardized metric TRUE
Row weights Kaiser
Number of observations 530
Fit measures:
chisq df pvalue cfi rmsea
nfactors = 2 138.405 43 0 0.869 0.212
Eigenvalues correlation matrix:
ev1 ev2 ev3 ev4 ev5 ev6 ev7 ev8
7.7468 1.5687 0.6617 0.5845 0.4428 0.2878 0.2223 0.1920
ev9 ev10 ev11 ev12
0.1177 0.0971 0.0603 0.0182
Standardized loadings: (* = significant at 1% level)
f1 f2 unique.var communalities
esqp_01 0.862* 0.431* 0.071 0.929
esqp_02 0.733* 0.516* 0.197 0.803
esqp_03 0.769* 0.471* 0.186 0.814
esqp_04 0.860* 0.388* 0.111 0.889
esqp_05 0.941* 0.112 0.888
esqp_06 0.818* .* 0.290 0.710
esqp_07 0.868* .* 0.226 0.774
esqp_08 .* 0.642* 0.549 0.451
esqp_09 .* 0.617* 0.599 0.401
esqp_10 . 0.665* 0.543 0.457
esqp_11 0.808* .* 0.275 0.725
esqp_12 0.946* .* 0.064 0.936
f1 f2 total
Sum of sq (ortho) loadings 6.540 2.238 8.778
Proportion of total 0.745 0.255 1.000
Proportion var 0.545 0.186 0.731
Cumulative var 0.545 0.731 0.731
Confronta i carichi fattoriali della soluzione varimax con quelli della soluzione oblimin. Quale soluzione produce item più factorially simple (che caricano chiaramente su un solo fattore)? Quale è più facile da interpretare?