% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/SparcePCA.R
\name{sparsePCA}
\alias{sparsePCA}
\title{Sparse Principal Components Analysis}
\usage{
sparsePCA(
  data,
  delay,
  selected,
  no_of_factors,
  ridge_penalty = 1e-06,
  lasso_penalty = NULL,
  max_iterations = 1000,
  weights = NULL,
  max_no_steps = NULL,
  comp_null = 1e-15,
  spca_conv_crit = 1e-04,
  parallel = FALSE,
  svd_method = "precise",
  normalise = TRUE,
  comp_var_expl = TRUE
)
}
\arguments{
\item{data}{Numeric (no_of_vars \eqn{\times}{x} no_of_obs) matrix of data or
zoo/xts object sampled at the same frequency.}

\item{delay}{Integer vector of variable delays, measured as the number of
months since the latest available observation.}

\item{selected}{Integer vector of the number of selected variables for each
factor.}

\item{no_of_factors}{Integer number of factors.}

\item{ridge_penalty}{Numeric ridge penalty.}

\item{lasso_penalty}{Numeric vector, lasso penalties for each factor (set to
NULL to disable as stopping criterion).}

\item{max_iterations}{Integer maximum number of iterations.}

\item{weights}{Numeric vector, weights for each variable weighing the
\eqn{\ell_1}{`l_1`} size constraint.}

\item{max_no_steps}{Integer number of LARS steps (set to NULL to disable as
stopping criterion).}

\item{comp_null}{Numeric computational zero.}

\item{spca_conv_crit}{Conversion threshold for the SPCA algorithm.}

\item{parallel}{Logical, whether or not to use Eigen's internal parallel
matrix operations.}

\item{svd_method}{Either "fast" or "precise". Option "fast" uses Eigen's
BDCSVD divide and conquer method for the computation of the singular values.
Option "precise" (default) implements the slower, but numerically more stable
JacobiSVD method.}

\item{normalise}{Logical, whether to normalise the loading matrix as in
\insertRef{zou2020elnet}{TwoStepSDFM}. Default is \code{TRUE}.}

\item{comp_var_expl}{Logical, whether to compute the relative variance
explained by each factor. Default is \verb{TRUE``.}}
}
\value{
An object of class \code{SPCAFit} with components:
\describe{
\item{data}{Original data matrix.}
\item{loading_matrix_estim}{Numeric matrix of estimated factor loadings.}
\item{factor_estim}{Object containing the SPCA factor estimates. The
object inherits its class from \code{data}: If \code{data} is provided as \code{zoo},
\code{factor_estim} will be a \code{zoo} object. If \code{data} is provided as  \code{matrix},
\code{factor_estim} will be a (\code{no_of_factors} \eqn{\times}{x} \code{no_of_obs})
matrix.}
\item{total_var_expl}{Numeric total variance explained.}
\item{pct_var_expl}{Numeric vector relative variance explained by each
factor.}
}
}
\description{
Estimate sparse sparse principal components via SPCA according to
\insertRef{zou2006sparse}{TwoStepSDFM}.
}
\details{
The function takes three stopping criteria: \code{selected}, \code{lasso_penalty}, and
\code{max_no_steps}. With \code{selected} the SPCA algorithm stops if each column of
the estimated loading matrix has the corresponding number of non-zero
loadings. This allows the user to directly control the degree of sparsity of
each factor loading. With \code{lasso_penalty}, the SPCA algorithm stops as soon
as the side-constraints of the inherent elastic-net problem are no longer
satisfied. With \code{max_no_steps}, the SPCA algorithm only takes that many LARS
steps for each factor loading's individual elastic-net problem before
stopping. If all criteria are provided, the first one satisfied will stop the
algorithm. For details see also \insertCite{zou2006sparse}{TwoStepSDFM} and
\insertCite{zou2020elnet}{TwoStepSDFM}.

Loosely, each SPCA algorithm iteration solves an elastic-net type problem for
each column of the loading matrix. One can extend this problem to the
adaptive elastic-net \insertCite{zou2009adaptive}{TwoStepSDFM}. The variable
\code{weights} lets the user provide weights for each observation. These weights
must be strictly greater than zero and are normalised internally to represent
relative weights. For more information on the computational implementation of
the weight extension in the context of SPCA see
\insertRef{zou2024general}{TwoStepSDFM}.

In each SPCA algorithm iteration, the function executes an SVD. To this end,
Eigen provides two alternatives \insertCite{eigenweb}{TwoStepSDFM}: Option
\code{precise} makes use of JacobiSVD. This method is numerically more stable, but
computationally costly, especially for medium to large matrices. Option
\code{fast} makes use of BDCSVD. This divide-and-conquer approach can lead to
significant performance gains with respect to large matrices. BDCSVD,
however, can be numerically unstable when Eigen is compiled with aggressive
speed optimisations. In the context of the \code{R}, this should be of no concern.
By default, \code{R} and most packages are compiled with "mild" \code{-O2} optimisation
and without any additional aggressive optimisation flags. Nonetheless, one
should checker whether both variants provide reasonably close results before
switching to \code{fast}. For more information see
\insertRef{eigenweb}{TwoStepSDFM}.
}
\examples{
data(factor_model)
set.seed(17032026)
no_of_factors <- 3
no_of_vars <- dim(factor_model$data)[2]
selected <- rep(floor(0.5 * no_of_vars), no_of_factors)
lasso_penalty <- exp(runif(no_of_factors, -10, 1))
max_no_steps <- 1000
spca_fit <- sparsePCA(data = factor_model$data, delay = factor_model$delay, 
                      selected = selected, no_of_factors = no_of_factors, 
                      ridge_penalty = 1e-2, lasso_penalty = lasso_penalty,
                      max_iterations = 1000, weights = NULL, 
                      max_no_steps = max_no_steps, comp_null = 1e-15,
                      spca_conv_crit = 1e-04, parallel = FALSE, 
                      svd_method = "precise", normalise = FALSE,
                      comp_var_expl = TRUE)
print(spca_fit)
spca_plots <- plot(spca_fit)
spca_plots$`Factor Time Series Plots`
spca_plots$`Loading Matrix Heatmap`
spca_plots$`Meas. Error Var.-Cov. Matrix Heatmap`
spca_plots$`Eigenvalue Plot`
spca_plots$`Variance Explained Chart`

}
\references{
\insertRef{zou2006sparse}{TwoStepSDFM}

\insertRef{zou2009adaptive}{TwoStepSDFM}

\insertRef{eigenweb}{TwoStepSDFM}

\insertRef{zou2020elnet}{TwoStepSDFM}

\insertRef{zou2024general}{TwoStepSDFM}
}
\author{
Domenic Franjic
}
