Learn R Programming

robustbase (version 0.99-4-1)

classPC: Compute Classical Principal Components via SVD or Eigen

Description

Compute classical principal components (PC) via SVD (svd or eigenvalue decomposition (eigen) with non-trivial rank determination.

Usage

classPC(x, scale = FALSE, center = TRUE, signflip = TRUE,
        via.svd = n > p, scores = FALSE)

Value

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 \times k\) matrix.

scores

if the scores argument was true, the \(n \times 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.

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

Valentin Todorov; efficiency tweaks by Martin Maechler

See Also

In spirit very similar to R's standard prcomp and princomp, one of the main differences being how the rank is determined via a non-trivial tolerance.

Examples

Run this code
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 here
pc0 <- 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 case

cpc1 <- classPC(cbind(1:3)) # 1-D matrix
stopifnot(cpc1$rank == 1,
          all.equal(cpc1$eigenvalues, 1),
          all.equal(cpc1$loadings, 1))
# \dontshow{
stopifnot(classPC(x, center=FALSE)$rank == min(dim(x)))
ii <- names(pcx); ii <- ii[ii != "scores"]
stopifnot(all.equal(pcx[ii], pc2[ii], tol=0),
	  all.equal(pcx, pcS, tol=1e-8),
	  length(pc.x$center) == 10, identical(pc0$center, FALSE),
          all.equal(crossprod(pcx $loadings), diag(9)),
          all.equal(crossprod(pc.x$loadings), diag(10)),
          all.equal(colSums(abs(pcx$loadings)),
                    c(2.69035673, 2.78449399, 3.00148438,
                      2.9016688,  2.49400759, 2.90477204,
                      3.01639807, 2.4217181, 2.64665957)),
	  length(pc0$scale) == 12)
# }

Run the code above in your browser using DataLab