Estoy comparando la salida de dos funciones en R para hacer Análisis de Componentes Principales (PCA), el FactoMineR::PCA()
y el base::svd()
utilizando el conjunto de datos incorporado en R mtcars
dado que la primera función es una envoltura de la segunda, por lo que deberían converger en los resultados básicos del $U$ si todo está bien, $\Sigma$ y $V$ ya que $X = U\cdot \Sigma \cdot V^{T}$
# PCA using FactoMineR::PCA()
library(FactoMineR)
res.pca <- FactoMineR::PCA(mtcars[, c(1:11)], ncp = 9, quali.sup = c(8, 9), graph = F) # variable 8 and 9 are supplementary not active in the construction of the PCs
# PCA using base::svd()
A <- as.matrix(mtcars[,c(1:7,10,11)], row = 9, byrow = T)
S <- scale(A)
svd.pca <- svd(S)
# comparison in terms of V (they match up after correction for signs)
round(res.pca$svd$V, 2) == round(svd.pca$v, 2) # Mixed TRUE/FALSE
svd.pca$v[, c(5, 7)] <- svd.pca$v[, c(5, 7)] * -1 # correct for signs in columns 5 and 7
round(res.pca$svd$V, 2) == round(svd.pca$v, 2) # TRUE
# comparison in terms of Sigma (they match up after correction for the divisor N-1
round(res.pca$svd$vs, 3) == round(svd.pca$d / (sqrt(nrow(S) - 1)), 3) # TRUE
# comparison in terms of U (they don't match up after correction for signs)
svd.pca$u[, c(5, 7)] <- svd.pca$u[, c(5, 7)] * -1 # correct for signs
svd.pca$vs <- svd.pca$d / (sqrt(nrow(S) - 1)) # to add $sdev to sdv() output and make it match up with FactoMineR $svd$vs
svd.pca$vr <- svd.pca$vs ^ 2 # to add Sigma (variance) to the sdv() output
round(res.pca$svd$U, 2) == round(svd.pca$u %*% diag(svd.pca$vr), 2) # Except for the first column everything else is FALSE, why?
R> head(res.pca$svd$U[, 1:5])
[,1] [,2] [,3] [,4] [,5]
[1,] -0.2838 0.826 -0.292 -0.249 -1.785
[2,] -0.2722 0.688 0.159 -0.169 -1.559
[3,] -0.9825 -0.230 -0.301 -0.214 0.181
[4,] -0.0920 -1.392 -0.471 -0.608 0.579
[5,] 0.6780 -0.584 -1.478 0.291 0.529
[6,] 0.0212 -1.723 0.160 -1.720 0.299
R> svd.pca$u %*% diag(svd.pca$vr)[, 1:5]
[,1] [,2] [,3] [,4] [,5]
[1,] -0.2837 0.3041 -0.02606 -0.01165 -0.05780
[2,] -0.2722 0.2532 0.01413 -0.00792 -0.05048
[3,] -0.9823 -0.0846 -0.02680 -0.01004 0.00586
[4,] -0.0920 -0.5123 -0.04202 -0.02848 0.01875
[5,] 0.6779 -0.2148 -0.13174 0.01363 0.01712
[6,] 0.0212 -0.6341 0.01426 -0.08059 0.00967
Como puedes ver, la primera columna coincide, pero otras columnas no. Entonces, ¿cuál sería la $U$ matriz en FactoMineR
representando de forma diferente a la del svd
? ¿Cómo hacer que coincidan utilizando R?
Aparte de los signos, parece que el $V$ es la misma para los dos outpus de la función, pero lo que hace la $U$ ¿diferente entonces entre ellos?
Note
la escala también es diferente entre las dos funciones y esta línea de abajo hará la corrección:
A <- as.matrix(mtcars[,c(1:7,10,11)], row = 9, byrow = T)
S.corr <- scale(A) / (sqrt((nrow(A) - 1)/ nrow(A))) # correct for scaling
# to get the scaled data from FactoMineR
df_restored <- res.pca$svd$U %*% diag(res.pca$svd$vs) %*% t(res.pca$svd$V)
Nota al margen código fuente de FactoMineR::PCA()
se puede acceder y ver por:
FactoMineR:::PCA