Невозможно воспроизвести вращение варимакс из психики: изменен порядок факторов

Мне нужно программно воспроизвести автоматическое (варимаксное) вращение из 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 был применен к прошлой версии основных компонентов в их исходном порядке.


person maxheld    schedule 02.09.2015    source источник


Ответы (1)


На самом деле это дубликат этот вопрос в порядке возвращенных загрузок в psych::principalpsych::fa), и поэтому помечен.

Вот как вы можете воспроизвести вращение варимакс из psych::principal, применяя тот же порядок:

# using code from within psych::principal, as per this answer: https://stackoverflow.com/questions/16896959/psychprincipal-explanation-for-the-order-and-naming-of-rotated-principal-c
ev.rotated <- diag(t(manual.varimax) %*% manual.varimax)  # find eigenvalues
ev.order <- order(ev.rotated, decreasing = TRUE)  # order by eigenvalues
manual.varimax <- manual.varimax[, ev.order]

round(manual.varimax, 14) == round(principal.varimax, 14)  # works now
#>     [,1] [,2] [,3] [,4]
#> 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
person maxheld    schedule 02.09.2015