R'de varimax döndürülmüş ana bileşenler nasıl hesaplanır?


13

PCA'yı 25 değişken üzerinde çalıştırdım ve kullanarak ilk 7 bilgisayarı seçtim prcomp.

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

Daha sonra bu bileşenler üzerinde varimax rotasyonu yaptım.

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

Ve şimdi varimax PCA döndürülmüş verileri döndürmek istiyorum (varimax nesnesinin bir parçası olmadığı için - sadece yükleme matrisi ve döndürme matrisi). Bunu yapmak için ben bunu yapardı böylece rotasyon matris devri veri devri ile çarpın okuyun:

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

Ancak, yukarıdaki matrisin boyutlarının sırasıyla ve olduğu için mantıklı değil ve bu yüzden satır yerine sadece satırlık bir matris bırakacağım ... kimse biliyor mu burada neyi yanlış yapıyorum ya da son çizgim ne olmalı? Daha sonra geri aktarmam gerekiyor mu?7 × 16933 7 169337×77×16933716933

Yanıtlar:


22

"Rotasyonlar" faktör analizinde geliştirilen bir yaklaşımdır; kovaryans matrisinin özvektörlerine değil, yüklemelere rotasyonlar (örneğin varimax gibi) uygulanır . Yükler, ilgili özdeğerlerin kare kökleri ile ölçeklendirilmiş özvektörlerdir. Varimax dönüşünden sonra, yükleme vektörleri artık dikey değildir (dönüş "dik" olarak adlandırılsa bile), bu nedenle verilerin döndürülmüş yükleme yönleri üzerinde dik açılı izdüşümleri hesaplanamaz.

@ FTusell'in cevabı, özvektörlere varimax rotasyonunun uygulandığını varsayar (yüklemelere değil). Bu oldukça alışılmadık olurdu. Ayrıntılı bilgi için lütfen detaylı PCA + varimax hesabımı inceleyin: PCA'nın ardından hala PCA döndürme (varimax gibi) geliyor mu? Kısaca, veri matrisinin SVD'sine bakarsak , yüklemeleri döndürmek, bazı dönme matrisi için eklenmesi anlamına gelir : R R ' R X = ( U R ) ( R' S V ) .X=USVRRRX=(UR)(RSV).

Yüklere rotasyon uygulanırsa (genellikle olduğu gibi), o zaman R'de varimax döndürülmüş PC'leri hesaplamanın en az üç kolay yolu vardır:

  1. İşlev yoluyla kolayca elde edilebilirler psych::principal(bunun gerçekten standart yaklaşım olduğunu gösterir). Standart skorlar döndürdüğünü , yani tüm PC'lerde birim varyansı olduğunu unutmayın.

  2. varimaxYükleri döndürmek için işlevi manuel olarak kullanabilir ve ardından puanları elde etmek için yeni döndürülmüş yüklemeleri kullanabilirsiniz; döndürülmüş yüklemelerin transpozisyonu sahte tersi ile verilerin çoğaltılması gerekir ( bu cevaptaki @ttnphns formüllerine bakınız ). Bu aynı zamanda standart puanlar da verecektir.

  3. varimaxYükleri döndürmek için işlev kullanılabilir ve ardından $rotmatelde edilen standart puanları döndürmek için döndürme matrisi kullanılabilir prcomp.

Her üç yöntem de aynı sonucu verir:

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

Bu üç özdeş çıkış sağlar:

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

Not:varimax R fonksiyonu kullanan normalize = TRUE, eps = 1e-5varsayılan (parametreleri belgelere bakın ). epsSonuçları SPSS gibi diğer yazılımlarla karşılaştırırken bu parametreleri değiştirmek ( toleransı azaltmak ve Kaiser normalizasyonuna dikkat etmek) gerekebilir . @GottfriedHelms'e bunu dikkatimi çektiği için teşekkür ederim. [Not: Bu parametreler varimaxişleve iletildiğinde çalışır, ancak işleve iletildiğinde psych::principalçalışmaz. Bu, düzeltilecek bir hata gibi görünüyor.]


1
Bunu şimdi görüyorum ve bence haklısın. Tutarsızlığın kaynağını izlemek için orijinal cevabımı düzenleyeceğim (veya başka bir cevap ekleyeceğim). Sizinki ve @ttnphns çok eksiksiz ve İngilizce cevaplar hoşuma gitti, genellikle kitaplarda bulunmayan ayrıntılı açıklamalar sağladım.
F.Tusell

@amoeba Bir PCA + varimax kullanarak yapmaya çalışıyorum principal, prcompve princompfakat çıkan yüklemeleri / çalışma sonuçları birbirinden çok farklıdır. Anladığım kadarıyla, prcomp ve princomp standart puanları veya yüklemeleri iade etmiyor. Sorum şu: en iyi yaklaşım nedir? Gerçekten standartlaştırılmış sonuçlar ister miyim? Kodumun pca_iris <- prcomp(irisX, center=T, scale=T)ardından varimax(pca_iris$rotation)$loadingsyukarıdaki kodunuz kadar doğru değil mi?
JMarcelino

@JMarcelino, hayır, kodunuz yüklemelerde değil özvektörlerde varimax-rotasyonu yapıyor. Varimax rotasyonu genellikle bu şekilde anlaşılmaz veya uygulanmaz.
amip, Reinstate Monica'ya

1
@JMarcelino, matematiğin # 2 yönteminde söylediği gibi neden çalıştığını mı soruyorsunuz? Bu tür doğrusal cebirlere aşina iseniz basittir. PCA, SVD ayrışımı . Varimax gibi bir döndürmenin uygulanması, döndürme matrisi için eklenmesi anlamına gelir : . Döndürülmüş yüklemeler , döndürülmüş standart puanlar , dolayısıyla ve biliyorsunuz ; nasıl alınır ? Cevap R R R X = U R R S V L = V S R / X=USVRRRX=URRSV T=URL=VSR/n1 X=TL. XLTT=X(L)+=X(L+).T=URn1
X=TL.
XLT
T=X(L)+=X(L+).
amip diyor Reinstate Monica

1
Revelle paketinin koruyucusuna bir cevap aldım. principalProsedürdeki parametrelerin işlenmesinde bir hata gibi görünüyor , bu da her zaman Kaiser normalizasyonu ve eps = 1e-5 ile hesaplanıyor . Şu ana kadar hiçbir bilgi yok, neden r-fiddle.org'da sürüm doğru çalışıyor? Bu yüzden güncellemeleri beklemeliyiz - ve şimdi kullanılmayan tüm yorumları silmeliyim. amip - cevabınızdaki ifadeyi buna göre güncellemek iyi olur. Tüm işbirliği için teşekkürler!
Gottfried Helms

9

Matrisi kullanmanız gerekir $loadings, değil $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

Matris $rotmat, döndürülmemiş olanlardan yeni yükler üreten dik matrisdir.

12 Şubat 2015 itibarıyla EDIT:

Aşağıda @amoeba tarafından haklı olarak işaret edildiği gibi (ayrıca önceki yazısının yanı sıra @ttnphns'tan başka bir yazıyı da inceleyin ) bu cevap doğru değil. Bir veri matrisi düşünün . Tekil değer ayrışımı , burada sütunları olarak (normalleştirilmiş) özvektörlerine sahiptir . Şimdi, bir dönme koordinatların değişmesi ve yukarıdaki eşitliğin şu şekilde yazılmasıdır: , bir elde etmek için ortogonal bir matrisdir seyrek yakın (girişler arasındaki maksimum kontrast, gevşek konuşma). Şimdi, hepsi bu olsaydın×mX

X=USVT
VXX
X=(UST)(TTVT)=UV
TVki öyle değil, biri olarak puanları elde etmek için yukarıdaki eşitliği ile çarpabilir , ama elbette tüm PC'yi asla döndürmüyoruz. Aksine, bir alt kümesini hala iyi bir rank- içerir yaklaştırılmasını , Bu şekilde döndürüldüğü çözüm hemen şimdi bir matrisidir. Biz artık öyle değil sadece çarpma can arasında devrik ile ziyade biz çözümlerinden biri @amoeba tarafından tarif başvurmak gerekir.VUX(V)Tk<mkXX(UkSkTk)(T T k V T k )=Uk Vk Vk k×nXVk
X(UkSk)(VkT)
X(UkSkTk)(TkTVkT)=UkVk
Vkk×nXVk

Başka bir deyişle, önerdiğim çözüm sadece işe yaramaz ve saçma olacağı belirli bir durumda doğrudur.

Bu konuyu bana açıklığa kavuşturduğu için içten teşekkürler @amoeba'ya; Yıllardır bu yanlış anlama ile yaşıyorum.

@ Amip yayınının yola yukarıdaki notu o / o ilişkilendirmek gibi görünüyor bir nokta da ile bölgesi . PCA'da norm 1 sütunlarına sahip olması ve temel bileşenin değerlerinde emmesi daha yaygındır . Aslında, bunlar genellikle tabi olan orijinal (ortalanmış, belki ölçeklendirilmiş) değişkenlerin doğrusal kombinasyonları olarak sunulur . Her iki şekilde de kabul edilebilir olduğunu düşünüyorum ve aradaki her şey (biplot analizinde olduğu gibi).SVLVSviTX (i=1,,m)vi=1

FURTHER EDIT - 12 Şubat 2015

@ Amaeba'nın işaret ettiği gibi, dikdörtgen olsa da , önerdiğim çözüm hala kabul edilebilir olabilir: birim matris ve . Yani her şey, birinin tercih ettiği puanların tanımına bağlı görünüyor. V k ( V k ) T X ( V k ) TU kVkVk(Vk)TX(Vk)TUk


1
Ah büyük. Ben prcomp yükleri "döndürme" olarak adlandırılır, çünkü yardım daha iyi okumak zorunda karıştı. Prcomp yönteminde "center = TRUE, scale = TRUE" kullandığım için bu gerçekten varimax $ yüklemelerimle çarpmadan önce verilerimi ortalamam ve ölçeklemem gerektiği anlamına mı geliyor?
Scott

1
Evet, iyi bir nokta, benim hatam. Merkezleme, noktaları kaydırırmış gibi önemli olmayacaktır, ancak ölçek, ölçeklendirmeye değişmeyen temel bileşenleri hesaplamak için kullanılanla aynı olmalıdır.
F.Tusell

2
Henüz yapmadıysanız, factanal fonksiyonuna bakmak isteyebileceğinizi belirtmeyi unuttum. Temel bileşenler yerine faktör analizi yapar, ancak puanları doğrudan döndürür.
F.Tusell

2
-1. Bu cevabın doğru olmadığına inanıyorum ve bunu göstermek için kendi cevabımı gönderdim. Döndürülmüş yükler üzerinde dik çıkıntı ile döndürülmüş puanlar alınamaz (çünkü artık dik değildirler). Doğru skorları elde etmenin en basit yolu kullanmaktır psych::principal. [Bunun dışında, yukarıdaki yorumlarda tartışıldığı gibi ölçeklendirmeyi eklemek için cevabınızı düzenledim.]
amip diyor Reinstate Monica

1
Üzgünüm benim hatam. Demek olan . Şimdi düzelteceğim. Ve ... evet, şimdi ona baktığımda dik sütunları var, bu yüzden bize hala bir birim matris alacaktı, değil mi? Eğer öyleyse, orijinal posteri yanlış yönlendirmedim, ruhumdan bir yük kaldırdın! k × n V ( T T k V T k ) ( V k T k )Vkk×nV(TkTVkT)(VkTk)
F.Tusell

0

Ade4 kullanılarak yapılan PCA için çalışan bir çözüm arıyordum .

Lütfen aşağıdaki işlevi bulun:

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 tarihinde reprex paketi tarafından oluşturuldu (v0.3.0)

Umarım bu yardım!


Bir cevap için bu alanı kullanmanız gerekiyor.
Michael R. Chernick

Tamlık için bir cevap eklemenin geçerli olduğu bana benziyordu. Bu soru için olduğu gibi: stackoverflow.com/questions/6862742/draw-a-circle-with-ggplot2 . Gerekirse teklifimi taşımaktan memnuniyet duyarım.
Alain Danet

Yanlış anladım çünkü cevaplardan birinde bir hatayı düzeltiyor gibisin. Belirli bir yazılım paketi reklamı4 için bir ek olduğunu görüyorum. Çapraz Onaylı, kesinlikle kodla ilgili sorulara veya cevaplara bakmaz. Yığın Taşması, yazılım sorunlarının ele alındığı yerdir.
Michael R. Chernick
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.