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.
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
)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. When oblique_normalize = TRUE
the returned loadings are back-transformed to the original scale, but
value is the criterion on the Kaiser-normalized loadings, so it is not
0.5 * sum((loadings - Target)^2).
Numeric loading matrix to be aligned.
Numeric target matrix with the same dimensions as A.
Character string, either "orthogonal" or "oblique".
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.
Optional k x k nonsingular starting transformation matrix for
the oblique solver. Its columns are normalized internally. If NULL (the
default), the oblique solver is warm-started from the closed-form orthogonal
Procrustes solution.
Positive convergence tolerance for the projected-gradient norm in the oblique solver.
Non-negative integer. Maximum number of projected-gradient updates in the full oblique solver.
Non-negative integer. Maximum number of step-halving attempts after the initial line-search step.
Positive initial step size for the oblique solver.
Logical; if TRUE, apply Kaiser row normalization to
the loadings (only) in the oblique solver and back-transform the aligned
loadings afterwards, leaving Target unnormalized (as in
GPArotation::targetQ(normalize = TRUE)).
Non-negative integer. Number of additional random starts used by the oblique solver.
Non-negative integer. Number of random starts retained after cheap objective screening and sent to triage optimization.
Non-negative integer. Number of short optimization iterations used in the triage stage.
Non-negative scalar. Relative improvement required for a triaged start to be promoted to full optimization.
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.$$
By default the oblique solver is warm-started from the closed-form orthogonal
Procrustes solution, which resolves the factor permutation and sign
indeterminacy and avoids the poor local minima an identity start can fall
into. Supply T_init to override this start. 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.