Learn R Programming

EFAtools (version 0.7.1)

PROCRUSTES: Rotate a loading matrix to a target using Procrustes alignment

Description

`PROCRUSTES()` aligns one loading matrix to a target loading matrix with the same dimensions. It is used internally by `EFA_POOLED()`, but can also be used directly when factor columns must be brought into a common orientation before averaging or comparing solutions.

Usage

PROCRUSTES(
  A,
  Target,
  rotation = c("orthogonal", "oblique"),
  S = NULL,
  T_init = NULL,
  oblique_eps = 1e-05,
  oblique_maxit = 1000,
  oblique_max_line_search = 10,
  oblique_step0 = 1,
  oblique_normalize = FALSE,
  oblique_random_starts = 0,
  oblique_screen_keep = 2,
  oblique_triage_maxit = 25,
  oblique_triage_improve_tol = 0
)

Value

A list containing aligned `loadings`, transformation matrix `T`, factor intercorrelation matrix `Phi`, target criterion `value`, convergence diagnostics, line-search diagnostics, and multi-start summaries. Row and column names are preserved where possible.

Arguments

A

Numeric loading matrix to be aligned.

Target

Numeric target matrix with the same dimensions as `A`.

rotation

Character string, either `"orthogonal"` or `"oblique"`.

S

Optional `k x k` cross-product matrix `crossprod(A)`. Supplying this is useful when the same `A` is rotated repeatedly. `S` is used only when `oblique_normalize = FALSE`; if Kaiser normalization is requested, the cross-product must be recomputed on the normalized matrix.

T_init

Optional `k x k` nonsingular starting transformation matrix for the oblique solver. Its columns are normalized internally.

oblique_eps

Positive convergence tolerance for the projected-gradient norm in the oblique solver.

oblique_maxit

Non-negative integer. Maximum number of projected-gradient updates in the full oblique solver.

oblique_max_line_search

Non-negative integer. Maximum number of step-halving attempts after the initial line-search step.

oblique_step0

Positive initial step size for the oblique solver.

oblique_normalize

Logical; if `TRUE`, apply Kaiser row normalization in the oblique solver and back-transform the aligned loadings afterwards.

oblique_random_starts

Non-negative integer. Number of additional random starts used by the oblique solver.

oblique_screen_keep

Non-negative integer. Number of random starts retained after cheap objective screening and sent to triage optimization.

oblique_triage_maxit

Non-negative integer. Number of short optimization iterations used in the triage stage.

oblique_triage_improve_tol

Non-negative scalar. Relative improvement required for a triaged start to be promoted to full optimization.

Details

For `rotation = "orthogonal"`, the function solves the closed-form orthogonal Procrustes problem

$$\min_T \frac{1}{2}\|A T - B\|_F^2 \quad \textrm{subject to}\quad T'T = I,$$

where `A` is the loading matrix and `B` is `Target`.

For `rotation = "oblique"`, the function calls the compiled `.oblique_procrustes()` optimizer. The oblique convention is the same as in `GPArotation::targetQ()`:

$$L = A T^{-T}, \qquad \Phi = T'T, \qquad diag(\Phi) = 1.$$

Random starts are only used for oblique alignment. For one-factor models, oblique and orthogonal alignment are equivalent, so the function uses the stable one-factor orthogonal solution instead of calling the oblique optimizer.