# faAlign: Align the columns of two factor loading matrices In fungible: Psychometric Functions from the Waller Lab

## Description

Align factor loading matrices across solutions using the Hungarian algorithm to locate optimal matches. faAlign will match the factors of F2 (the input matrix) to those in F1 (the target matrix) to minimize a least squares discrepancy function or to maximize factor congruence coefficients (i.e., vector cosines).

## Usage

 `1` ```faAlign(F1, F2, Phi2 = NULL, MatchMethod = "LS") ```

## Arguments

 `F1` target Factor Loadings Matrix. `F2` input Factor Loadings Matrix. F2 will be aligned with the target matrix, F1. `Phi2` optional factor correlation matrix for F2 (default = NULL). `MatchMethod` "LS" (Least Squares) or "CC" (congruence coefficients).

## Value

 `F2` re-ordered and reflected loadings of F2. `Phi2` reordered and reflected factor correlations. `FactorMap` a 2 x k matrix (where k is the number of columns of F1) structured such that row 1: the original column order of F2; row 2: the sorted column order of F2. `UniqueMatch` (logical) indicates whether a unique match was found. `MatchMethod` "LS" (least squares) or "CC" (congruence coefficients, i.e., cosines). `CC` Congruence coefficients for the matched factors. `LS` Root-mean-squared-deviations (least squares criterion) for the matched factors.

## Note

The Hungarian algorithm is implemented with the clue (Cluster Ensembles, Hornik, 2005) package. See Hornik K (2005). A CLUE for CLUster Ensembles. Journal of Statistical Software, 14(12). doi: 10.18637/jss.v014.i12 (URL: http://doi.org/10.18637/jss.v014.i12).

Niels Waller

## References

Kuhn, H. W. (1955). The Hungarian Method for the assignment problem. Naval Research Logistics Quarterly, 2, 83-97.

Kuhn, H. W. (1956). Variants of the Hungarian method for assignment problems. Naval Research Logistics Quarterly, 3, 253-258.

Papadimitriou, C. & Steiglitz, K. (1982). Combinatorial Optimization: Algorithms and Complexity. Englewood Cliffs: Prentice Hall.

Other Factor Analysis Routines: `BiFAD()`, `Box26`, `GenerateBoxData()`, `Ledermann()`, `SLi()`, `SchmidLeiman()`, `faEKC()`, `faIB()`, `faLocalMin()`, `faMB()`, `faMain()`, `faScores()`, `faSort()`, `faStandardize()`, `faX()`, `fals()`, `fapa()`, `fareg()`, `fsIndeterminacy()`, `orderFactors()`, `print.faMB()`, `print.faMain()`, `promaxQ()`, `summary.faMB()`, `summary.faMain()`
 ``` 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110``` ```# This example demonstrates the computation of # non-parametric bootstrap confidence intervals # for rotated factor loadings. library(GPArotation) data(HS9Var) HS9 <- HS9Var[HS9Var\$school == "Grant-White",7:15] # Compute an R matrix for the HSVar9 Mental Abilities Data R.HS9 <- cor(HS9) varnames <- c( "vis.per", "cubes", "lozenges", "paragraph.comp", "sentence.comp","word.mean", "speed.add", "speed.count.dots", "speed.discr") # Extract and rotate a 3-factor solution # via unweighted least squares factor extraction # and oblimin rotation. NFac <- 3 NVar <- 9 B <- 200 # Number of boostrap samples NSubj <- nrow(HS9) # Unrotated 3 factor uls solution F3.uls <- fals(R = R.HS9, nfactors = NFac) # Rotate via oblimin F3.rot <- oblimin(F3.uls\$loadings, gam = 0, normalize = FALSE) F3.loadings <- F3.rot\$loadings F3.phi <- F3.rot\$Phi # Reflect factors so that salient loadings are positive Dsgn <- diag(sign(colSums(F3.loadings^3))) F3.loadings <- F3.loadings %*% Dsgn F3.phi <- Dsgn %*% F3.phi %*% Dsgn rownames(F3.loadings) <- varnames colnames(F3.loadings) <- paste0("f", 1:3) colnames(F3.phi) <- rownames(F3.phi) <- paste0("f", 1:3) cat("\nOblimin rotated factor loadings for 9 Mental Abilities Variables") print( round(F3.loadings, 2)) cat("\nFactor correlation matrix") print( round( F3.phi, 2)) # Declare variables to hold bootstrap output Flist <- Philist <- as.list(rep(0, B)) UniqueMatchVec <- rep(0, B) rows <- 1:NSubj # Analyze bootstrap samples and record results for(i in 1:B){ cat("\nWorking on sample ", i) set.seed(i) # Create bootstrap sanples bsRows <- sample(rows, NSubj, replace= TRUE) Fuls <- fals(R = cor(HS9[bsRows, ]), nfactors = NFac) # rotated loadings Fboot <- oblimin(Fuls\$loadings, gam = 0, normalize = FALSE) out <- faAlign(F1 = F3.loadings, F2 = Fboot\$loadings, MatchMethod = "LS") Flist[[i]] <- out\$F2 # aligned version of Fboot\$loadings UniqueMatchVec[i] <- out\$UniqueMatch } cat("\nNumber of Unique Matches: ", 100*round(mean(UniqueMatchVec),2),"%\n") # Make a 3D array from list of matrices arr <- array( unlist(Flist) , c(NVar, NFac, B) ) # Get quantiles of factor elements over third dimension (samples) F95 <- apply( arr , 1:2 , quantile, .975 ) F05 <- apply( arr , 1:2 , quantile, .025 ) Fse <- apply( arr , 1:2, sd ) cat("\nUpper Bound 95% CI\n") print( round(F95,3)) cat("\n\nLower Bound 95% CI\n") print( round(F05,3)) # plot distribution of bootstrap estimates # for example element hist(arr[5,1,], xlim=c(.4,1), main = "Bootstrap Distribution for F[5,1]", xlab = "F[5,1]") print(round (F3.loadings, 2)) cat("\nStandard Errors") print( round( Fse, 2)) ```