Creo que a lo que se refiere en su pregunta se refiere al truncamiento de datos utilizando un número menor de componentes principales (PC). Para tales operaciones, creo que la función prcomp
es más ilustrativa ya que es más fácil visualizar la multiplicación de matrices utilizada en la reconstrucción.
Primero, proporcione un conjunto de datos sintético, Xt
realice la PCA (normalmente centraría las muestras para describir las PC relacionadas con una matriz de covarianza:
#Generate data
m=50
n=100
frac.gaps <- 0.5 # the fraction of data with NaNs
N.S.ratio <- 0.25 # the Noise to Signal ratio for adding noise to data
x <- (seq(m)*2*pi)/m
t <- (seq(n)*2*pi)/n
#True field
Xt <-
outer(sin(x), sin(t)) +
outer(sin(2.1*x), sin(2.1*t)) +
outer(sin(3.1*x), sin(3.1*t)) +
outer(tanh(x), cos(t)) +
outer(tanh(2*x), cos(2.1*t)) +
outer(tanh(4*x), cos(0.1*t)) +
outer(tanh(2.4*x), cos(1.1*t)) +
tanh(outer(x, t, FUN="+")) +
tanh(outer(x, 2*t, FUN="+"))
Xt <- t(Xt)
#PCA
res <- prcomp(Xt, center = TRUE, scale = FALSE)
names(res)
En los resultados o prcomp
, puede ver las PC ( res$x
), los valores propios ( res$sdev
) que proporcionan información sobre la magnitud de cada PC y las cargas ( res$rotation
).
res$sdev
length(res$sdev)
res$rotation
dim(res$rotation)
res$x
dim(res$x)
Al cuadrar los valores propios, obtienes la varianza explicada por cada PC:
plot(cumsum(res$sdev^2/sum(res$sdev^2))) #cumulative explained variance
Finalmente, puede crear una versión truncada de sus datos utilizando solo las PC principales (importantes):
pc.use <- 3 # explains 93% of variance
trunc <- res$x[,1:pc.use] %*% t(res$rotation[,1:pc.use])
#and add the center (and re-scale) back to data
if(res$scale != FALSE){
trunc <- scale(trunc, center = FALSE , scale=1/res$scale)
}
if(res$center != FALSE){
trunc <- scale(trunc, center = -1 * res$center, scale=FALSE)
}
dim(trunc); dim(Xt)
Puede ver que el resultado es una matriz de datos ligeramente más uniforme, con características de pequeña escala filtradas:
RAN <- range(cbind(Xt, trunc))
BREAKS <- seq(RAN[1], RAN[2],,100)
COLS <- rainbow(length(BREAKS)-1)
par(mfcol=c(1,2), mar=c(1,1,2,1))
image(Xt, main="Original matrix", xlab="", ylab="", xaxt="n", yaxt="n", breaks=BREAKS, col=COLS)
box()
image(trunc, main="Truncated matrix (3 PCs)", xlab="", ylab="", xaxt="n", yaxt="n", breaks=BREAKS, col=COLS)
box()
Y aquí hay un enfoque muy básico que puede hacer fuera de la función prcomp:
#alternate approach
Xt.cen <- scale(Xt, center=TRUE, scale=FALSE)
C <- cov(Xt.cen, use="pair")
E <- svd(C)
A <- Xt.cen %*% E$u
#To remove units from principal components (A)
#function for the exponent of a matrix
"%^%" <- function(S, power)
with(eigen(S), vectors %*% (values^power * t(vectors)))
Asc <- A %*% (diag(E$d) %^% -0.5) # scaled principal components
#Relationship between eigenvalues from both approaches
plot(res$sdev^2, E$d) #PCA via a covariance matrix - the eigenvalues now hold variance, not stdev
abline(0,1) # same results
Ahora, decidir qué PC retener es una pregunta separada, una que me interesó hace un tiempo . Espero que ayude.