Compute Classical Principal Components via SVD or Eigen
Compute Classical Principal Components via SVD or Eigen
Compute classical principal components (PC) via SVD (svd
or eigenvalue decomposition (eigen) with non-trivial rank determination.
classPC(x, scale =FALSE, center =TRUE, signflip =TRUE, via.svd = n > p, scores =FALSE)
Arguments
x: a numeric matrix.
scale: logical indicating if the matrix should be scaled; it is mean centered in any case (via scale(*, scale=scale)c
center: logical or numeric vector for centering the matrix.
signflip: logical indicating if the sign(.) of the loadings should be determined should flipped such that the absolutely largest value is always positive.
via.svd: logical indicating if the computation is via SVD or Eigen decomposition; the latter makes sense typically only for n <= p.
scores: logical indicating
Author(s)
Valentin Todorov; efficiency tweaks by Martin Maechler
Returns
a list with components - rank: the (numerical) matrix rank of x; an integer number, say k, from 0:min(dim(x)). In the n>p case, it is rankMM(x).
eigenvalues: the k eigenvalues, in the n>p case, proportional to the variances.
loadings: the loadings, a p∗k matrix.
scores: if the scores argument was true, the n∗k matrix of scores, where k is the rank above.
center: a numeric p-vector of means, unless the center argument was false.
scale: if the scale argument was not false, the scale used, a p-vector.
See Also
In spirit very similar to 's standard prcomp and princomp, one of the main differences being how the rank is determined via a non-trivial tolerance.
Examples
set.seed(17)x <- matrix(rnorm(120),10,12)# n < p {the unusual case}pcx <- classPC(x)(k <- pcx$rank)# = 9 [after centering!]pc2 <- classPC(x, scores=TRUE)pcS <- classPC(x, via.svd=TRUE)all.equal(pcx, pcS, tol =1e-8)## TRUE: eigen() & svd() based PC are close herepc0 <- classPC(x, center=FALSE, scale=TRUE)pc0$rank # = 10 here *no* centering (as E[.] = 0)## Loadings are orthnormal:zapsmall( crossprod( pcx$loadings ))## PC Scores are roughly orthogonal:S.S <- crossprod(pc2$scores)print.table(signif(zapsmall(S.S),3), zero.print=".")stopifnot(all.equal(pcx$eigenvalues, diag(S.S)/k))## the usual n > p case :pc.x <- classPC(t(x))pc.x$rank # = 10, full rank in the n > p casecpc1 <- classPC(cbind(1:3))# 1-D matrixstopifnot(cpc1$rank ==1, all.equal(cpc1$eigenvalues,1), all.equal(cpc1$loadings,1))