Как вычислить повернутые варимаксом главные компоненты в R?


13

Я запустил PCA на 25 переменных и выбрал лучшие 7 компьютеров, используя prcomp.

prc <- prcomp(pollutions, center=T, scale=T, retx=T)

Затем я сделал ротацию варимакса для этих компонентов.

varimax7 <- varimax(prc$rotation[,1:7])

А теперь я хочу, чтобы varimax вращал данные, повернутые PCA (поскольку они не являются частью объекта varimax - только матрица загрузок и матрица вращения). Я прочитал, что для этого вы умножаете транспонирование матрицы вращения на транспонирование данных, поэтому я бы сделал это:

newData <- t(varimax7$rotmat) %*% t(prc$x[,1:7])

Но это не имеет смысла, так как размеры транспонированной матрицы выше 7×7 и 7×16933 соответственно, и поэтому у меня останется только матрица из 7 строк, а не 16933 строк ... Кто-нибудь знает, что я я делаю что-то не так или какова должна быть моя последняя строка? Должен ли я просто потом перенести обратно?

Ответы:


22

«Повороты» - это подход, разработанный в факторном анализе; там вращения (такие как, например, varimax) применяются к нагрузкам , а не к собственным векторам ковариационной матрицы. Нагрузки являются собственными векторами, масштабированными по квадратным корням соответствующих собственных значений. После вращения варимакса векторы нагрузки больше не являются ортогональными (даже если вращение называется «ортогональным»), поэтому нельзя просто вычислить ортогональные проекции данных на повернутые направления загрузки.

Ответ @ FTusell предполагает, что поворот варимакса применяется к собственным векторам (не к нагрузкам). Это было бы довольно нетрадиционно. Пожалуйста, ознакомьтесь с подробным отчетом о моем PCA + varimax: после PCA все еще происходит ротация (например, varimax)? Вкратце, если мы посмотрим на SVD матрицы данных , то вращение нагрузок означает вставку R R для некоторой матрицы вращения R следующим образом: X = ( U R ) ( R S V ) ,Иксзнак равноUSВрррИксзнак равно(Uр)(рSВ),

Если вращение применяется к нагрузкам (как это обычно бывает), то существует как минимум три простых способа вычисления ПК с переменным поворотом в R:

  1. Они легко доступны через функцию psych::principal(демонстрируя, что это действительно стандартный подход). Обратите внимание, что он возвращает стандартизированные оценки , т. Е. Все компьютеры имеют дисперсию единиц.

  2. Можно вручную использовать varimaxфункцию для поворота нагрузок, а затем использовать новые повернутые нагрузки для получения баллов; необходимо умножить данные на транспонированные псевдообратные повернутые нагрузки (см. формулы в этом ответе @ttnphns ). Это также даст стандартизированные оценки.

  3. Можно использовать varimaxфункцию, чтобы вращать нагрузки, а затем использовать $rotmatматрицу вращения, чтобы вращать стандартизированные оценки, полученные с prcomp.

Все три метода дают одинаковый результат:

irisX <- iris[,1:4]      # Iris data
ncomp <- 2

pca_iris_rotated <- psych::principal(irisX, rotate="varimax", nfactors=ncomp, scores=TRUE)
print(pca_iris_rotated$scores[1:5,])  # Scores returned by principal()

pca_iris        <- prcomp(irisX, center=T, scale=T)
rawLoadings     <- pca_iris$rotation[,1:ncomp] %*% diag(pca_iris$sdev, ncomp, ncomp)
rotatedLoadings <- varimax(rawLoadings)$loadings
invLoadings     <- t(pracma::pinv(rotatedLoadings))
scores          <- scale(irisX) %*% invLoadings
print(scores[1:5,])                   # Scores computed via rotated loadings

scores <- scale(pca_iris$x[,1:2]) %*% varimax(rawLoadings)$rotmat
print(scores[1:5,])                   # Scores computed via rotating the scores

Это дает три идентичных выхода:

1 -1.083475  0.9067262
2 -1.377536 -0.2648876
3 -1.419832  0.1165198
4 -1.471607 -0.1474634
5 -1.095296  1.0949536

Примечание . varimaxФункция в R normalize = TRUE, eps = 1e-5по умолчанию использует параметры ( см. Документацию ). Можно хотеть изменить эти параметры (уменьшить epsдопуск и позаботиться о нормализации Кайзера) при сравнении результатов с другим программным обеспечением, таким как SPSS. Я благодарю @GottfriedHelms за то, что обратили на это мое внимание. [Примечание: эти параметры работают при передаче в varimaxфункцию, но не работают при передаче в psych::principalфункцию. Похоже, это ошибка, которая будет исправлена.]


1
Я вижу это сейчас, и я думаю, что вы правы. Я отредактирую свой первоначальный ответ (или добавлю еще один), чтобы отследить источник расхождений. Мне понравились ваши и @ttnphns очень полные и содержательные ответы, содержащие подробные объяснения, которые обычно не встречаются в книгах.
Ф. Тусел

@amoeba Я пытаюсь сделать PCA + varimax, используя principal, prcompи princomp, но полученные нагрузки / выводы исследования сильно отличаются друг от друга. Насколько я понимаю, prcomp и princomp не возвращают ни стандартизированные оценки, ни загрузки. Мой вопрос: каков наилучший подход? Я действительно хочу стандартизированные результаты? Разве мой код не pca_iris <- prcomp(irisX, center=T, scale=T)является varimax(pca_iris$rotation)$loadingsтаким же правильным, как ваш выше?
JMarcelino

@JMarcelino, нет, ваш код выполняет варимакс-вращение по собственным векторам, а не по нагрузкам. Это не то, как варимакс вращение обычно понимается или применяется.
говорит амеба, восстанови Монику

1
@JMarcelino, вы спрашиваете, почему математика работает так, как я говорю, в методе № 2? Это просто, если вы знакомы с этим типом линейной алгебры. ПХД разложения . Применение вращения, такого как varimax, означает вставку R R matrix для матрицы вращения R следующим образом:Иксзнак равноUSВррр . Вращаемые нагрузки L = V S R / Иксзнак равноUррSВ , повернутые стандартизированные оценкиT=URLзнак равноВSр/N-1 , поэтомуX=TL. Вы знаетеXиL; как получитьТ? Ну, ответ:T=X(L)+=X(L+). Tзнак равноUрN-1
Иксзнак равноTL,
ИксLT
T=X(L)+=X(L+).
говорит амеба, восстанови Монику

1
Я получил ответ от сопровождающего пакета профессора Ревелла. Кажется, это ошибка в обработке параметров в principalпроцедуре, которая всегда вычисляется с помощью Kaiser-normalization и eps = 1e-5. Пока нет информации, почему на r-fiddle.org версия работает правильно. Поэтому мы должны ждать обновлений - и я должен удалить все устаревшие комментарии. амеба - было бы хорошо обновить примечание в вашем ответе соответственно. Спасибо за сотрудничество!
Готфрид Хелмс

9

Вам нужно использовать матрицу $loadings, а не $rotmat:

 x <- matrix(rnorm(600),60,10)
 prc <- prcomp(x, center=TRUE, scale=TRUE)
 varimax7 <- varimax(prc$rotation[,1:7])
 newData <- scale(x) %*% varimax7$loadings

Матрица $rotmat- это ортогональная матрица, которая генерирует новые нагрузки из неповрежденных.

ИЗМЕНИТЬ по состоянию на 12 февраля 2015 года:

n×mX

X=USVT
VXX
X=(UST)(TTVT)=UV
TVVUX(V)Tk<mkX
X(UkSk)(VkT)
X(UkSkTk)(TkTVkT)=UkVk
Vkk×nXVk, а нам нужно прибегнуть к одному из решений, описанных @amoeba.

Другими словами, предложенное мной решение является правильным только в том конкретном случае, когда оно будет бесполезным и бессмысленным.

Сердечная благодарность @amoeba за разъяснение этого вопроса для меня; Я жил с этим заблуждением в течение многих лет.

SVLVSviTX (i=1,,m)vi=1, Я думаю, что любой способ приемлем, и все промежуточное (как в анализе биплота).

ДОПОЛНИТЕЛЬНОЕ РЕДАКТИРОВАНИЕ 12 февраля 2015 г.

VkVk(Vk)TИкс(ВК*)TUК*, Так что все, кажется, зависит от определения баллов, которые предпочитают.


1
Ах, верно, великий. Я запутался, потому что нагрузки для prcomp называются «ротацией», следовало бы лучше прочитать справку. Так как я использую «center = TRUE, scale = TRUE» в методе prcomp, означает ли это, что на самом деле я должен центрировать и масштабировать свои данные перед тем, как их умножить на мои загрузки varimax $?
Скотт

1
Да, хорошая мысль, моя ошибка. Центрирование не имело бы значения, как если бы только сдвигало точки, но масштаб должен быть таким же, который используется для вычисления главных компонентов, которые не являются инвариантными для масштабирования.
Ф. Туселл

2
Я забыл упомянуть, что вы можете посмотреть на функцию factanal, если вы еще этого не сделали. Он выполняет факторный анализ, а не основные компоненты, но возвращает результаты напрямую.
Ф. Туселл

2
-1. Я считаю, что этот ответ не является правильным, и я опубликовал свой собственный ответ, чтобы продемонстрировать его. Нельзя получить повернутые баллы путем ортогональной проекции на повернутые нагрузки (потому что они больше не ортогональны). Самый простой способ получить правильные оценки - это использовать psych::principal. [Кроме того, я отредактировал ваш ответ, чтобы вставить шкалу, как обсуждалось в комментариях выше.]
говорит амеба Восстановить Монику

1
Извините, это моя ошибка. я имел в видуВК* является К×N, Я исправлю это сейчас. И ... да, теперь, когда я смотрю на это,В имеет ортогональные столбцы так (TКTВКT)(ВКTК)все равно принесет нам единичную матрицу, верно? Если это так, я не ввел в заблуждение оригинальный постер, вы поднимаете груз из моей души!
Ф. Туселл

0

Я искал решение, которое работает для PCA, выполненного с использованием ade4 .

Пожалуйста, найдите функцию ниже:

library(ade4)

irisX <- iris[,1:4]      # Iris data
ncomp <- 2
# With ade4
dudi_iris <- dudi.pca(irisX, scannf = FALSE, nf = ncomp)

rotate_dudi.pca <- function(pca, ncomp = 2) {

  rawLoadings <- as.matrix(pca$c1[,1:ncomp]) %*% diag(sqrt(pca$eig), ncomp, ncomp)
  pca$c1 <- rawLoadings
  pca$li <- scale(pca$li[,1:ncomp]) %*% varimax(rawLoadings)$rotmat

  return(pca)
} 
rot_iris <- rotate_dudi.pca(pca = dudi_iris, ncomp = ncomp)
print(rot_iris$li[1:5,])                   # Scores computed via rotating the scores
#>        [,1]       [,2]
#> 1 -1.083475 -0.9067262
#> 2 -1.377536  0.2648876
#> 3 -1.419832 -0.1165198
#> 4 -1.471607  0.1474634
#> 5 -1.095296 -1.0949536

Создано 2020-01-14 пакетом представлением (v0.3.0)

Надеюсь, это поможет!


Вам нужно использовать это место для ответа.
Майкл Р. Черник

Мне показалось, что справедливо добавить ответ для полноты. Как и для этого вопроса: stackoverflow.com/questions/6862742/draw-a-circle-with-ggplot2 . Я буду рад переместить мое предложение в случае необходимости.
Ален Данет

Я неправильно понял, потому что это звучало так, как будто вы исправляли ошибку в одном из ответов. Я вижу, что это дополнение к определенному программному пакету ad4. Cross Validated не рассматривает вопросы или ответы, которые строго касаются кода. Переполнение стека - это место, где решаются проблемы с программным обеспечением.
Майкл Р. Черник
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.