Làm thế nào để tính toán các thành phần chính xoay vòng varimax trong R?


13

Tôi đã chạy PCA trên 25 biến và chọn 7 PC hàng đầu sử dụng prcomp.

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

Sau đó tôi đã thực hiện xoay varimax trên các thành phần đó.

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

Và bây giờ tôi muốn varimax xoay dữ liệu xoay PCA (vì nó không phải là một phần của đối tượng varimax - chỉ có ma trận tải và ma trận xoay). Tôi đọc rằng để làm điều này, bạn nhân số chuyển vị của ma trận xoay với chuyển vị của dữ liệu để tôi có thể thực hiện điều này:

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

Nhưng điều đó không có nghĩa gì khi các kích thước của ma trận chuyển đổi ở trên là và 7 × 16933 và vì vậy tôi sẽ chỉ còn lại một ma trận gồm 7 hàng, thay vì 16933 hàng ... có ai biết không Tôi đang làm sai ở đây hoặc dòng cuối cùng của tôi nên là gì? Tôi chỉ cần chuyển đổi trở lại sau đó?7×77×16933716933

Câu trả lời:


22

"Xoay vòng" là một cách tiếp cận được phát triển trong phân tích nhân tố; có các phép quay (chẳng hạn như varimax) được áp dụng cho tải , không hàm riêng của ma trận hiệp phương sai. Tải trọng là các hàm riêng được chia tỷ lệ theo căn bậc hai của các giá trị riêng tương ứng. Sau khi xoay varimax, các vectơ tải không còn trực giao nữa (mặc dù phép quay được gọi là "trực giao"), do đó, người ta không thể đơn giản tính toán các phép chiếu trực giao của dữ liệu lên các hướng tải được xoay.

Câu trả lời của @ FTusell giả định rằng xoay varimax được áp dụng cho các hàm riêng (không cho tải). Điều này sẽ là khá độc đáo. Vui lòng xem tài khoản chi tiết của tôi về PCA + varimax để biết chi tiết: PCA có được theo sau bởi một vòng quay (chẳng hạn như varimax) vẫn là PCA không? Tóm lại, nếu chúng ta nhìn vào SVD của ma trận dữ liệu , sau đó để xoay loadings phương tiện chèn R R đối với một số vòng quay ma trận R như sau: X = ( U R ) ( R S V ) .X=USVRRRX=(UR)(RSV).

Nếu xoay được áp dụng cho tải (như thường lệ), thì có ít nhất ba cách dễ dàng để tính toán các máy tính xoay vòng varimax trong R:

  1. Chúng có sẵn thông qua chức năng psych::principal(chứng minh rằng đây thực sự là phương pháp tiêu chuẩn). Lưu ý rằng nó trả về điểm số được tiêu chuẩn hóa , tức là tất cả các PC có phương sai đơn vị.

  2. Người ta có thể sử dụng varimaxchức năng thủ công để xoay các tải trọng, và sau đó sử dụng các tải trọng xoay mới để đạt được điểm số; người ta cần phải nhân nhiều dữ liệu với giả nghịch đảo của các tải được xoay (xem công thức trong câu trả lời này của @ttnphns ). Điều này cũng sẽ mang lại điểm số tiêu chuẩn.

  3. Người ta có thể sử dụng varimaxchức năng để xoay các tải, và sau đó sử dụng $rotmatma trận xoay để xoay các điểm số tiêu chuẩn thu được với prcomp.

Tất cả ba phương pháp đều cho kết quả như nhau:

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

Điều này mang lại ba đầu ra giống hệt nhau:

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

Lưu ý: Các varimaxhàm trong R sử dụng normalize = TRUE, eps = 1e-5các thông số mặc định ( xem tài liệu ). Người ta có thể muốn thay đổi các tham số này (giảm epsdung sai và quan tâm đến việc chuẩn hóa Kaiser) khi so sánh kết quả với các phần mềm khác như SPSS. Tôi cảm ơn @GottfriedHelms vì đã chú ý đến điều này. [Lưu ý: các tham số này hoạt động khi được truyền cho varimaxhàm, nhưng không hoạt động khi được truyền cho psych::principalhàm. Đây có vẻ là một lỗi sẽ được sửa.]


1
Tôi thấy điều này bây giờ, và tôi nghĩ bạn là chính xác. Tôi sẽ chỉnh sửa câu trả lời ban đầu của mình (hoặc thêm câu trả lời khác) để theo dõi nguồn gốc của sự khác biệt. Tôi thích câu trả lời rất đầy đủ và hấp dẫn của bạn và @ttnphns, cung cấp các giải thích chi tiết không thường thấy trong sách.
F. Tusell

@amoeba Tôi đang cố gắng sử dụng varimax PCA + principal, prcompprincomp, nhưng kết quả tải / kết luận nghiên cứu rất khác nhau. Đối với những gì tôi hiểu, prcomp và Princomp không trả lại điểm chuẩn cũng như tải. Câu hỏi của tôi là: cách tiếp cận tốt nhất là gì? Tôi có thực sự muốn kết quả tiêu chuẩn? Không phải mã của tôi pca_iris <- prcomp(irisX, center=T, scale=T)theo sau varimax(pca_iris$rotation)$loadingslà chính xác như của bạn ở trên sao?
JMarcelino

@JMarcelino, không, mã của bạn thực hiện xoay vòng varimax trên các hàm riêng, không phải trên các tải. Đây không phải là cách xoay varimax thường được hiểu hoặc áp dụng.
amip nói rằng Phục hồi lại

1
@JMarcelino, bạn có hỏi tại sao toán học hoạt động như tôi nói nó làm trong phương pháp # 2 không? Thật đơn giản nếu bạn quen thuộc với loại đại số tuyến tính này. PCA là SVD phân hủy . Áp dụng luân phiên như phương tiện varimax chèn R R cho một vòng quay ma trận R như sau: X = U R R S V . Tải trọng xoay là L = V S R / X=USVRRRX=URRSV điểm, xoay chuẩn làT=URL=VSR/n1 , do đóX=TL. Bạn biếtXL; làm thế nào để có đượcT? Vâng, câu trả lời làT=X(L)+=X(L+). T=URn1
X=TL.
XLT
T=X(L)+=X(L+).
amip nói rằng Phục hồi Monica

1
Tôi nhận được câu trả lời của người duy trì gói Giáo sư Revelle. Nó dường như là một lỗi trong việc xử lý các tham số trong principalquy trình, luôn tính toán với chuẩn hóa Kaiser và eps = 1e-5. Cho đến nay không có thông tin, tại sao trên r-fiddle.org phiên bản hoạt động chính xác. Vì vậy, chúng ta nên chờ đợi cập nhật - và tôi nên xóa tất cả các bình luận đã lỗi thời. amip - sẽ tốt hơn nếu cập nhật nhận xét trong câu trả lời của bạn cho phù hợp. Cảm ơn tất cả sự hợp tác!
Gottfried Helms

9

Bạn cần sử dụng ma trận $loadings, không phải $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

Ma trận $rotmatlà ma trận trực giao tạo ra các tải trọng mới từ các ma trận không được bảo vệ.

EDIT kể từ ngày 12 tháng 2 năm 2015:

n×mX

X=USVT
VXX
X=(UST)(TTVT)=UV
TVVUX(V)Tk<mkX
X(UkSk)(VkT)
X(UkSkTk)(TkTVkT)=UkVk
Vkk×nXVk, nhưng thay vào đó, chúng ta cần sử dụng một trong những giải pháp được mô tả bởi @amoeba.

Nói cách khác, giải pháp tôi đề xuất chỉ đúng trong trường hợp cụ thể mà nó sẽ vô dụng và vô nghĩa.

Xin chân thành cảm ơn đến @amoeba vì đã làm rõ vấn đề này với tôi; Tôi đã sống với quan niệm sai lầm này trong nhiều năm.

SVLVSviTX (i=1,,m)vi=1. Tôi nghĩ cách nào cũng được chấp nhận và mọi thứ ở giữa (như trong phân tích biplot).

THÊM EDIT ngày 12 tháng 2 năm 2015

VkVk(Vk)TX(Vk)TUk


1
À đúng rồi. Tôi đã bối rối vì các tải cho prcomp được gọi là "xoay", nên đã đọc trợ giúp tốt hơn. Vì tôi đang sử dụng "centre = TRUE, scale = TRUE" trong phương thức prcomp, điều đó có nghĩa là tôi thực sự phải tập trung và nhân rộng dữ liệu của mình trước khi nhân nó với tải varimax $ của tôi?
Scott

1
Vâng, điểm tốt, sai lầm của tôi. Việc định tâm sẽ không thành vấn đề, vì nếu chỉ thay đổi các điểm, nhưng thang đo sẽ được sử dụng như nhau để tính các thành phần chính, không bất biến đối với tỷ lệ.
F. Tusell

2
Tôi quên đề cập rằng bạn có thể muốn xem xét chức năng trên thực tế, nếu bạn chưa thực hiện nó. Nó không phân tích nhân tố chứ không phải thành phần chính, nhưng sẽ trả về điểm trực tiếp.
F. Tusell

2
-1. Tôi tin rằng câu trả lời này là không chính xác và tôi đã đăng câu trả lời của riêng mình để chứng minh điều đó. Người ta không thể có được điểm quay bằng phép chiếu trực giao trên các tải được xoay (vì chúng không còn trực giao nữa). Cách đơn giản nhất để có được điểm chính xác là sử dụng psych::principal. [Ngoài ra, tôi đã chỉnh sửa câu trả lời của bạn để chèn tỷ lệ, như đã thảo luận trong các ý kiến ​​ở trên.]
amip nói rằng Rebstate Monica

1
Vkk×nV(TkTVkT)(VkTk)

0

Tôi đang tìm kiếm một giải pháp hoạt động cho PCA được thực hiện bằng ade4 .

Vui lòng tìm chức năng dưới đây:

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

Được tạo vào ngày 2020-01-2014 bởi gói reprex (v0.3.0)

Hy vọng điều này giúp đỡ!


Bạn cần sử dụng không gian này cho một câu trả lời.
Michael R. Chernick

Dường như với tôi rằng nó là hợp lệ để thêm một câu trả lời cho đầy đủ. Giống như cho câu hỏi này: stackoverflow.com/questions/6862742/draw-a-circle-with-ggplot2 . Tôi sẽ rất vui khi chuyển đề xuất của mình nếu cần thiết.
Alain Danet

Tôi đã hiểu nhầm bởi vì có vẻ như bạn đang sửa lỗi trong một trong những câu trả lời. Tôi thấy rằng đó là một bổ sung cho một gói phần mềm cụ thể ad4. Xác thực chéo không nhìn vào các câu hỏi hoặc câu trả lời nghiêm túc về mã. Stack Overflow là nơi giải quyết các vấn đề phần mềm.
Michael R. Chernick
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.