Skip to contents

Optimize factor loading rotation objective.

Usage

oblimin(A, Tmat=diag(ncol(A)), gam=0, normalize=FALSE, randomStarts=0, ...)
    quartimin(A, Tmat=diag(ncol(A)), normalize=FALSE, randomStarts=0, ...)
    targetT(A=NULL, Tmat=diag(ncol(A)), Target=NULL, normalize=FALSE, eps=1e-5, 
        maxit=1000, randomStarts=0, L=NULL, ...)
    targetQ(A=NULL, Tmat=diag(ncol(A)), Target=NULL, normalize=FALSE, eps=1e-5, 
        maxit=1000, randomStarts=0, L=NULL, ...)
    pstT(A=NULL, Tmat=diag(ncol(A)), W=NULL, Target=NULL, normalize=FALSE, eps=1e-5, 
        maxit=1000, randomStarts=0, L=NULL, ...)
    pstQ(A=NULL, Tmat=diag(ncol(A)), W=NULL, Target=NULL, normalize=FALSE, eps=1e-5, 
        maxit=1000, randomStarts=0, L=NULL, ...)
    oblimax(A, Tmat=diag(ncol(A)), normalize=FALSE, randomStarts=0, ...)
    entropy(A, Tmat=diag(ncol(A)), normalize=FALSE, randomStarts=0, ...)
    quartimax(A, Tmat=diag(ncol(A)), normalize=FALSE, randomStarts=0, ...)
    Varimax(A, Tmat=diag(ncol(A)), normalize=FALSE, randomStarts=0, ...)
    simplimax(A, Tmat=diag(ncol(A)), k=nrow(A), normalize=FALSE, randomStarts=0, ...)
    bentlerT(A, Tmat=diag(ncol(A)), normalize=FALSE, randomStarts=0, ...)
    bentlerQ(A, Tmat=diag(ncol(A)), normalize=FALSE, randomStarts=0, ...)
    tandemI(A, Tmat=diag(ncol(A)), normalize=FALSE, randomStarts=0, ...)
    tandemII(A, Tmat=diag(ncol(A)), normalize=FALSE, randomStarts=0, ...)
    geominT(A, Tmat=diag(ncol(A)), delta=0.01, normalize=FALSE, randomStarts=0, ...)
    geominQ(A, Tmat=diag(ncol(A)), delta=0.01, normalize=FALSE, randomStarts=0, ...)
    bigeominT(A, Tmat=diag(ncol(A)), delta=0.01, normalize=FALSE, randomStarts=0, ...)
    bigeominQ(A, Tmat=diag(ncol(A)), delta=0.01, normalize=FALSE, randomStarts=0, ...)
    cfT(A, Tmat=diag(ncol(A)), kappa=0, normalize=FALSE, randomStarts=0, ...)
    cfQ(A, Tmat=diag(ncol(A)), kappa=0, normalize=FALSE, randomStarts=0, ...)
    equamax(A, Tmat=diag(ncol(A)), kappa=ncol(A)/(2*nrow(A)), normalize=FALSE,
        randomStarts=0, ...)
    parsimax(A, Tmat=diag(ncol(A)), kappa=(ncol(A)-1)/(ncol(A)+nrow(A)-2), 
        normalize=FALSE, randomStarts=0, ...)
    infomaxT(A, Tmat=diag(ncol(A)), normalize=FALSE, randomStarts=0, ...)
    infomaxQ(A, Tmat=diag(ncol(A)), normalize=FALSE, randomStarts=0, ...)
    mccammon(A, Tmat=diag(ncol(A)), normalize=FALSE, randomStarts=0, ...)
    varimin(A, Tmat=diag(ncol(A)), normalize=FALSE, randomStarts=0, ...)
    bifactorT(A, Tmat=diag(ncol(A)), normalize=FALSE, randomStarts=0, ...)
    bifactorQ(A, Tmat=diag(ncol(A)), normalize=FALSE, randomStarts=0, ...)
    lpT(A, Tmat=diag(ncol(A)), p=1, normalize=FALSE, eps=1e-05, maxit=1000, 
            randomStarts=0, gpaiter=5) 
    lpQ(A, Tmat=diag(ncol(A)), p=1, normalize=FALSE, eps=1e-05, maxit=1000, 
        randomStarts=0, gpaiter=5)

Arguments

A

an initial loadings matrix to be rotated.

Tmat

initial rotation matrix.

gam

Obliqueness parameter (\(\gamma\) in the mathematical definition). 0=Quartimin, .5=Biquartimin, 1=Covarimin.

Target

rotation target for objective calculation.

W

weighting of each element in target.

k

number of close to zero loadings.

delta

constant added to \(\Lambda^2\) in the objective calculation.

kappa

see details.

normalize

parameter passed to optimization routine (GPForth or GPFoblq).

eps

convergence tolerance passed to GPForth or GPFoblq via .... Convergence is assumed when the norm of the gradient is smaller than eps. Default is 1e-5.

maxit

maximum number of iterations passed to GPForth or GPFoblq via .... Default is 1000.

...

additional arguments passed to GPForth or GPFoblq, including eps and maxit.

randomStarts

parameter passed to optimization routine (GPFRSorth or GPFRSoblq).

L

provided for backward compatibility in target rotations only. Use A going forward.

p

Component-wise \(L^p\), where 0 < p \(=<\) 1.

gpaiter

Maximum iterations for GPA rotation loop in \(L^p\) rotation.

Value

A GPArotation object which is a list with elements:

loadings

The rotated loadings matrix, one column per factor. If random starts were requested, this is the solution with the lowest criterion value.

Th

The rotation matrix, satisfying loadings %*% t(Th) = A for orthogonal rotation and loadings = A %*% solve(t(Th)) for oblique rotation.

Table

A matrix recording the iteration history: iteration number, criterion value, log10 of the gradient norm, and step size (alpha).

method

A string indicating the rotation criterion.

orthogonal

A logical indicating if the rotation is orthogonal.

convergence

A logical indicating if convergence was obtained.

Phi

t(Th) %*% Th, the covariance matrix of the rotated factors. Omitted (NULL) for orthogonal rotations.

Gq

The gradient of the criterion at the rotated loadings.

randStartChar

A named vector summarising random start results: randomStarts, Converged, atMinimum, localMins. Only present when randomStarts > 1.

Details

These functions optimize a rotation objective. They can be used directly or the function name can be passed to factor analysis functions like factanal. Several of the function names end in T or Q, which indicates if they are orthogonal or oblique rotations (using GPFRSorth or GPFRSoblq respectively). The gradient projection algorithms are described in Bernaards and Jennrich (2005).

obliminobliqueoblimin family; gam controls obliqueness
quartiminobliqueoblimin with gam = 0
targetTorthogonalrotation towards a target matrix
targetQobliquerotation towards a target matrix
pstTorthogonalpartially specified target rotation
pstQobliquepartially specified target rotation
oblimaxobliquemaximizes overall kurtosis of loadings
entropyorthogonalminimizes entropy of squared loadings
quartimaxorthogonalmaximizes variance of squared loadings within variables
Varimaxorthogonalmaximizes variance of squared loadings within factors
simplimaxobliqueminimizes the k smallest squared loadings
bentlerTorthogonalinvariant pattern simplicity
bentlerQobliqueinvariant pattern simplicity
tandemIorthogonalfactors share high loadings on same variables
tandemIIorthogonalfactors do not share high loadings on same variables
geominTorthogonalminimizes geometric mean of squared loadings
geominQobliqueminimizes geometric mean of squared loadings
bigeominTorthogonalgeomin with a general factor in column 1
bigeominQobliquegeomin with a general factor in column 1
cfTorthogonalCrawford-Ferguson family; kappa controls complexity
cfQobliqueCrawford-Ferguson family; kappa controls complexity
equamaxorthogonalCrawford-Ferguson with kappa = m/(2p)
parsimaxorthogonalCrawford-Ferguson with kappa = (m-1)/(p+m-2)
infomaxTorthogonalinfomax information criterion
infomaxQobliqueinfomax information criterion
mccammonorthogonalminimizes entropy ratio across factors
variminorthogonalminimizes variance of squared loadings within factors
bifactorTorthogonalbifactor; general factor in column 1
bifactorQobliquebiquartimin; general factor in column 1
lpTorthogonal\(L^p\) sparsity rotation
lpQoblique\(L^p\) sparsity rotation

The Varimax implementation in the list uses the gradient projection algorithm applied to vgQ.varimax. This implementation is different that the varimax rotation defined in the stats package. Additionally, varimax does Kaiser normalization by default whereas GPArotation::Varimax does not.

The argument kappa parameterizes the family for the Crawford-Ferguson method. If m is the number of factors and p is the number of indicators then kappa values having special names are \(0=\)Quartimax, \(1/p=\)Varimax, \(m/(2*p)=\)Equamax, \((m-1)/(p+m-2)=\)Parsimax, \(1=\)Factor parsimony.

Bifactor rotations, bifactorT and bifactorQ are called bifactor and biquartimin in Jennrich and Bentler (2011). For a comparison of exploratory bifactor analysis algorithms including those implemented here, see Garcia-Garzon, Abad and Garrido (2021).

The argument p is needed for \(L^p\) rotation. See Lp rotation for details on the rotation method.

References

Bernaards, C.A. and Jennrich, R.I. (2005) Gradient Projection Algorithms and Software for Arbitrary Rotation Criteria in Factor Analysis. Educational and Psychological Measurement, 65, 676–696. doi: 10.1177/0013164404272507

Bi, Y. and Barchard, K.A. (2024). Purchasing choices that reduce climate change: An exploratory factor analysis. Spectra Undergraduate Research Journal, 3(2), 8–14. doi: 10.9741/2766-7227.1028.

Fischer, R., & Fontaine, J. (2010). Methods for investigating structural equivalence. In D. Matsumoto & F. van de Vijver (Eds.), Cross-Cultural Research Methods in Psychology (pp. 179–215). Cambridge University Press. doi: 10.1017/CBO9780511779381.010

Garcia-Garzon, E., Abad, F.J. and Garrido, L.E. (2021). On omega hierarchical estimation: A comparison of exploratory bi-factor analysis algorithms. Multivariate Behavioral Research, 56(1), 101–119. doi: 10.1080/00273171.2020.1736977

Jennrich, R.I. and Bentler, P.M. (2011). Exploratory bi-factor analysis. Psychometrika, 76(4), 537–549. doi: 10.1007/s11336-011-9218-4

For references to individual rotation criteria see vignette("GPA1guide", package = "GPArotation").

Author

Coen A. Bernaards and Robert I. Jennrich with some R modifications by Paul Gilbert.

Examples

  # For extended examples see the vignettes:
  # vignette("GPA1guide",    package = "GPArotation")
  # vignette("GPA2local",    package = "GPArotation")
  # vignette("GPA3bifactor", package = "GPArotation")

  # --- Accessing rotated loadings ---
  data("Harman", package = "GPArotation") # 8 physical variables
  qHarman <- quartimax(Harman8)
  loadings(qHarman)                              # via extractor (recommended)
#>                      CF1       CF2
#> height         0.8987554 0.1948197
#> arm.span       0.9339440 0.1297446
#> forearm        0.9021319 0.1038604
#> lower.leg      0.8765090 0.1712805
#> weight         0.3155758 0.8764747
#> bitro.diameter 0.2511265 0.7734879
#> chest.girth    0.1980102 0.7146775
#> chest.width    0.3078601 0.6593331
  qHarman$loadings                               # via direct list access
#>                      CF1       CF2
#> height         0.8987554 0.1948197
#> arm.span       0.9339440 0.1297446
#> forearm        0.9021319 0.1038604
#> lower.leg      0.8765090 0.1712805
#> weight         0.3155758 0.8764747
#> bitro.diameter 0.2511265 0.7734879
#> chest.girth    0.1980102 0.7146775
#> chest.width    0.3078601 0.6593331
  all.equal(loadings(qHarman), qHarman$loadings) # identical
#> [1] TRUE

  # --- Rotating factanal loadings ---
  data("WansbeekMeijer", package = "GPArotation") # Netherlands TV viewership
  fa.unrotated <- factanal(factors = 2, covmat = NetherlandsTV,
                           normalize = TRUE, rotation = "none")
  quartimax(loadings(fa.unrotated), normalize = TRUE)
#> Orthogonal rotation method Quartimax converged.
#> Loadings:
#>          Factor1 Factor2
#> NL1        0.327   0.720
#> TV2        0.424   0.725
#> NL3        0.323   0.703
#> RTL4       0.669   0.214
#> RTL5       0.738   0.183
#> Veronica   0.811   0.109
#> SBS6       0.719   0.106
#> 
#>                Factor1 Factor2
#> SS loadings      2.556   1.641
#> Proportion Var   0.365   0.234
#> Cumulative Var   0.365   0.600
  geominQ(loadings(fa.unrotated), normalize = TRUE, randomStarts = 100)
#> Oblique rotation method Geomin converged at lowest minimum.
#> Of 100 random starts 100% converged, 100% at the same lowest minimum.
#> Loadings at lowest minimum:
#>          Factor1 Factor2
#> NL1       -0.016   0.800
#> TV2        0.090   0.785
#> NL3       -0.011   0.780
#> RTL4       0.631   0.113
#> RTL5       0.724   0.060
#> Veronica   0.844  -0.046
#> SBS6       0.743  -0.029
#> 
#>                Factor1 Factor2
#> SS loadings      2.254   1.943
#> Proportion Var   0.322   0.278
#> Cumulative Var   0.322   0.600
#> 
#> Phi:
#>         Factor1 Factor2
#> Factor1   1.000   0.582
#> Factor2   0.582   1.000

  # --- Passing rotation to factanal ---
  # CCAI:Climate-Friendly Purchasing Choices domain of the Climate Change Action Inventory
  data("CCAI", package = "GPArotation") 
  factanal(factors = 3, covmat = CCAI_R, n.obs = 461, rotation = "infomaxT")
#> 
#> Call:
#> factanal(factors = 3, covmat = CCAI_R, n.obs = 461, rotation = "infomaxT")
#> 
#> Uniquenesses:
#>  CCAI8  CCAI6  CCAI7 CCAI11 CCAI12 CCAI10 CCAI14 CCAI13  CCAI5  CCAI2  CCAI4 
#>  0.128  0.272  0.299  0.247  0.266  0.347  0.055  0.077  0.286  0.612  0.321 
#>  CCAI1  CCAI3  CCAI9 
#>  0.455  0.364  0.372 
#> 
#> Loadings:
#>        Factor1 Factor2 Factor3
#> CCAI8  0.864   0.277   0.222  
#> CCAI6  0.774   0.289   0.214  
#> CCAI7  0.744   0.343   0.172  
#> CCAI11 0.634   0.434   0.404  
#> CCAI12 0.600   0.397   0.465  
#> CCAI10 0.520   0.463   0.410  
#> CCAI14 0.302   0.277   0.882  
#> CCAI13 0.318   0.313   0.851  
#> CCAI5  0.308   0.460   0.638  
#> CCAI2  0.237   0.567   0.102  
#> CCAI4  0.273   0.739   0.241  
#> CCAI1  0.278   0.656   0.193  
#> CCAI3  0.355   0.653   0.290  
#> CCAI9  0.409   0.589   0.337  
#> 
#>                Factor1 Factor2 Factor3
#> SS loadings      3.720   3.296   2.884
#> Proportion Var   0.266   0.235   0.206
#> Cumulative Var   0.266   0.501   0.707
#> 
#> Test of the hypothesis that 3 factors are sufficient.
#> The chi square statistic is 387.64 on 52 degrees of freedom.
#> The p-value is 7.58e-53 
  factanal(factors = 3, covmat = CCAI_R, n.obs = 461, rotation = "infomaxT",
           control = list(rotate = list(normalize = TRUE, eps = 1e-6)))
#> 
#> Call:
#> factanal(factors = 3, covmat = CCAI_R, n.obs = 461, rotation = "infomaxT",     control = list(rotate = list(normalize = TRUE, eps = 1e-06)))
#> 
#> Uniquenesses:
#>  CCAI8  CCAI6  CCAI7 CCAI11 CCAI12 CCAI10 CCAI14 CCAI13  CCAI5  CCAI2  CCAI4 
#>  0.128  0.272  0.299  0.247  0.266  0.347  0.055  0.077  0.286  0.612  0.321 
#>  CCAI1  CCAI3  CCAI9 
#>  0.455  0.364  0.372 
#> 
#> Loadings:
#>        Factor1 Factor2 Factor3
#> CCAI8  0.322   0.852   0.205  
#> CCAI6  0.329   0.762   0.198  
#> CCAI7  0.381   0.729   0.155  
#> CCAI11 0.473   0.617   0.386  
#> CCAI12 0.436   0.586   0.448  
#> CCAI10 0.496   0.502   0.392  
#> CCAI14 0.312   0.298   0.871  
#> CCAI13 0.348   0.312   0.840  
#> CCAI5  0.489   0.293   0.623  
#> CCAI2  0.580   0.211          
#> CCAI4  0.756   0.241   0.220  
#> CCAI1  0.673   0.249   0.174  
#> CCAI3  0.676   0.327   0.270  
#> CCAI9  0.615   0.385   0.318  
#> 
#>                Factor1 Factor2 Factor3
#> SS loadings      3.671   3.507   2.721
#> Proportion Var   0.262   0.251   0.194
#> Cumulative Var   0.262   0.513   0.707
#> 
#> Test of the hypothesis that 3 factors are sufficient.
#> The chi square statistic is 387.64 on 52 degrees of freedom.
#> The p-value is 7.58e-53 
           
  # --- Target rotation ---
  # Orthogonal target rotation of two varimax rotated matrices 
  # towards each other. Data from Fischer and Fontaine (2010).
  # See vignette("GPA1guide", package = "GPArotation") for further analyses.
  trBritain <- matrix(c(.783, -.163, .811, .202, .724, .209, .850, .064,
                       -.031, .592, -.028, .723, .388, .434, .141, .808,
                       .215, .709), byrow = TRUE, ncol = 2)

  trGermany <- matrix(c(.778, -.066, .875, .081, .751, .079, .739, .092,
                       .195, .574, -.030, .807, -.135, .717, .125, .738,
                       .060, .691), byrow = TRUE, ncol = 2)
  trx <- targetT(trGermany, Target = trBritain)
  round(trx$loadings - trBritain, 3)  # difference from target
#>         [,1]   [,2]
#>  [1,] -0.009  0.064
#>  [2,]  0.067 -0.159
#>  [3,]  0.030 -0.162
#>  [4,] -0.108 -0.004
#>  [5,]  0.250 -0.027
#>  [6,]  0.033  0.085
#>  [7,] -0.492  0.288
#>  [8,]  0.015 -0.076
#>  [9,] -0.125 -0.021

  # --- Partially specified target rotation ---
  # See vignette("GPA1guide", package = "GPArotation") for full context.
  # Unrotated loadings matrix A and partially specified target SPA
  # NA entries in SPA are unspecified --- rotation is free there
  # Numeric entries are the target values the rotation aims towards
  A <- matrix(c(.664, .688, .492, .837, .705, .82, .661, .457, .765, .322,
                .248, .304, -0.291, -0.314, -0.377, .397, .294, .428,
                -0.075, .192, .224, .037, .155, -.104, .077, -.488, .009), ncol = 3)
  SPA <- matrix(c(rep(NA, 6), .7, .0, .7, rep(0, 3), rep(NA, 7),
                  0, 0, NA, 0, rep(NA, 4)), ncol = 3)
  comparison <- cbind(round(A, 3), rep(NA, nrow(A)), SPA)
  colnames(comparison) <- c("A.F1", "A.F2", "A.F3", "|", "T.F1", "T.F2", "T.F3")
  cat("Unrotated loadings (A) and partially specified target (SPA):\n")
#> Unrotated loadings (A) and partially specified target (SPA):
  print(comparison, na.print = "NA")
#>        A.F1   A.F2   A.F3  | T.F1 T.F2 T.F3
#>  [1,] 0.664  0.322 -0.075 NA   NA    0   NA
#>  [2,] 0.688  0.248  0.192 NA   NA    0    0
#>  [3,] 0.492  0.304  0.224 NA   NA    0    0
#>  [4,] 0.837 -0.291  0.037 NA   NA   NA   NA
#>  [5,] 0.705 -0.314  0.155 NA   NA   NA    0
#>  [6,] 0.820 -0.377 -0.104 NA   NA   NA   NA
#>  [7,] 0.661  0.397  0.077 NA  0.7   NA   NA
#>  [8,] 0.457  0.294 -0.488 NA  0.0   NA   NA
#>  [9,] 0.765  0.428  0.009 NA  0.7   NA   NA
  targetT(A, Target = SPA)
#> Orthogonal rotation method Target rotation converged.
#> Loadings:
#>        [,1]   [,2]  [,3]
#>  [1,] 0.611  0.023 0.420
#>  [2,] 0.734  0.055 0.173
#>  [3,] 0.607 -0.086 0.093
#>  [4,] 0.608  0.622 0.176
#>  [5,] 0.549  0.564 0.017
#>  [6,] 0.499  0.713 0.261
#>  [7,] 0.705 -0.069 0.314
#>  [8,] 0.235  0.023 0.691
#>  [9,] 0.768 -0.039 0.422
#> 
#>                 [,1]  [,2]  [,3]
#> SS loadings    3.341 1.231 1.068
#> Proportion Var 0.371 0.137 0.119
#> Cumulative Var 0.371 0.508 0.627

  # --- Random starts ---
  # CCAI Climate-Friendly Purchasing Choices domain, 14 items, 3 oblique factors.
  # High factor intercorrelations make oblimin the natural choice.
  # Note: factanal uses MLE extraction; results differ somewhat from
  # PCA-based extraction used in Bi and Barchard (2024).
  data("CCAI", package = "GPArotation")
  fa.unrotated <- factanal(factors = 3, covmat = CCAI_R, n.obs = 461, rotation = "none")
  oblimin(loadings(fa.unrotated), Tmat = Random.Start(3))  # single random start
#> Oblique rotation method Oblimin Quartimin converged.
#> Loadings:
#>        Factor1 Factor2 Factor3
#> CCAI8    0.984  -0.064  -0.011
#> CCAI6    0.858  -0.005  -0.002
#> CCAI7    0.806   0.100  -0.068
#> CCAI11   0.537   0.198   0.237
#> CCAI12   0.489   0.138   0.338
#> CCAI10   0.366   0.287   0.263
#> CCAI14   0.001  -0.048   1.001
#> CCAI13   0.016   0.007   0.946
#> CCAI5    0.003   0.296   0.619
#> CCAI2    0.028   0.668  -0.107
#> CCAI4   -0.046   0.848   0.013
#> CCAI1    0.014   0.745  -0.025
#> CCAI3    0.090   0.672   0.085
#> CCAI9    0.179   0.541   0.154
#> 
#>                Factor1 Factor2 Factor3
#> SS loadings      3.601   3.260   3.039
#> Proportion Var   0.257   0.233   0.217
#> Cumulative Var   0.257   0.490   0.707
#> 
#> Phi:
#>         Factor1 Factor2 Factor3
#> Factor1   1.000   0.707   0.622
#> Factor2   0.707   1.000   0.652
#> Factor3   0.622   0.652   1.000
  oblimin(loadings(fa.unrotated), randomStarts = 1)        # equivalent
#> Oblique rotation method Oblimin Quartimin converged.
#> Loadings:
#>        Factor1 Factor2 Factor3
#> CCAI8    0.984  -0.064  -0.011
#> CCAI6    0.858  -0.005  -0.002
#> CCAI7    0.806   0.100  -0.068
#> CCAI11   0.537   0.198   0.237
#> CCAI12   0.489   0.138   0.338
#> CCAI10   0.366   0.287   0.263
#> CCAI14   0.001  -0.048   1.001
#> CCAI13   0.016   0.007   0.946
#> CCAI5    0.003   0.296   0.619
#> CCAI2    0.028   0.668  -0.107
#> CCAI4   -0.046   0.848   0.013
#> CCAI1    0.014   0.745  -0.025
#> CCAI3    0.090   0.672   0.085
#> CCAI9    0.179   0.541   0.154
#> 
#>                Factor1 Factor2 Factor3
#> SS loadings      3.601   3.260   3.039
#> Proportion Var   0.257   0.233   0.217
#> Cumulative Var   0.257   0.490   0.707
#> 
#> Phi:
#>         Factor1 Factor2 Factor3
#> Factor1   1.000   0.707   0.622
#> Factor2   0.707   1.000   0.652
#> Factor3   0.622   0.652   1.000
  oblimin(loadings(fa.unrotated), randomStarts = 100)      # multiple starts
#> Oblique rotation method Oblimin Quartimin converged at lowest minimum.
#> Of 100 random starts 100% converged, 100% at the same lowest minimum.
#> Loadings at lowest minimum:
#>        Factor1 Factor2 Factor3
#> CCAI8    0.984  -0.064  -0.011
#> CCAI6    0.858  -0.005  -0.002
#> CCAI7    0.806   0.100  -0.068
#> CCAI11   0.537   0.198   0.237
#> CCAI12   0.489   0.138   0.338
#> CCAI10   0.366   0.287   0.263
#> CCAI14   0.001  -0.048   1.001
#> CCAI13   0.016   0.007   0.946
#> CCAI5    0.003   0.296   0.619
#> CCAI2    0.028   0.668  -0.107
#> CCAI4   -0.046   0.847   0.013
#> CCAI1    0.014   0.745  -0.025
#> CCAI3    0.090   0.672   0.085
#> CCAI9    0.179   0.541   0.154
#> 
#>                Factor1 Factor2 Factor3
#> SS loadings      3.601   3.260   3.039
#> Proportion Var   0.257   0.233   0.217
#> Cumulative Var   0.257   0.490   0.707
#> 
#> Phi:
#>         Factor1 Factor2 Factor3
#> Factor1   1.000   0.707   0.622
#> Factor2   0.707   1.000   0.652
#> Factor3   0.622   0.652   1.000

  # Directly via factanal call 
  factanal(factors = 3, covmat = CCAI_R, n.obs = 461, rotation = "oblimin",
      control = list(rotate = list(normalize = TRUE, gam = -0.1, randomStarts = 100)))
#> 
#> Call:
#> factanal(factors = 3, covmat = CCAI_R, n.obs = 461, rotation = "oblimin",     control = list(rotate = list(normalize = TRUE, gam = -0.1,         randomStarts = 100)))
#> 
#> Uniquenesses:
#>  CCAI8  CCAI6  CCAI7 CCAI11 CCAI12 CCAI10 CCAI14 CCAI13  CCAI5  CCAI2  CCAI4 
#>  0.128  0.272  0.299  0.247  0.266  0.347  0.055  0.077  0.286  0.612  0.321 
#>  CCAI1  CCAI3  CCAI9 
#>  0.455  0.364  0.372 
#> 
#> Loadings:
#>        Factor1 Factor2 Factor3
#> CCAI8   0.962                 
#> CCAI6   0.840                 
#> CCAI7   0.788   0.109         
#> CCAI11  0.535   0.200   0.252 
#> CCAI12  0.490   0.143   0.347 
#> CCAI10  0.370   0.283   0.280 
#> CCAI14                  0.977 
#> CCAI13                  0.926 
#> CCAI5           0.288   0.622 
#> CCAI2           0.639         
#> CCAI4           0.810         
#> CCAI1           0.712         
#> CCAI3           0.645   0.121 
#> CCAI9   0.187   0.522   0.183 
#> 
#>             Factor1 Factor2 Factor3
#> SS loadings    3.61   3.159    3.13
#> 
#> Factor Correlations:
#>         Factor1 Factor2 Factor3
#> Factor1   1.000   0.678   0.587
#> Factor2   0.678   1.000   0.602
#> Factor3   0.587   0.602   1.000
#> 
#> Test of the hypothesis that 3 factors are sufficient.
#> The chi square statistic is 387.64 on 52 degrees of freedom.
#> The p-value is 7.58e-53 

  # --- Assessing local minima ---
  # For detailed investigation of local minima across all random starts
  # see vignette("GPA2local", package = "GPArotation").
  data(Thurstone, package = "GPArotation")
  infomaxQ(box26, normalize = TRUE, randomStarts = 150)
#> Oblique rotation method Infomax converged at lowest minimum.
#> Of 150 random starts 100% converged, 31% at the same lowest minimum.
#> Random starts converged to 9 different local minima.
#> Loadings at lowest minimum:
#>         [,1]   [,2]   [,3]
#>  [1,] -0.698  0.733  0.741
#>  [2,]  0.632 -0.446  0.679
#>  [3,]  0.734  0.665 -0.489
#>  [4,] -0.012  0.102  0.937
#>  [5,]  0.055  0.906  0.094
#>  [6,]  0.894  0.107  0.057
#>  [7,] -0.308  0.407  0.892
#>  [8,]  0.310 -0.145  0.841
#>  [9,] -0.254  0.895  0.348
#> [10,]  0.329  0.934 -0.119
#> [11,]  0.856 -0.113  0.274
#> [12,]  0.881  0.301 -0.143
#> [13,] -1.068  1.019 -0.025
#> [14,]  1.068 -1.019  0.025
#> [15,] -1.147  0.000  1.072
#> [16,]  1.147  0.000 -1.072
#> [17,]  0.008 -1.057  1.028
#> [18,] -0.008  1.057 -1.028
#> [19,]  0.090 -0.006  0.922
#> [20,]  0.096  0.922  0.023
#> [21,]  0.876  0.109  0.082
#> [22,]  0.100  0.001  0.900
#> [23,]  0.122  0.886  0.013
#> [24,]  0.837  0.102  0.116
#> [25,]  0.348  0.405  0.419
#> [26,]  0.473  0.310  0.358
#> 
#>                 [,1]  [,2]  [,3]
#> SS loadings    8.668 8.559 8.183
#> Proportion Var 0.333 0.329 0.315
#> Cumulative Var 0.333 0.663 0.977
#> 
#> Phi:
#>       [,1]  [,2]  [,3]
#> [1,] 1.000 0.548 0.607
#> [2,] 0.548 1.000 0.543
#> [3,] 0.607 0.543 1.000
  geominQ(box26,  normalize = TRUE, randomStarts = 150)
#> Oblique rotation method Geomin converged at lowest minimum.
#> Of 150 random starts 100% converged, 23% at the same lowest minimum.
#> Random starts converged to 4 different local minima.
#> Loadings at lowest minimum:
#>         [,1]   [,2]   [,3]
#>  [1,] -0.015 -0.010  0.993
#>  [2,]  0.942  0.048  0.059
#>  [3,]  0.061  0.965 -0.001
#>  [4,]  0.642 -0.014  0.637
#>  [5,]  0.002  0.646  0.596
#>  [6,]  0.613  0.644 -0.025
#>  [7,]  0.383  0.007  0.835
#>  [8,]  0.812  0.034  0.385
#>  [9,] -0.020  0.418  0.788
#> [10,]  0.027  0.858  0.444
#> [11,]  0.766  0.452 -0.019
#> [12,]  0.442  0.784 -0.029
#> [13,] -0.829  0.009  0.747
#> [14,]  0.829 -0.009 -0.747
#> [15,]  0.006 -0.825  0.816
#> [16,] -0.006  0.825 -0.816
#> [17,]  0.848 -0.798 -0.009
#> [18,] -0.848  0.798  0.009
#> [19,]  0.710 -0.020  0.548
#> [20,] -0.023  0.689  0.557
#> [21,]  0.618  0.631 -0.006
#> [22,]  0.700 -0.008  0.537
#> [23,] -0.009  0.681  0.525
#> [24,]  0.618  0.599  0.016
#> [25,]  0.478  0.466  0.453
#> [26,]  0.528  0.487  0.340
#> 
#>                 [,1]  [,2]  [,3]
#> SS loadings    8.824 8.795 7.790
#> Proportion Var 0.339 0.338 0.300
#> Cumulative Var 0.339 0.678 0.977
#> 
#> Phi:
#>       [,1]  [,2]  [,3]
#> [1,] 1.000 0.268 0.206
#> [2,] 0.268 1.000 0.278
#> [3,] 0.206 0.278 1.000