Perché le funzioni R 'princomp' e 'prcomp' danno autovalori diversi?


22

È possibile utilizzare il set di dati del decathlon {FactoMineR} per riprodurre questo. La domanda è perché gli autovalori calcolati differiscono da quelli della matrice di covarianza.

Ecco gli autovalori usando 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 

E lo stesso usando 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

Puoi spiegarmi perché gli autovalori calcolati direttamente differiscono da quelli? (gli autovettori sono gli stessi):

> 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

Inoltre, il prcompmetodo alternativo fornisce gli stessi autovalori del calcolo diretto:

> 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

Perché PCA/ princompe prcompdare autovalori diversi?


PCA ti darà risultati diversi a seconda che tu usi la matrice di covarianza o la matrice di correlazione.
charles.y.zheng,

7
Le differenze sembrano relativamente piccole, sebbene probabilmente troppo grandi per essere semplici problemi numerici. Potrebbe essere la differenza tra la normalizzazione di o , ad esempio, quando si calcola una stima della covarianza prima di calcolare la decomposizione di SVD o autovalori? n - 1nn-1
cardinale il

7
@cardinal Nice indovina! Si noti che le due diverse sequenze di autovalori hanno rapporti consecutivi identici. Pertanto, un set è un multiplo costante dell'altro. Il multiplo è 1.025 = 41/40 ( esattamente ). Non mi è chiaro da dove provenga. Forse il set di dati ha 41 elementi e l'OP sta rivelando solo i primi 10?
whuber

7
@cardinal Indeed: Pagina di aiuto per princomp: "Si noti che il calcolo predefinito utilizza il divisore N per la matrice di covarianza." Pagina di aiuto per prcomp: "A differenza di princomp, le variazioni sono calcolate con il solito divisore N-1."
Caracal,

2
@caracal, dovresti copiare il tuo commento in una risposta (e magari renderlo in CW) in modo che possa essere accettato e la domanda possa essere contrassegnata come risolta.
cardinale

Risposte:


16

Come fuori punte nei commenti, è perché princompusi per il divisore, ma e il calcolo diretto utilizzando sia l'uso , invece di .N - 1 NNprcompcovN-1N

Questo è menzionato sia nella sezione Dettagli di help(princomp):

Si noti che il calcolo predefinito utilizza il divisore 'N' per la matrice di covarianza.

e la sezione Dettagli di help(prcomp):

Diversamente princomp, le variazioni sono calcolate con il solito divisore N - 1.

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
}

È possibile evitare questa moltiplicazione specificando l' covmatargomento anziché l' xargomento.

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

Aggiornamento relativo ai punteggi PCA:

cor = TRUEprincompprincompzN

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


1
Potresti considerare di sostituire "indovinato" con "già confermato" (vedi il flusso di commenti sopra.) Potresti anche considerare di modificare la tua risposta per renderla CW. Saluti.
cardinale

@cardinal Non ho visto quei commenti. Ho visto solo quelli che erano stati votati. Grazie. Inoltre, potresti spiegare la logica alla base della risposta CW? Quali sono le regole / linee guida per questo?
Joshua Ulrich,

Qualcuno può indovinare perché il codice non sta semplicemente cv <- cov.wt(z, method="ML")rendendo superflue le 2 righe che seguono?
Caracal,

2
@Joshua: Il mio suggerimento riguardo alla risposta in CW era dovuto al fatto che la risposta appariva attraverso un flusso di commenti ed era generata da una discussione "comunitaria". Poiché è stato risolto nei commenti, ritengo che abbia più senso riformularla come risposta, contrassegnata come CW per indicare questa collaborazione, e ciò consente di accettare la risposta e di contrassegnare la domanda come risolta. (Altrimenti, verrà automaticamente ripristinato dal software dopo un certo periodo di tempo.)
cardinale

2
@amoeba sarebbe stato utile menzionarlo nel tuo commento di modifica. "Aggiunto 860 caratteri al corpo" a una risposta di ~ 450 caratteri non aiuta nessuno a valutare se la modifica sia ragionevole.
Joshua Ulrich,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.