R'de PCA biplotunda temel değişkenlerin okları


11

Soruyu yazılıma özgü hale getirme riski altındadır ve her yerde ve kendine özgü ifadelerinin mazereti ile, biplot()R'deki fonksiyon hakkında ve daha spesifik olarak, varsayılan, üst üste binmiş kırmızı okların hesaplanması ve çizilmesi hakkında sormak istiyorum. temeldeki değişkenlere.


[Yorumlardan bazılarını anlamak için, başlangıçta gönderilen arazilerin az ilgi duyduğu bir sclaing sorunu vardı ve şimdi siliniyorlar.]


Yeşil oklarınızı nasıl bulduğunuzu anlayamıyorum. Doğru değiller. Uzunluğun yeşil olması yaklaşık. s.width green'den iki kat daha uzun, standartlaştırılmamış değişkenlerle ilgili vektörleri çizdiğinizden şüphelenmenizi sağlar. Bu korelasyonlara dayalı bir PCA biplotunda gerçekleşemez.
ttnphns

Kırmızı oklar doğru görünüyor. Bkz: aynı uzunluktadırlar ve PC2 hakkında simetriktirler. Sadece 2 değişkenli ve korelasyonlara (yani standartlaştırılmış değişkenler) dayalı PCA yaptığınızda mümkün olan tek pozisyon budur. Korelasyonlara dayalı PCA'da yükler (okların koordineli) PC'ler ve değişkenler arasındaki korelasyonlardır. Örnekte, yüklemeleri (PC'ler tarafından vars) şunlardır: .74752, .66424; -.74752, .66424.
ttnphns

@ttnphns Evet, kırmızı oklar çoğaltmaya çalıştığım şeydir (doğrudur) ve biplot(name_of_the_PCA)bu durumda R ile çağrılırlar biplot(PCA). Verileri ortaladım ve ölçeklendirdim.
Antoni Parellada

Sorunuz ne? Kırmızı okların koordinatlarını nasıl hesaplayabilirim? Bunlar PCA yüklemeleri olmalıdır . Bazen, özvektörler çizilir (R komutunuz muhtemelen bunu yaptı ??), ancak, rıza gösteren, anlamlı yol , yüklemeleri çizmektir .
ttnphns

@ttnphns Özvektörleri çizmek (yüklemelerle aynı olduğunu varsayıyorum) bana doğru yönelimi veriyor (teşekkür ederim), ancak kırmızı oklarla aynı büyüklükte değil (görüntüyü OP'ye yapıştırıyorum).
Antoni Parellada

Yanıtlar:


19

Upvoting düşünün @ amip en ve @ttnphns' sonrası . Yardımlarınız ve fikirleriniz için teşekkür ederiz.


Aşağıdaki dayanır R İris veri kümesi , ve spesifik olarak, ilk üç değişken (sütun): Sepal.Length, Sepal.Width, Petal.Length.

Bir biplot , bir yükleme grafiğini (standartlaştırılmamış özvektörler) - betonda, ilk iki yüklemeyi ve bir skor grafiğini (ana bileşenlere göre çizilen döndürülmüş ve dilate veri noktaları) birleştirir. Aynı veri kümesini kullanarak, @amoeba , birinci ve ikinci temel bileşenlerin skor grafiğinin 3 olası normalizasyonuna ve başlangıç ​​değişkenlerinin yükleme grafiğinin (oklar) 3 normalizasyonuna dayanan 9 olası PCA biplot kombinasyonunu açıklar . R'nin bu olası kombinasyonları nasıl ele aldığını görmek için biplot()yönteme bakmak ilginçtir :


İlk önce kopyalamaya ve yapıştırmaya hazır lineer cebir:

X = as.matrix(iris[,1:3])             # Three first variables of Iris dataset
CEN = scale(X, center = T, scale = T) # Centering and scaling the data
PCA = prcomp(CEN)

# EIGENVECTORS:
(evecs.ei = eigen(cor(CEN))$vectors)       # Using eigen() method
(evecs.svd = svd(CEN)$v)                   # PCA with SVD...
(evecs = prcomp(CEN)$rotation)             # Confirming with prcomp()

# EIGENVALUES:
(evals.ei = eigen(cor(CEN))$values)        # Using the eigen() method
(evals.svd = svd(CEN)$d^2/(nrow(X) - 1))   # and SVD: sing.values^2/n - 1
(evals = prcomp(CEN)$sdev^2)               # with prcomp() (needs squaring)

# SCORES:
scr.svd = svd(CEN)$u %*% diag(svd(CEN)$d)  # with SVD
scr = prcomp(CEN)$x                        # with prcomp()
scr.mm = CEN %*% prcomp(CEN)$rotation      # "Manually" [data] [eigvecs]

# LOADINGS:

loaded = evecs %*% diag(prcomp(CEN)$sdev)  # [E-vectors] [sqrt(E-values)]

1. Yükleme grafiğinin (oklar) çoğaltılması:

VSepal L.ha1a2VPC1PC2


resim açıklamasını buraya girin


Sepal L.PC1

a1=hcos(ϕ)

PC1S1

S1=1nscores12=1VS1

a1=VS1=VS1cos(ϕ)(1)=h×1×cos(ϕ)

Yana ,V=x2

Var(V)=x2n1=Vn1V=h=var(V)n1.

Aynı şekilde,

S1=1=var(S1)n1.

Eq. ,(1)

a1=h×1×cos(ϕ)=var(V)var(S1)cos(θ)(n1)

cos(ϕ) bu nedenle, faktörünün kırışıklığını anlamadığım uyarıyla , Pearson'un korelasyon katsayısı , olarak düşünülebilir .rn1

Kırmızı okları çoğaltma ve üst üste bindirme biplot()

par(mfrow = c(1,2)); par(mar=c(1.2,1.2,1.2,1.2))

biplot(PCA, cex = 0.6, cex.axis = .6, ann = F, tck=-0.01) # R biplot
# R biplot with overlapping (reproduced) arrows in blue completely covering red arrows:
biplot(PCA, cex = 0.6, cex.axis = .6, ann = F, tck=-0.01) 
arrows(0, 0,
       cor(X[,1], scr[,1]) * 0.8 * sqrt(nrow(X) - 1), 
       cor(X[,1], scr[,2]) * 0.8 * sqrt(nrow(X) - 1), 
       lwd = 1, angle = 30, length = 0.1, col = 4)
arrows(0, 0,
       cor(X[,2], scr[,1]) * 0.8 * sqrt(nrow(X) - 1), 
       cor(X[,2], scr[,2]) * 0.8 * sqrt(nrow(X) - 1), 
       lwd = 1, angle = 30, length = 0.1, col = 4)
arrows(0, 0,
       cor(X[,3], scr[,1]) * 0.8 * sqrt(nrow(X) - 1), 
       cor(X[,3], scr[,2]) * 0.8 * sqrt(nrow(X) - 1), 
       lwd = 1, angle = 30, length = 0.1, col = 4)

resim açıklamasını buraya girin

İlgi noktaları:

  • Oklar, orijinal değişkenlerin ilk iki temel bileşen tarafından üretilen puanlarla korelasyonu olarak çoğaltılabilir.
  • Alternatif olarak bu, @ amoeba'nın gönderisinde etiketli ikinci satırdaki ilk grafikte olduğu gibi gerçekleştirilebilir :VS

resim açıklamasını buraya girin

veya R kodunda:

    biplot(PCA, cex = 0.6, cex.axis = .6, ann = F, tck=-0.01) # R biplot
    # R biplot with overlapping arrows in blue completely covering red arrows:
    biplot(PCA, cex = 0.6, cex.axis = .6, ann = F, tck=-0.01) 
    arrows(0, 0,
       (svd(CEN)$v %*% diag(svd(CEN)$d))[1,1] * 0.8, 
       (svd(CEN)$v %*% diag(svd(CEN)$d))[1,2] * 0.8, 
       lwd = 1, angle = 30, length = 0.1, col = 4)
    arrows(0, 0,
       (svd(CEN)$v %*% diag(svd(CEN)$d))[2,1] * 0.8, 
       (svd(CEN)$v %*% diag(svd(CEN)$d))[2,2] * 0.8, 
       lwd = 1, angle = 30, length = 0.1, col = 4)
    arrows(0, 0,
       (svd(CEN)$v %*% diag(svd(CEN)$d))[3,1] * 0.8, 
       (svd(CEN)$v %*% diag(svd(CEN)$d))[3,2] * 0.8, 
       lwd = 1, angle = 30, length = 0.1, col = 4)

hatta henüz ...

    biplot(PCA, cex = 0.6, cex.axis = .6, ann = F, tck=-0.01) # R biplot
    # R biplot with overlapping (reproduced) arrows in blue completely covering red arrows:
    biplot(PCA, cex = 0.6, cex.axis = .6, ann = F, tck=-0.01) 
    arrows(0, 0,
       (loaded)[1,1] * 0.8 * sqrt(nrow(X) - 1), 
       (loaded)[1,2] * 0.8 * sqrt(nrow(X) - 1), 
       lwd = 1, angle = 30, length = 0.1, col = 4)
    arrows(0, 0,
       (loaded)[2,1] * 0.8 * sqrt(nrow(X) - 1), 
       (loaded)[2,2] * 0.8 * sqrt(nrow(X) - 1), 
       lwd = 1, angle = 30, length = 0.1, col = 4)
    arrows(0, 0,
       (loaded)[3,1] * 0.8 * sqrt(nrow(X) - 1), 
       (loaded)[3,2] * 0.8 * sqrt(nrow(X) - 1), 
       lwd = 1, angle = 30, length = 0.1, col = 4)

bağlantı @ttnphns ile yükleri geometrik açıklama veya @ttnphns ile de bu diğer bilgi yazı .

  • Bir ölçeklendirme faktörü var: sqrt(nrow(X) - 1)bu biraz gizemini koruyor.

  • 0.8 , etiket için alan oluşturmakla ilgilidir - bu yoruma buradan bakın :

Ayrıca, okların metin etiketinin merkezi olması gereken yerde olacak şekilde çizildiğini söylemek gerekir! Daha sonra, çizilmeden önce oklar 0.80.8 ile çarpılır, yani tüm oklar, muhtemelen metin etiketi ile çakışmayı önlemek için olması gerekenden daha kısadır (biplot.default koduna bakın). Bunun son derece kafa karıştırıcı olduğunu düşünüyorum. - 19 Mart'ta amip 10:06


2. biplot()Skor grafiğinin çizilmesi (ve oklar aynı anda):

Eksen tekabül eden, kareler birim toplamına ölçeklenir birinci bölgeden ilk satırın @ amip yayınının matris çizilmesi çoğaltılabilir, "- SVD ayrışma (bu konuda daha sonra) Sütunlarını : bunlar, birim kareler toplamına ölçeklendirilmiş temel bileşenler. "UU

resim açıklamasını buraya girin

Biplot yapısında alt ve üst yatay eksenlerde iki farklı ölçek vardır:

resim açıklamasını buraya girin

Bununla birlikte, göreceli ölçek hemen belli değildir, işlevlerin ve yöntemlerin incelenmesini gerektirir:

biplot() dikey birim vektörler olan sütunları olarak grafikleri :U

> scr.svd = svd(CEN)$u %*% diag(svd(CEN)$d) 
> U = svd(CEN)$u
> apply(U, 2, function(x) sum(x^2))
[1] 1 1 1

Oysa prcomp()R işlevi, özdeğerler ölçeklenmiş puanları verir:

> apply(scr, 2, function(x) var(x))         # pr.comp() scores scaled to evals
       PC1        PC2        PC3 
2.02142986 0.90743458 0.07113557 
> evals                                     #... here is the proof:
[1] 2.02142986 0.90743458 0.07113557

Bu nedenle özdeğerlere bölerek varyansı ölçeklendirebiliriz :1

> scr_var_one = scr/sqrt(evals)[col(scr)]  # to scale to var = 1
> apply(scr_var_one, 2, function(x) var(x)) # proved!
[1] 1 1 1

Ancak karelerin toplamının olmasını istediğimiz için gerekecek çünkü:1n1

var(scr_var_one)=1=1nscr_var_onen1
> scr_sum_sqrs_one = scr_var_one / sqrt(nrow(scr) - 1) # We / by sqrt n - 1.
> apply(scr_sum_sqrs_one, 2, function(x) sum(x^2))     #... proving it...
PC1 PC2 PC3 
  1   1   1

Not olarak, ölçeklendirme faktörünün kullanımı daha sonra değiştirilirken , açıklama tanımlanırkenn1nlan

prcomp kullanır : "princomp'den farklı olarak varyanslar normal bölücü ile hesaplanır ".n1n1


Onları tüm ififadelerden ve diğer temizlikçi tüylerden arındırdıktan sonra, biplot()aşağıdaki gibi ilerler:

X   = as.matrix(iris[,1:3])                    # The original dataset
CEN = scale(X, center = T, scale = T)          # Centered and scaled
PCA = prcomp(CEN)                              # PCA analysis

par(mfrow = c(1,2))                            # Splitting the plot in 2.
biplot(PCA)                                    # In-built biplot() R func.

# Following getAnywhere(biplot.prcomp):

choices = 1:2                                  # Selecting first two PC's
scale = 1                                      # Default
scores= PCA$x                                  # The scores
lam = PCA$sdev[choices]                        # Sqrt e-vals (lambda) 2 PC's
n = nrow(scores)                               # no. rows scores
lam = lam * sqrt(n)                            # See below.

# at this point the following is called...
# biplot.default(t(t(scores[,choices])      /  lam), 
#                t(t(x$rotation[,choices]) *   lam))

# Following from now on getAnywhere(biplot.default):

x = t(t(scores[,choices])       / lam)         # scaled scores
# "Scores that you get out of prcomp are scaled to have variance equal to      
#  the eigenvalue. So dividing by the sq root of the eigenvalue (lam in 
#  biplot) will scale them to unit variance. But if you want unit sum of 
#  squares, instead of unit variance, you need to scale by sqrt(n)" (see comments).
# > colSums(x^2)
# PC1       PC2 
# 0.9933333 0.9933333    # It turns out that the it's scaled to sqrt(n/(n-1)), 
# ...rather than 1 (?) - 0.9933333=149/150

y = t(t(PCA$rotation[,choices]) * lam)         # scaled eigenvecs (loadings)


n = nrow(x)                                    # Same as dataset (150)
p = nrow(y)                                    # Three var -> 3 rows

# Names for the plotting:

xlabs = 1L:n
xlabs = as.character(xlabs)                    # no. from 1 to 150 
dimnames(x) = list(xlabs, dimnames(x)[[2L]])   # no's and PC1 / PC2

ylabs = dimnames(y)[[1L]]                      # Iris species
ylabs = as.character(ylabs)
dimnames(y) <- list(ylabs, dimnames(y)[[2L]])  # Species and PC1/PC2

# Function to get the range:
unsigned.range = function(x) c(-abs(min(x, na.rm = TRUE)), 
                                abs(max(x, na.rm = TRUE)))
rangx1 = unsigned.range(x[, 1L])               # Range first col x
# -0.1418269  0.1731236
rangx2 = unsigned.range(x[, 2L])               # Range second col x
# -0.2330564  0.2255037
rangy1 = unsigned.range(y[, 1L])               # Range 1st scaled evec
# -6.288626   11.986589
rangy2 = unsigned.range(y[, 2L])               # Range 2nd scaled evec
# -10.4776155   0.8761695

(xlim = ylim = rangx1 = rangx2 = range(rangx1, rangx2))
# range(rangx1, rangx2) = -0.2330564  0.2255037

# And the critical value is the maximum of the ratios of ranges of 
# scaled e-vectors / scaled scores:

(ratio = max(rangy1/rangx1, rangy2/rangx2)) 
# rangy1/rangx1   =   26.98328    53.15472
# rangy2/rangx2   =   44.957418   3.885388
# ratio           =   53.15472

par(pty = "s")                                 # Calling a square plot

# Plotting a box with x and y limits -0.2330564  0.2255037
# for the scaled scores:

plot(x, type = "n", xlim = xlim, ylim = ylim)  # No points
# Filling in the points as no's and the PC1 and PC2 labels:
text(x, xlabs) 
par(new = TRUE)                                # Avoids plotting what follows separately

# Setting now x and y limits for the arrows:

(xlim = xlim * ratio)  # We multiply the original limits x ratio
# -16.13617  15.61324
(ylim = ylim * ratio)  # ... for both the x and y axis
# -16.13617  15.61324

# The following doesn't change the plot intially...
plot(y, axes = FALSE, type = "n", 
     xlim = xlim, 
     ylim = ylim, xlab = "", ylab = "")

# ... but it does now by plotting the ticks and new limits...
# ... along the top margin (3) and the right margin (4)
axis(3); axis(4)
text(y, labels = ylabs, col = 2)  # This just prints the species

arrow.len = 0.1                   # Length of the arrows about to plot.

# The scaled e-vecs are further reduced to 80% of their value
arrows(0, 0, y[, 1L] * 0.8, y[, 2L] * 0.8, 
       length = arrow.len, col = 2)

beklendiği biplot()gibi biplot(PCA), dokunulmamış tüm estetik eksikliklerinde çıktıyı doğrudan (aşağıda soldaki çizim) ile çağrıldığı şekilde ( aşağıda sağdaki görüntü) üretir :

resim açıklamasını buraya girin

İlgi noktaları:

  • Oklar, iki ana bileşenin her birinin ölçeklendirilmiş özvektörü ile bunlara ilişkin ölçeklendirilmiş puanlar ( ratio) arasındaki maksimum oranla ilişkili bir ölçekte çizilir . AS @amoeba yorumlar:

dağılım grafiği ve "ok grafiği", okların en büyük (mutlak değer) x veya y ok koordinatı, dağınık veri noktalarının en büyük (mutlak değer) x veya y koordinatına tam olarak eşit olacak şekilde ölçeklendirilir

  • Yukarıda tahmin edildiği gibi, noktalar doğrudan SVD'nin matrisindeki puanlar olarak çizilebilir :U


1
+1, İyi çalışma. RSorunuza etiket ekledim çünkü kafa karıştırıcı madde (ölçeklendirme katsayısı) kısmen R'ye özgü olduğunu kanıtladı. Genel olarak, PCA biplotunun bileşen puanlarının (satır koordinatları) ve bileşen yönü katsayılarının (sütun koordinatları) bir bindirme dağılım grafiği olduğunu görebiliyordunuz ve her birine "atalet" (varyans) ile çeşitli standartlar uygulanabileceğinden biplotun çeşitli görünümleri ortaya çıkabilir. Eklemek için: en tipik olarak (daha anlamlı), yüklemeler sütun koordinatları (oklar) olarak görüntülenir.
ttnphns

1
(devam) Güzel cevabınızda neyi gösterdiğinizi açıklayan biplot genel bakışımı görün .
ttnphns

2
+ 1 öğretici yazdığınız için ve bizim için tekrarlanabilir kod ile teşekkürler!
Haitao Du

Antony, resmini çizdin mi (elle olduğu gibi) ya da resmini çizdin (verilerle beslendi)? Hangi yazılımı kullandınız? Güzel görünüyor.
ttnphns

@ttnphns Teşekkürler! İşte bağlantı . Onu geliştirip geliştiremeyeceğinizi ve yükleri ve PC'leri daha iyi, daha didaktik bir şekilde çizip çizemeyeceğinizi merak ediyordum. Değiştirmekten çekinmeyin (harika bir kullanıcı dostu programdır) ve eğer yaparsanız, lütfen paylaşın.
Antoni Parellada
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.