Mengapa fungsi R 'prompomp' dan 'prcomp' memberikan nilai eigen yang berbeda?


22

Anda dapat menggunakan dataset decathlon {FactoMineR} untuk mereproduksi ini. Pertanyaannya adalah mengapa nilai eigen yang dikomputasi berbeda dari nilai matriks kovarians.

Berikut adalah nilai-nilai eigen yang digunakan princomp:

> library(FactoMineR);data(decathlon)
> pr <- princomp(decathlon[1:10], cor=F)
> pr$sd^2
      Comp.1       Comp.2       Comp.3       Comp.4       Comp.5       Comp.6 
1.348073e+02 2.293556e+01 9.747263e+00 1.117215e+00 3.477705e-01 1.326819e-01 
      Comp.7       Comp.8       Comp.9      Comp.10 
6.208630e-02 4.938498e-02 2.504308e-02 4.908785e-03 

Dan hal yang sama menggunakan PCA:

> res<-PCA(decathlon[1:10], scale.unit=FALSE, ncp=5, graph = FALSE)
> res$eig
          eigenvalue percentage of variance cumulative percentage of variance
comp 1  1.348073e+02           79.659589641                          79.65959
comp 2  2.293556e+01           13.552956464                          93.21255
comp 3  9.747263e+00            5.759799777                          98.97235
comp 4  1.117215e+00            0.660178830                          99.63252
comp 5  3.477705e-01            0.205502637                          99.83803
comp 6  1.326819e-01            0.078403653                          99.91643
comp 7  6.208630e-02            0.036687700                          99.95312
comp 8  4.938498e-02            0.029182305                          99.98230
comp 9  2.504308e-02            0.014798320                          99.99710
comp 10 4.908785e-03            0.002900673                         100.00000

Bisakah Anda jelaskan kepada saya mengapa nilai eigen yang dihitung secara langsung berbeda dari nilai eigen? (vektor eigennya sama):

> eigen(cov(decathlon[1:10]))$values
 [1] 1.381775e+02 2.350895e+01 9.990945e+00 1.145146e+00 3.564647e-01
 [6] 1.359989e-01 6.363846e-02 5.061961e-02 2.566916e-02 5.031505e-03

Juga, prcompmetode alternatif memberikan nilai eigen yang sama dengan perhitungan langsung:

> prc <- prcomp(decathlon[1:10])
> prc$sd^2
 [1] 1.381775e+02 2.350895e+01 9.990945e+00 1.145146e+00 3.564647e-01
 [6] 1.359989e-01 6.363846e-02 5.061961e-02 2.566916e-02 5.031505e-03

Mengapa PCA/ princompdan prcompmemberikan nilai eigen yang berbeda?


PCA akan memberi Anda hasil yang berbeda tergantung pada apakah Anda menggunakan matriks kovarians atau matriks korelasi.
charles.y.zheng

7
Perbedaannya tampak relatif kecil, meskipun mungkin terlalu besar untuk menjadi masalah numerik sederhana. Mungkinkah perbedaan antara normalisasi dengan atau n - 1 , misalnya, ketika menghitung estimasi kovarians sebelum menghitung SVD atau dekomposisi nilai eigen? nn-1
kardinal

7
@ kardinal Tebakan bagus! Perhatikan bahwa dua urutan nilai eigen yang berbeda memiliki rasio berturut-turut yang identik. Jadi, satu set adalah kelipatan konstan dari yang lain. Kelipatannya adalah 1,025 = 41/40 ( tepat ). Tidak jelas bagi saya dari mana ini berasal. Mungkin dataset memiliki 41 elemen dan OP hanya mengungkapkan 10 elemen pertama?
whuber

7
@ cardinal Memang: Halaman Bantuan untuk princomp: "Perhatikan bahwa perhitungan default menggunakan pembagi N untuk matriks kovarians." Halaman bantuan untuk prcomp: "Tidak seperti princomp, varian dihitung dengan pembagi N-1 yang biasa."
caracal

2
@caracal, Anda harus menyalin komentar Anda ke dalam sebuah jawaban (dan mungkin membuatnya menjadi CW) sehingga dapat diterima dan pertanyaan itu dapat ditandai sebagai telah diselesaikan.
kardinal

Jawaban:


16

princompNprcompcovN-1N .

Ini disebutkan di bagian Detail dari help(princomp):

Perhatikan bahwa perhitungan default menggunakan pembagi 'N' untuk matriks kovarians.

dan Rincian bagian help(prcomp):

Tidak seperti princomp, varian dihitung dengan pembagi N - 1 yang biasa.

princompNn.obscv

else if (is.null(covmat)) {
    dn <- dim(z)
    if (dn[1L] < dn[2L]) 
        stop("'princomp' can only be used with more units than variables")
    covmat <- cov.wt(z)
    n.obs <- covmat$n.obs
    cv <- covmat$cov * (1 - 1/n.obs)
    cen <- covmat$center
}

Anda dapat menghindari perkalian ini dengan menentukan covmatargumen alih-alih xargumen.

princomp(covmat = cov(iris[,1:4]))$sd^2

Pembaruan terkait skor PCA:

cor = TRUEprincompprincompzN untuk penyebut.

princomp(scale(data))$scoresprincomp(data, cor = TRUE)$scores(N-1)/N


1
Anda dapat mempertimbangkan mengganti "tebak" dengan "sudah dikonfirmasi" (lihat aliran komentar di atas.) Anda mungkin juga mempertimbangkan untuk mengedit jawaban Anda untuk menjadikannya CW. Tepuk tangan.
kardinal

@ cardinal Saya tidak melihat komentar itu. Saya hanya melihat orang-orang yang telah terpilih. Terima kasih. Juga, bisakah Anda menjelaskan alasan di balik membuat jawaban CW? Apa aturan / pedoman untuk itu?
Joshua Ulrich

Adakah yang bisa menebak mengapa kode ini tidak hanya cv <- cov.wt(z, method="ML")membuat 2 garis follwing tidak perlu?
caracal

2
@ Yosua: Saran saya tentang membuat jawaban CW adalah karena fakta bahwa jawaban itu muncul melalui aliran komentar dan dihasilkan oleh diskusi "komunitas". Karena sudah dipecahkan dalam komentar, pikiran saya adalah bahwa paling masuk akal untuk merumuskannya kembali sebagai jawaban, ditandai sebagai CW untuk menunjukkan kolaborasi ini, dan ini memungkinkan jawaban diterima dan pertanyaan ditandai sebagai diselesaikan. (Kalau tidak, itu akan secara otomatis dihadang oleh perangkat lunak setelah waktu tertentu.)
kardinal

2
@amoeba akan sangat membantu untuk menyebutkan itu di komentar edit Anda. "Menambahkan 860 karakter ke tubuh" ke jawaban ~ 450 karakter tidak membantu siapa pun mengevaluasi apakah pengeditan itu masuk akal.
Joshua Ulrich
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.