Memvisualisasikan PCA dalam R: titik data, vektor eigen, proyeksi, elips kepercayaan

8

Saya memiliki dataset 17 orang, peringkat 77 pernyataan. Saya ingin mengekstraksi komponen-komponen utama pada matriks korelasi transposisi korelasi antara orang (sebagai variabel) di seluruh pernyataan (sebagai kasus). Aku tahu, itu aneh, itu disebut Q Metodologi .

Saya ingin menggambarkan bagaimana PCA bekerja dalam konteks ini, dengan mengekstraksi dan memvisualisasikan nilai eigen / vektor hanya untuk sepasang data. (Karena beberapa orang dalam disiplin saya mendapatkan PCA, apalagi itu aplikasi untuk Q, termasuk saya sendiri).

Saya ingin visualisasi dari tutorial yang fantastis ini , hanya untuk data nyata saya .

Visualisasi yang hebat

Jadikan ini bagian dari data saya:

Person1 <- c(-3,1,1,-3,0,-1,-1,0,-1,-1,3,4,5,-2,1,2,-2,-1,1,-2,1,-3,4,-6,1,-3,-4,3,3,-5,0,3,0,-3,1,-2,-1,0,-3,3,-4,-4,-7,-5,-2,-2,-1,1,1,2,0,0,2,-2,4,2,1,2,2,7,0,3,2,5,2,6,0,4,0,-2,-1,2,0,-1,-2,-4,-1)
Person2 <- c(-4,-3,4,-5,-1,-1,-2,2,1,0,3,2,3,-4,2,-1,2,-1,4,-2,6,-2,-1,-2,-1,-1,-3,5,2,-1,3,3,1,-3,1,3,-3,2,-2,4,-4,-6,-4,-7,0,-3,1,-2,0,2,-5,2,-2,-1,4,1,1,0,1,5,1,0,1,1,0,2,0,7,-2,3,-1,-2,-3,0,0,0,0)
df <- data.frame(cbind(Person1, Person2))
g <- ggplot(data = df, mapping = aes(x = Person1, y = Person2))
g <- g + geom_point(alpha = 1/3)  # alpha b/c of overplotting
g <- g + geom_smooth(method = "lm")  # just for comparison
g <- g + coord_fixed()  # otherwise, the angles of vectors are off
g

corrplot untuk data saya

Perhatikan bahwa, dengan pengukuran, data ini:

  • ... memiliki rata-rata nol,
  • ... sangat simetris,
  • ... dan sama-sama diskalakan pada kedua variabel (seharusnya tidak ada perbedaan antara matriks korelasi dan kovarians)

Sekarang, saya ingin menggabungkan kedua plot di atas .

corre <- cor(x = df$Person1, y = df$Person2, method = "spearman")  # calculate correlation, must be spearman b/c of measurement
matrix <- matrix(c(1, corre, corre, 1), nrow = 2)  # make this into a matrix
eigen <- eigen(matrix)  # calculate eigenvectors and values
eigen

memberi

> $values
> [1] 1.6 0.4
>
> $vectors
>     [,1]  [,2]
> [1,] 0.71 -0.71
> [2,] 0.71  0.71
>
> $vectors.scaled
>     [,1]  [,2]
> [1,]  0.9 -0.45
> [2,]  0.9  0.45

dan, pindah

g <- g + stat_ellipse(type = "norm")
  # add ellipse, though I am not sure which is the adequate type
  # as per https://github.com/hadley/ggplot2/blob/master/R/stat-ellipse.R
eigen$slopes[1] <- eigen$vectors[1,1]/eigen$vectors[2,1]  # calc slopes as ratios
eigen$slopes[2] <- eigen$vectors[1,1]/eigen$vectors[1,2]  # calc slopes as ratios
g <- g + geom_abline(intercept = 0, slope = eigen$slopes[1], colour = "green")  # plot pc1
g <- g + geom_abline(intercept = 0, slope = eigen$slopes[2], colour = "red")  # plot pc2
g <- g + geom_segment(x = 0, y = 0, xend = eigen$values[1], yend = eigen$slopes[1] * eigen$values[1], colour = "green", arrow = arrow(length = unit(0.2, "cm")))  # add arrow for pc1
g <- g + geom_segment(x = 0, y = 0, xend = eigen$values[2], yend = eigen$slopes[2] * eigen$values[2], colour = "red", arrow = arrow(length = unit(0.2, "cm")))  # add arrow for pc2
# Here come the perpendiculars, from StackExchange answer /programming/30398908/how-to-drop-a-perpendicular-line-from-each-point-in-a-scatterplot-to-an-eigenv ===
perp.segment.coord <- function(x0, y0, a=0,b=1){
#finds endpoint for a perpendicular segment from the point (x0,y0) to the line
# defined by lm.mod as y=a+b*x
  x1 <- (x0+b*y0-a*b)/(1+b^2)
  y1 <- a + b*x1
  list(x0=x0, y0=y0, x1=x1, y1=y1)
}
ss <- perp.segment.coord(df$Person1, df$Person2, 0, eigen$slopes[1])
g <- g + geom_segment(data=as.data.frame(ss), aes(x = x0, y = y0, xend = x1, yend = y1), colour = "green", linetype = "dotted")
g

Plot terakhir

Apakah plot ini cukup menggambarkan ekstraksi eigen / nilai eigen di PCA?

  • Saya tidak yakin akan menjadi elips dan / atau panjang vektor yang memadai (atau tidak masalah?)
  • Saya menduga, bahwa vektor memiliki kemiringan 1, -1adalah karena data saya (peringkat? Simetri?), Dan akan berbeda untuk data lain.

Ps .: ini didasarkan pada tutorial di atas dan pertanyaan CrossValidated ini .

Pps .: garis tegak lurus yang dijatuhkan pada vektor adalah singkat dari jawaban StackExchange ini

maksimum
sumber
3
Jangan skala vektor eigen Anda; lalu gambar ulang plotnya. Saya pikir Anda akan segera melihat di mana Anda melakukan kesalahan.
whuber
terima kasih @whuber, perbaiki. Saya perlu mengambil rasio dari dua vektor Eigen. Apakah sekarang terlihat lebih baik? Ada saran lain? (Saya menduga bahwa lereng tepat -1, 1 adalah karena data aneh saya).
maksimal
3
Ketika hanya ada dua variabel, vektor eigen standar selalu , yang - seperti teori katakan - adalah ortogonal. Kesalahan Anda adalah bahwa Anda salah menskala: Anda harus menskala kolom daripada baris. (1/2,±1/2)
Whuber
@amoeba setuju, jawabannya 95%. Bisakah Anda mengomentari dua peluru terakhir yang diangkat dalam pertanyaan? 1) Apakah elips benar dan 2) adalah 1, -1kemiringan yang diharapkan?
maksimal

Jawaban:

2

Tidak banyak yang bisa dijawab di sini. Anda tampaknya memiliki beberapa masalah dengan skrip Anda yang sekarang sudah diperbaiki. Saat ini tidak ada yang salah dengan visualisasi Anda dan sebenarnya saya merasa ilustrasi yang sangat bagus dan memadai.

Untuk menjawab pertanyaan Anda yang tersisa:

  1. Kemiringan sumbu utama Anda akan selalu menjadi dan untuk dataset dua dimensi standar (yaitu jika Anda bekerja dengan matriks korelasi), seperti yang dikatakan @whuber dalam komentar. Lihat jawaban saya di sini: Apakah matriks korelasi dua variabel selalu memiliki vektor eigen yang sama?11

  2. Elips yang diplot (menurut pemahaman saya tentang kode sumber stat_ellipse()) adalah elips cakupan 95% dengan asumsi distribusi normal multivarian. Ini pilihan yang masuk akal. Perhatikan bahwa jika Anda menginginkan cakupan yang berbeda, Anda dapat mengubahnya melalui levelparameter input, tetapi 95% cukup standar dan oke.

amuba
sumber