An R package for Generalized Principal Component Analysis (GPCA) and related matrix decompositions when data is observed in non-Euclidean inner-product spaces.
Standard PCA assumes all observations and variables are equally important and that Euclidean distance is the appropriate similarity measure. However, many real-world datasets violate these assumptions:
GPCA extends standard PCA by incorporating row and column metrics (M and A) that encode prior knowledge about data structure, following the framework of Allen, Grosenick & Taylor (2014). The package also implements generalized PLS methods building on ideas from Beaton et al. (2016).
genpca):
Decomposition with row metric M and column metric Agenpca_cov):
Direct analysis of pre-computed covariance matriceseigen: Direct eigendecomposition for small-to-medium
problemsspectra: Iterative partial SVD of the metric-whitened
data (via eigencore) for large problemsrandomized: Block-sketch approximation for wide
low-rank settingsdeflation: Sequential extraction for memory-constrained
scenariosgenpls/genplsc): Two-block analysis with
metricsgplssvd_op): Efficient PLS without materializing whitened
matricesrepair_metric(),
constraints_remedy)sfpca): Rank-1
components with sparsity and spatial smoothness penalties,
e.g. sfpca(X, K = 2, spat_cds = coords). See
?sfpca.rpls): Single-metric
penalized PLS (Allen et al. 2013) with "l1" or
"ridge" penalties,
e.g. rpls(X, Y, K = 3, lambda = 0.1, penalty = "l1"). See
?rpls.mnpca_mrl):
Low-rank factorization with sparse row/column precision matrices under
matrix-normal noise,
e.g. mnpca_mrl(Y, ncomp = 3, lambda_row = 0.05, lambda_col = 0.05).
See ?mnpca_mrl.gpca_mle):
Experimental alternation of GPCA with maximum-likelihood estimation of
the row/column metrics themselves,
e.g. gpca_mle(X, ncomp = 2). See
?gpca_mle.multivarious package
ecosystemMatrix packageThe default backend is method = "eigen".
"auto" is opt-in: pass it explicitly to let a heuristic
pick among "eigen", "spectra", and
"randomized" based on problem shape and constraint
structure.
| Method | Best for | Pros | Cons |
|---|---|---|---|
eigen |
Small/medium problems, exact reference runs | Most stable reference behavior | Builds larger intermediate matrices; for very large sparse
constraints may rely on truncated eigensolve (maxeig) and
become slower/approximate |
spectra |
Large problems with few components | Iterative partial SVD of the whitened operator (eigencore); lower memory | Both metrics are factored once (Cholesky or sparse Cholesky); a large dense general metric costs one factorization |
randomized |
Wide (p >> n), sparse-metric, low-rank
workloads |
Often fastest in wide settings; block GEMM/SpMM path | Approximate by design; tune oversample,
n_power, n_polish |
deflation |
Few components with limited memory | Low memory, component-by-component extraction | Can converge slowly; C++ path currently expects sparse metrics |
auto |
Default production usage | Chooses among
eigen/spectra/randomized
heuristically |
Heuristics may not be optimal for every hardware/data regime |
# install.packages("devtools")
devtools::install_github("bbuchsbaum/genpca")You’ll also want these runtime dependencies installed:
install.packages(c("Matrix", "eigencore", "multivarious"))
# Optional for some utilities / tests
install.packages(c("irlba", "knitr", "rmarkdown"))library(genpca)
set.seed(1)
X <- matrix(rnorm(200 * 50), 200, 50)
# Standard PCA (identity metrics by default)
fit <- genpca(X, ncomp = 5, preproc = multivarious::center())
fit$sdev # generalized singular values;
# with identity metrics this is
# prcomp(X)$sdev * sqrt(nrow(X) - 1)
head(multivarious::scores(fit)) # scores (n × k)
head(multivarious::components(fit)) # loadings (p × k)# Example: Survey data with population weights
library(Matrix)
pop_weights <- runif(nrow(X), 0.5, 1.5) # population sizes
M <- Diagonal(nrow(X), x = pop_weights) # row metric
# Variable importance weights
var_importance <- c(rep(2, 10), rep(1, 30), rep(0.5, 10))
A <- Diagonal(ncol(X), x = var_importance) # column metric
fit_weighted <- genpca(X, M = M, A = A, ncomp = 5,
preproc = multivarious::center())# When you have pre-computed covariance C = X'MX. fit_weighted above used
# preproc = multivarious::center(), so C must be built from centered X for
# the two fits to agree exactly.
Xc <- scale(X, center = TRUE, scale = FALSE)
C <- crossprod(Xc, M %*% Xc)
fit_cov <- genpca_cov(C, R = A, ncomp = 5, method = "gmd")
# Mathematically equivalent to fit_weighted above
all.equal(fit_weighted$sdev, fit_cov$d, tolerance = 1e-8)# Two-block analysis with canonical PLS
Y <- matrix(rnorm(200 * 20), 200, 20)
pls <- genpls(X, Y, ncomp = 3,
preproc_x = multivarious::center(),
preproc_y = multivarious::center())
pls$d # singular values of the whitened cross-product
# Xe'Ye (covariance scale, NOT canonical correlations)
dim(pls$vx); dim(pls$vy) # X/Y weight matrices
# To get canonical-correlation-like quantities, correlate the latent
# variable pairs directly:
diag(cor(pls$lx, pls$ly))The metrics M and A define inner products and distances in the observation and variable spaces:
||x||_M^2 = x^T M xd_M(x,y)^2 = (x−y)^T M (x−y)||v||_A^2 = v^T A vd_A(v,w)^2 = (v−w)^T A (v−w)When M = I and A = I, GPCA reduces to
standard PCA.
Build locally:
devtools::build_vignettes()
browseVignettes("genpca")Run tests locally:
library(testthat)
library(pkgload)
pkgload::load_all()
testthat::test_dir("tests/testthat")The methods in this package are based on:
Allen, G. I., Grosenick, L., & Taylor, J. (2014). A generalized least-square matrix decomposition. Journal of the American Statistical Association, 109(505), 145-159. doi:10.1080/01621459.2013.852978
Beaton, D., ADNI, et al. (2016). Generalized partial least squares: A framework for simultaneously capturing common and individual variation. NeuroImage, 141, 346-363. doi:10.1016/j.neuroimage.2016.07.034
For additional theoretical background on generalized decompositions, see:
MIT (see LICENSE).
Issues and PRs welcome. Please open a ticket with a minimal example, your R session info, and (if relevant) a pointer to the metric matrices that reproduce the behavior.
This package uses the albersdown theme. Existing vignette theme hooks
are replaced so albers.css and local albers.js
render consistently on CRAN and GitHub Pages. The defaults are
configured via params$family and params$preset
(family = ‘red’, preset = ‘interaction’). The pkgdown site uses
template: { package: albersdown } together with generated
pkgdown/extra.css and pkgdown/extra.js so the
theme is linked and activated on site pages.