Мне нужно программно воспроизвести автоматическое (варимаксное) вращение из psych::principal
для целей тестирования.
Оказывается, для некоторых данных я не могу воспроизвести это вращение из psych
, потому что, по-видимому, порядок компонентов в выходных данных изменяется при вращении.
Рассмотрим этот воспроизводимый пример:
# some dataset from psych
library(psych)
data("Thurstone")
principal.unrotated <- principal(r = Thurstone, nfactors = 4, rotate = "none")$loa # calculate unrotated loadings
principal.varimax <- principal(r = Thurstone, nfactors = 4, rotate = "varimax")$loa # calculate varimax rotated loadings
rot.mat.varimax <- varimax(x = principal.unrotated)$rotmat # manually calculate varimax rotmat on unrotated loadings
round(x = unclass(principal.unrotated) %*% rot.mat.varimax, digits = 12) == round(x = unclass(principal.varimax), digits = 12) # works as expected
#> [,1] [,2] [,3] [,4]
#> Sentences TRUE TRUE TRUE TRUE
#> Vocabulary TRUE TRUE TRUE TRUE
#> Sent.Completion TRUE TRUE TRUE TRUE
#> First.Letters TRUE TRUE TRUE TRUE
#> 4.Letter.Words TRUE TRUE TRUE TRUE
#> Suffixes TRUE TRUE TRUE TRUE
#> Letter.Series TRUE TRUE TRUE TRUE
#> Pedigrees TRUE TRUE TRUE TRUE
#> Letter.Group TRUE TRUE TRUE TRUE
# same procedure using some dataset from another package
library(qmethod)
data("lipset")
Lipset <- cor(x = lipset[[1]], method = "pearson") # must calculate cor matrix first
principal.unrotated <- principal(r = Lipset, nfactors = 4, rotate = "none")$loa # calculate unrotated loadings
principal.varimax <- principal(r = Lipset, nfactors = 4, rotate = "varimax")$loa # calculate varimax rotated loadings
rot.mat.varimax <- varimax(x = principal.unrotated)$rotmat # manually calculate varimax rotmat on unrotated loadings
round(x = unclass(principal.unrotated) %*% rot.mat.varimax, digits = 12) == round(x = unclass(principal.varimax), digits = 12) # fails
#> [,1] [,2] [,3] [,4]
#> US1 FALSE FALSE TRUE TRUE
#> US2 FALSE FALSE TRUE TRUE
#> US3 FALSE FALSE TRUE TRUE
#> US4 FALSE FALSE TRUE TRUE
#> JP5 FALSE FALSE TRUE TRUE
#> CA6 FALSE FALSE TRUE TRUE
#> UK7 FALSE FALSE TRUE TRUE
#> US8 FALSE FALSE TRUE TRUE
#> FR9 FALSE FALSE TRUE TRUE
round(unclass(principal.varimax)[, c(2,1,3,4)], 12) == round(unclass(principal.unrotated) %*% rot.mat.varimax, 12) # seems like the ORDER of components is reversed
#> PC1 PC2 PC3 PC4
#> US1 TRUE TRUE TRUE TRUE
#> US2 TRUE TRUE TRUE TRUE
#> US3 TRUE TRUE TRUE TRUE
#> US4 TRUE TRUE TRUE TRUE
#> JP5 TRUE TRUE TRUE TRUE
#> CA6 TRUE TRUE TRUE TRUE
#> UK7 TRUE TRUE TRUE TRUE
#> US8 TRUE TRUE TRUE TRUE
#> FR9 TRUE TRUE TRUE TRUE
- Является ли это ожидаемым поведением, и если да, то почему?
- Как я могу этого избежать?
Обновить
Небольшое дополнение: матрицы поворота фактически одинаковы для обеих процедур:
principal.varimax$rot.mat == rot.mat.varimax
Это подразумевает (немного парадоксально), что rot.mat
был применен к прошлой версии основных компонентов в их исходном порядке.