Я вважаю, те, що ви отримуєте у своєму запитанні, стосується обрізання даних за допомогою меншої кількості основних компонентів (ПК). Для таких операцій я вважаю, що функція prcomp
є більш наочною тим, що легше візуалізувати множення матриці, що використовується для реконструкції.
По-перше, дайте синтетичний набір даних, Xt
ви виконуєте PCA (як правило, ви б центрирували зразки, щоб описати зв'язки ПК з коваріаційною матрицею:
#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)
В результатах або prcomp
, ви можете побачити ПК ( res$x
), власні значення ( res$sdev
), що дають інформацію про величину кожного ПК та навантаження ( res$rotation
).
res$sdev
length(res$sdev)
res$rotation
dim(res$rotation)
res$x
dim(res$x)
Шматуючи власні значення, ви отримуєте дисперсію, пояснювану кожним ПК:
plot(cumsum(res$sdev^2/sum(res$sdev^2))) #cumulative explained variance
Нарешті, ви можете створити усічену версію своїх даних, використовуючи лише провідні (важливі) ПК:
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)
Ви можете бачити, що результат - це трохи плавніша матриця даних із відфільтрованими функціями невеликого масштабу:
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()
І ось дуже базовий підхід, який ви можете виконувати поза функцією 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
Тепер, вирішити, які ПК зберігати, - це окреме питання - те, що мене цікавило ще деякий час . Сподіваюся, що це допомагає.