Skip to contents

Internal utility function that computes normalizing weights for factor loading matrices prior to rotation. Called by GPForth, GPFoblq, and the random-start wrappers.

Usage

NormalizingWeight(A, normalize=FALSE)

Arguments

A

A factor loading matrix.

normalize

Indicates if and how the matrix should be normalized. If FALSE (default), no normalization is done. If TRUE, Kaiser normalization is applied. If a numeric vector of length nrow(A), columns are divided by these weights before rotation and multiplied after. If a function, it should take A as its argument and return a numeric vector used as weights.

Value

A numeric vector of normalizing weights. This function is not exported from the NAMESPACE and is only called internally by the gradient projection rotation functions. See GPFRSorth for details on the normalize argument.

Details

NormalizingWeight is not exported from the NAMESPACE and is called internally by GPForth, GPFoblq, and the random-start wrapper functions. For a full description of the normalize argument and its options, see GPFRSorth.

The choice of normalization method can affect the rotation solution and its interpretation. For a detailed investigation of the effects of normalization on factor rotations, see Nguyen and Waller (2023).

References

Nguyen, H.V. and Waller, N.G. (2023). Local minima and factor rotations in exploratory factor analysis. Psychological Methods, 28(5), 1122–1141. doi: 10.1037/met0000467

See also

Examples

  data("CCAI", package = "GPArotation")
  # Kaiser normalization
  factanal(factors = 3, covmat = CCAI_R, n.obs = 461, rotation = "oblimin",
           control = list(rotate = list(normalize = TRUE)))
#> 
#> Call:
#> factanal(factors = 3, covmat = CCAI_R, n.obs = 461, rotation = "oblimin",     control = list(rotate = list(normalize = TRUE)))
#> 
#> 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.994                 
#> CCAI6   0.866                 
#> CCAI7   0.811                 
#> CCAI11  0.542   0.186   0.244 
#> CCAI12  0.494   0.126   0.343 
#> CCAI10  0.368   0.275   0.274 
#> CCAI14                  1.003 
#> CCAI13                  0.949 
#> CCAI5           0.283   0.632 
#> CCAI2           0.659         
#> CCAI4           0.835         
#> CCAI1           0.733         
#> CCAI3           0.660   0.109 
#> CCAI9   0.176   0.528   0.174 
#> 
#>             Factor1 Factor2 Factor3
#> SS loadings   3.628   3.136   3.136
#> 
#> Factor Correlations:
#>         Factor1 Factor2 Factor3
#> Factor1   1.000   0.713   0.625
#> Factor2   0.713   1.000   0.638
#> Factor3   0.625   0.638   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 
           
  # Cureton-Mulaik normalization passed as a function.
  # May result in convergence problems.
  NormalizingWeightCM <- function(L) {
    Dk    <- diag(sqrt(diag(L %*% t(L)))^-1) %*% L
    wghts <- rep(0, nrow(L))
    fpls  <- Dk[, 1]
    acosi <- acos(ncol(L)^(-1/2))
    for (i in 1:nrow(L)) {
      num      <- acosi - acos(abs(fpls[i]))
      dem      <- acosi - (function(a, m)
                    ifelse(abs(a) < (m^(-1/2)), pi/2, 0))(fpls[i], ncol(L))
      wghts[i] <- cos(num / dem * pi/2)^2 + 0.001
    }
    wghts * sqrt(diag(L %*% t(L)))^-1
  }

  data(Harman, package = "GPArotation")
  quartimin(Harman8, normalize = NormalizingWeightCM(Harman8), randomStarts = 100)
#> Oblique rotation method Quartimin converged at lowest minimum.
#> Of 100 random starts 100% converged, 100% at the same lowest minimum.
#> Loadings at lowest minimum:
#>                   CF1    CF2
#> height          0.899  0.040
#> arm.span        0.963 -0.041
#> forearm         0.938 -0.064
#> lower.leg       0.884  0.018
#> weight          0.001  0.931
#> bitro.diameter -0.029  0.827
#> chest.girth    -0.064  0.771
#> chest.width     0.077  0.686
#> 
#>                  CF1   CF2
#> SS loadings    3.374 2.591
#> Proportion Var 0.422 0.324
#> Cumulative Var 0.422 0.746
#> 
#> Phi:
#>       CF1   CF2
#> CF1 1.000 0.498
#> CF2 0.498 1.000
  quartimin(Harman8, normalize = TRUE, randomStarts = 100)
#> Oblique rotation method Quartimin converged at lowest minimum.
#> Of 100 random starts 100% converged, 100% at the same lowest minimum.
#> Loadings at lowest minimum:
#>                   CF1    CF2
#> height          0.892  0.056
#> arm.span        0.954 -0.023
#> forearm         0.929 -0.046
#> lower.leg       0.877  0.034
#> weight          0.014  0.925
#> bitro.diameter -0.017  0.821
#> chest.girth    -0.052  0.765
#> chest.width     0.086  0.683
#> 
#>                  CF1   CF2
#> SS loadings    3.362 2.604
#> Proportion Var 0.420 0.325
#> Cumulative Var 0.420 0.746
#> 
#> Phi:
#>       CF1   CF2
#> CF1 1.000 0.473
#> CF2 0.473 1.000