Prendo il focus della domanda è meno sul lato teorico e più sul lato pratico, cioè come implementare un'analisi fattoriale dei dati dicotomici in R.
Innanzitutto, simuliamo 200 osservazioni da 6 variabili, provenienti da 2 fattori ortogonali. Prenderò un paio di passaggi intermedi e inizierò con dati continui normali multivariati che in seguito dichoto. In questo modo, possiamo confrontare le correlazioni di Pearson con le correlazioni policoriche e confrontare i caricamenti dei fattori da dati continui con quello dei dati dicotomici e i caricamenti reali.
set.seed(1.234)
N <- 200 # number of observations
P <- 6 # number of variables
Q <- 2 # number of factors
# true P x Q loading matrix -> variable-factor correlations
Lambda <- matrix(c(0.7,-0.4, 0.8,0, -0.2,0.9, -0.3,0.4, 0.3,0.7, -0.8,0.1),
nrow=P, ncol=Q, byrow=TRUE)
x = Λ f+ eXΛfe
library(mvtnorm) # for rmvnorm()
FF <- rmvnorm(N, mean=c(5, 15), sigma=diag(Q)) # factor scores (uncorrelated factors)
E <- rmvnorm(N, rep(0, P), diag(P)) # matrix with iid, mean 0, normal errors
X <- FF %*% t(Lambda) + E # matrix with variable values
Xdf <- data.frame(X) # data also as a data frame
Esegui l'analisi dei fattori per i dati continui. I caricamenti stimati sono simili a quelli veri quando si ignora il segno irrilevante.
> library(psych) # for fa(), fa.poly(), factor.plot(), fa.diagram(), fa.parallel.poly, vss()
> fa(X, nfactors=2, rotate="varimax")$loadings # factor analysis continuous data
Loadings:
MR2 MR1
[1,] -0.602 -0.125
[2,] -0.450 0.102
[3,] 0.341 0.386
[4,] 0.443 0.251
[5,] -0.156 0.985
[6,] 0.590
Ora dicotomizziamo i dati. Conserveremo i dati in due formati: come un frame di dati con fattori ordinati e come matrice numerica. hetcor()
dal pacchetto polycor
ci fornisce la matrice di correlazione policorica che useremo in seguito per l'AF.
# dichotomize variables into a list of ordered factors
Xdi <- lapply(Xdf, function(x) cut(x, breaks=c(-Inf, median(x), Inf), ordered=TRUE))
Xdidf <- do.call("data.frame", Xdi) # combine list into a data frame
XdiNum <- data.matrix(Xdidf) # dichotomized data as a numeric matrix
library(polycor) # for hetcor()
pc <- hetcor(Xdidf, ML=TRUE) # polychoric corr matrix -> component correlations
Ora usa la matrice di correlazione policorica per fare una FA regolare. Si noti che i carichi stimati sono abbastanza simili a quelli dei dati continui.
> faPC <- fa(r=pc$correlations, nfactors=2, n.obs=N, rotate="varimax")
> faPC$loadings
Loadings:
MR2 MR1
X1 -0.706 -0.150
X2 -0.278 0.167
X3 0.482 0.182
X4 0.598 0.226
X5 0.143 0.987
X6 0.571
Puoi saltare tu stesso il passaggio del calcolo della matrice di correlazione policorica e utilizzare direttamente fa.poly()
dal pacchetto psych
, che alla fine fa la stessa cosa. Questa funzione accetta i dati dicotomici grezzi come matrice numerica.
faPCdirect <- fa.poly(XdiNum, nfactors=2, rotate="varimax") # polychoric FA
faPCdirect$fa$loadings # loadings are the same as above ...
EDIT: per i punteggi dei fattori, guarda il pacchetto ltm
che ha una factor.scores()
funzione specifica per i risultati dei risultati politomici. Un esempio è fornito in questa pagina -> "Punteggi dei fattori - Stime delle abilità".
È possibile visualizzare i caricamenti dall'analisi dei fattori utilizzando factor.plot()
e fa.diagram()
, entrambi dal pacchetto psych
. Per qualche motivo, factor.plot()
accetta solo il $fa
componente del risultato fa.poly()
, non l'intero oggetto.
factor.plot(faPCdirect$fa, cut=0.5)
fa.diagram(faPCdirect)
L'analisi parallela e un'analisi di "struttura molto semplice" forniscono un aiuto nella selezione del numero di fattori. Ancora una volta, il pacchetto psych
ha le funzioni richieste. vss()
prende come argomento la matrice di correlazione policorica.
fa.parallel.poly(XdiNum) # parallel analysis for dichotomous data
vss(pc$correlations, n.obs=N, rotate="varimax") # very simple structure
Il pacchetto fornisce anche un'analisi parallela per l'AF policorica random.polychor.pa
.
library(random.polychor.pa) # for random.polychor.pa()
random.polychor.pa(data.matrix=XdiNum, nrep=5, q.eigen=0.99)
Si noti che le funzioni fa()
e fa.poly()
forniscono molte altre opzioni per impostare l'AF. Inoltre, ho modificato parte dell'output che fornisce bontà dei test di adattamento, ecc. La documentazione per queste funzioni (e il pacchetto psych
in generale) è eccellente. Questo esempio qui è solo per iniziare.