Я вважаю, що фокус питання полягає не в теоретичній стороні, а більше з практичної сторони, тобто як реалізувати факторний аналіз дихотомічних даних у Р.
Спочатку давайте змоделюємо 200 спостережень із 6 змінних, що походять від 2 ортогональних факторів. Я візьму пару проміжних кроків і почну з багатоваріантних нормальних безперервних даних, які згодом дихотомізую. Таким чином, ми можемо порівняти Пірсонові кореляції з поліхорними кореляціями та порівняти факторні навантаження з безперервних даних з дихотомічними даними та справжніми навантаженнями.
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+ ехΛfе
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
Зробіть факторний аналіз для безперервних даних. Орієнтовні навантаження схожі на справжні, якщо ігнорувати нерелевантний знак.
> 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
Тепер давайте дихотомізуємо дані. Ми збережемо дані у двох форматах: як кадр даних із упорядкованими факторами, і як числова матриця. hetcor()
з пакета polycor
дає нам поліхорну матрицю кореляції, яку ми згодом використовуватимемо для FA.
# 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
Тепер використовуйте поліхіричну кореляційну матрицю, щоб зробити звичайну ФА. Зауважимо, що передбачувані навантаження досить схожі на завантажені з безперервних даних.
> 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
Ви можете пропустити крок обчислення матриці поліхорної кореляції самостійно та безпосередньо скористатися fa.poly()
з пакету psych
, який зрештою робить те саме. Ця функція приймає необроблені дихотомічні дані як числову матрицю.
faPCdirect <- fa.poly(XdiNum, nfactors=2, rotate="varimax") # polychoric FA
faPCdirect$fa$loadings # loadings are the same as above ...
РЕДАКТУВАННЯ: Для оцінки факторів дивіться пакет, ltm
який має factor.scores()
функцію спеціально для даних політомів результатів. Приклад наведено на цій сторінці -> "Оцінки факторів - Оцінки можливостей".
Ви можете візуалізувати навантаження з факторного аналізу, використовуючи factor.plot()
і fa.diagram()
, і з пакету psych
. Чомусь factor.plot()
приймає лише $fa
компонент результату від fa.poly()
, а не повний об'єкт.
factor.plot(faPCdirect$fa, cut=0.5)
fa.diagram(faPCdirect)
Паралельний аналіз та аналіз "дуже простої структури" надають допомогу у виборі кількості факторів. Знову пакет psych
має необхідні функції. vss()
приймає полігорну кореляційну матрицю як аргумент.
fa.parallel.poly(XdiNum) # parallel analysis for dichotomous data
vss(pc$correlations, n.obs=N, rotate="varimax") # very simple structure
Паралельний аналіз на поліхорну ФА також надається пакетом random.polychor.pa
.
library(random.polychor.pa) # for random.polychor.pa()
random.polychor.pa(data.matrix=XdiNum, nrep=5, q.eigen=0.99)
Зауважте, що функції fa()
і fa.poly()
надають ще багато інших варіантів налаштування FA. Крім того, я відредагував частину результатів, які дають змогу добре перевірити відповідність і т. Д. Документація для цих функцій (і пакет psych
взагалі) є відмінною. Цей приклад тут призначений для початку роботи.