R: Choose a Transformation in Exploratory Factor Analysis

Rotate

R Documentation

Choose a Transformation in Exploratory Factor Analysis

Description

This function is intended for users and finds an optimal rotation
of preliminary factor loadings extracted via exploratory factor
analysis. Unlike other software, Rotate finds a rotation
that is optimal with respect to an intersection of
criteria, one of which is a “analytic” criterion and the
rest are “constraints”. Similar to make_restrictions,
much of the functionality of Rotate is implemented via
pop-up menus, which is the strongly recommended way to proceed.
Also, the vignette details what all these options mean in
substantive terms; execute vignette("FAiR") to read it.

An optional list whose elements are functions or
character strings naming functions to be used in the lexical
optimization process. If unspecified, Rotate will prompt you
with pop-up menus, which is the recommended way to proceed. See the
Details section otherwise.

methodArgs

an option list with named elements for additional
arguments needed by some criterion functions; see the Details section

normalize

a vector with the same length as the number of manifest
variables, or a function that takes the preliminary primary pattern
matrix as its first argument and produces such a vector, or a character
string that is either "kaiser" or "cureton-mulaik", which
are discussed more in the Details section. The rows of the preliminary
primary pattern matrix are divided by this vector before the
optimal transformation is found. Note that row-normalization may not be
sensible, especially if the objective function optimizes the reference structure
matrix or the factor contribution matrix.

seeds

A vector of length one or two to be used as the random
number generator seeds corresponding to the unif.seed and
int.seed arguments to genoud respectively.
If seeds is a single number, this seed is used for both
unif.seed and int.seed. These seeds override the defaults
for genoud and make it easier to replicate
an analysis exactly. However, if seeds = NULL, then the default
seeds are used, which is absolutely necessary during simulations.

NelderMead

Logical indicating whether to call optim with
method = "Nelder-Mead" when the genetic algorithm has finished to further
polish the solution.

...

Further arguments that are passed to genoud.
Note that several of the default arguments to genoud
are silently overridden by Factanal out of logical necissitity:

argument

value

why?

nvars

FAobject@restrictions@factors[1]^2

max

FALSE

minimizing the objective

hessian

FALSE

not meaningful

lexical

TRUE

resticted optimization

Domains

NULL

default.domains

1

parameters are cosines

data.type.int

FALSE

parameters are doubles

fn

wrapper around an internal function

BFGSfn

wrapper around an internal function

gn

NULL

analytic gradients are unknown

BFGShelp

wrapper around an internal function

unif.seed

taken from seeds

replicability

int.seed

taken from seeds

replicability

The following arguments to genoud default to values
that differ from those documented at genoud but can
be overridden by specifying them explicitly in the ... :

argument

value

why?

boundary.enforcement

1 usually

2 can cause problems

MemoryMatrix

FALSE

runs faster

print.level

1

output is not that helpful for >= 2

P9mix

1

to always accept the BFGS result

BFGSburnin

5

to have a little burnin

max.generations

1000

big number is often necessary

project.path

contains "Rotate.txt"

The arguments to genoud that remain at their defaults but you
may want to consider tweaking are pop.size, wait.generations, and
solution.tolerance.

Details

This help page should really only be used as a reminder for what the various
choices are, which are normally indicated by leaving criteria and
methodArgs unspecified and responding to pop-up menus. The vignette provides
a step-by-step guide to the pop-up menus and formally defines the criteria; execute
vignette("FAiR") to read it.

The basic problem is to choose a transformation of the factors that is optimal
with respect to some intersection of criteria. Since the objective function is
vector valued, lexical optimization is performed via a genetic algorithm, which is
tantamount to constrained optimization; see genoud.

The following functions can be named as constraints but must not be the last element of
criteria:

name

methodArgs

reminder of what function does

"no_factor_collapse"

nfc_threshold

to prevent factor collapse

"limit_correlations"

lower and upper

limits factor intercorrelations

"positive_manifold"

pm_threshold

forces “positive” manifold

"ranks_rows_1st"

row_ranks

row-wise ordering constraints

"ranks_cols_1st"

col_ranks

column-wise ordering constraints

"indicators_1st"

indicators

designate which is the best indicator of a factor

"evRF_1st"

none

restrict effective variance of reference factors

"evPF_1st"

none

restrict effective variance of primary factors

"h2_over_FC_1st"

none

communalities >= factor contributions

"no_neg_suppressors_1st"

FC_threshold

no negative suppressors

"gv_1st"

none

generalized variance of primary <= reference factors

"distinguishability_1st"

none

best indicators have no negative suppressors

In fact, "no_factor_collapse" is always included and is listed above only to
emphasize that one must specify methodArgs$nfc_threshold to avoid seeing the
associated pop-up menu. This restriction to avoid factor collapse makes it possible
to utilize one of the following “analytic” criteria that would otherwise
result in factor collapse much of the time. One of the following can be named as the
last element of criteria:

name

methodArgs

"phi"

c

"varphi"

weights

"LS"

eps, scale, and E

"minimaximin"

"geomin"

delta

"quartimin"

"target"

Target

"pst"

Target

"oblimax"

"simplimax"

k

"bentler"

"cf"

kappa

"infomax"

"mccammon"

"oblimin"

gam

The first four are defined only on the reference structure matrix. The remainder are copied
from the GPArotation package and have the same arguments, with the exception of
"pst" which uses NA in the target matrix for untargeted cells rather than
also specifying a weight matrix (which is called W in the GPArotation package).
In addition, one can specify methodArgs$matrix as one of "PP", "RS", or
"FC" to use the primary pattern, reference structure, or factor contribution matrix in
conjunction with the criteria from the GPArotation package, although these criteria
are technically defined with respect to the primary pattern matrix.

Row-standardization should not be necessary. Row-standardization was originally
intended to counteract some tendencies in the transformation process that can
now be accomplished directly through lexical (i.e. constrained) optimization.
Nevertheless, Kaiser normalization divides each row of the preliminary primary
pattern matrix by its length and Cureton-Mulaik normalization favors rows that
are thought to have only one large loading after transformation. Both schemes
are thoroughly discussed in Browne (2001), which also discusses most of the
continuous analytic criteria available in FAiR with the exceptions of
those in Thurstone (1935) and Lorenzo-Seva (2003).

It is not necessary to provide starting values for the parameters. But a matrix of
starting values can be passed to through the dots to genoud.
This matrix should have rows equal to the pop.size argument in
genoud and columns equal the number of factors squared. The columns
correspond to the cells of the transformation matrix in column-major order. In contrast to
some texts, the transformation matrix in Rotate has unit-length columns, rather
than unit-length rows.

Value

An object of FA.EFA-class.

Note

The underlying genetic algorithm will print a variety of output as it progresses.
On Windows, you have to move the scrollbar periodically to flush the output
to the screen. The output will look something like this

Generation

First

Second

...

Last

Analytic

number

constraint

constraint

constraint

criterion

0

-1.0

-1.0

...

-1.0

double

1

-1.0

-1.0

...

-1.0

double

...

...

...

...

...

...

42

-1.0

-1.0

...

-1.0

double

The integer on the very left indicates the generation number. If it appears to
skip one or more generations, that signifies that the best individual in the
“missing” generation was no better than the best individual in the
previous generation. The sequence of negative ones indicates that various
constraints specified by the user are being satisfied by the best individual in
the generation. The curious are referred to the source code and / or the,
vignette, but for the most part users need not worry about them provided they
are -1.0. If any but the last are not -1.0 after the first few
generations, there is a problem because no individual is satisfying all the
constraints. The last number is a double-precision number and is typically the
(logarithm of the) analytic criterion specified by the user. This number will,
decrease, sometimes painfully slowly, sometimes intermittently, over the
generations since the criterion is being minimized subject to the aforementioned
constraints. Finally, do not be particularly concerned if there are messages
indicating a gradient check has failed because there is no strong reason to
expect the gradient of the (last) criterion with respect to all the cells of the
transformation matrix will be particularly small

Author(s)

Ben Goodrich

References

Browne, M.W. (2001) An overview of analytic rotation in exploratory factor analysis.
Multivariate Behavioral Research, 36, 111–150.

Lorenzo-Seva, U. (2003) A factor simplicity index.
Psychometrika, 68, 49–60.

Smith, G. A. and Stanley G. (1983)
Clocking g: relating intelligence and measures of timed
performance. Intelligence, 7, 353–368.

Thurstone, L. L. (1935) The Vectors of Mind.
Cambridge University Press.

Venables, W. N. and Ripley, B. D. (2002)
Modern Applied Statistics with S. Fourth edition. Springer.

See Also

Factanal

Examples

## Example from Venables and Ripley (2002, p. 323)
## Previously from Bartholomew and Knott (1999, p. 68--72)
## Originally from Smith and Stanley (1983)
## Replicated from example(ability.cov)
man <- make_manifest(covmat = ability.cov)
res <- make_restrictions(man, factors = 2, model = "EFA")
efa <- Factanal(manifest = man, restrictions = res, impatient = TRUE)
show(efa); summary(efa)
# 'criteria' and 'methodArgs' would typically be left unspecified
# and equivalent choices would be made from the pop-up menus
efa.rotated <- Rotate(efa, criteria = list("phi"),
methodArgs = list(nfc_threshold = 0.25, c = 1.0))
summary(efa.rotated)
pairs(efa.rotated)
## See the example for Factanal() for more post-estimation commands

Results

R version 3.3.1 (2016-06-21) -- "Bug in Your Hair"
Copyright (C) 2016 The R Foundation for Statistical Computing
Platform: x86_64-pc-linux-gnu (64-bit)
R is free software and comes with ABSOLUTELY NO WARRANTY.
You are welcome to redistribute it under certain conditions.
Type 'license()' or 'licence()' for distribution details.
R is a collaborative project with many contributors.
Type 'contributors()' for more information and
'citation()' on how to cite R or R packages in publications.
Type 'demo()' for some demos, 'help()' for on-line help, or
'help.start()' for an HTML browser interface to help.
Type 'q()' to quit R.
> library(FAiR)
Loading required package: rgenoud
## rgenoud (Version 5.7-12.4, Build Date: 2015-07-19)
## See http://sekhon.berkeley.edu/rgenoud for additional documentation.
## Please cite software as:
## Walter Mebane, Jr. and Jasjeet S. Sekhon. 2011.
## ``Genetic Optimization Using Derivatives: The rgenoud package for R.''
## Journal of Statistical Software, 42(11): 1-26.
##
Loading required package: gWidgetsRGtk2
Loading required package: RGtk2
Loading required package: gWidgets
Loading required package: cairoDevice
Loading required package: stats4
Loading required package: rrcov
Loading required package: robustbase
Scalable Robust Estimators with High Breakdown Point (version 1.3-11)
Loading required package: Matrix
## FAiR Version 0.4-15 Build Date: 2014-02-08
## See http://wiki.r-project.org/rwiki/doku.php?id=packages:cran:fair for more info
FAiR Copyright (C) 2008 -- 2012 Benjamin King Goodrich
This program comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions, namely those specified in the LICENSE file
in the root directory of the source code.
> png(filename="/home/ddbj/snapshot/RGM3/R_CC/result/FAiR/04Rotate.Rd_%03d_medium.png", width=480, height=480)
> ### Name: Rotate
> ### Title: Choose a Transformation in Exploratory Factor Analysis
> ### Aliases: Rotate
> ### Keywords: multivariate models
>
> ### ** Examples
>
> ## Example from Venables and Ripley (2002, p. 323)
> ## Previously from Bartholomew and Knott (1999, p. 68--72)
> ## Originally from Smith and Stanley (1983)
> ## Replicated from example(ability.cov)
>
> man <- make_manifest(covmat = ability.cov)
Warning message:
In FAiR_make_manifest_list(covmat, shrink) :
it is strongly preferable to pass the raw data to make_manifest()
> res <- make_restrictions(man, factors = 2, model = "EFA")
> efa <- Factanal(manifest = man, restrictions = res, impatient = TRUE)
>
> show(efa); summary(efa)
Call:
Factanal(manifest = man, restrictions = res, impatient = TRUE)
Number of observations: 112
Discrepancy: 6.344784
Exploratory factor anaylsis
2 factors
4 degrees of freedom
Call:
Factanal(manifest = man, restrictions = res, impatient = TRUE)
uniqueness
general 0.455
picture 0.589
blocks 0.218
maze 0.769
reading 0.052
vocab 0.334
>
> # 'criteria' and 'methodArgs' would typically be left unspecified
> # and equivalent choices would be made from the pop-up menus
> efa.rotated <- Rotate(efa, criteria = list("phi"),
+ methodArgs = list(nfc_threshold = 0.25, c = 1.0))
Mon Jul 4 17:53:21 2016
Domains:
-1.000000e+00 <= X1 <= 1.000000e+00
-1.000000e+00 <= X2 <= 1.000000e+00
-1.000000e+00 <= X3 <= 1.000000e+00
-1.000000e+00 <= X4 <= 1.000000e+00
Data Type: Floating Point
Operators (code number, name, population)
(1) Cloning........................... 122
(2) Uniform Mutation.................. 125
(3) Boundary Mutation................. 125
(4) Non-Uniform Mutation.............. 125
(5) Polytope Crossover................ 125
(6) Simple Crossover.................. 126
(7) Whole Non-Uniform Mutation........ 125
(8) Heuristic Crossover............... 126
(9) Local-Minimum Crossover........... 0
HARD Maximum Number of Generations: 1000
Maximum Nonchanging Generations: 10
Population size : 1000
Convergence Tolerance: 1.000000e-03
Using the BFGS Derivative Based Optimizer on the Best Individual Each Generation.
Checking Gradients before Stopping.
Not Using Out of Bounds Individuals But Allowing Trespassing.
Minimization Problem.
Generation# Solution Values (lexical)
0 -1.000000e+00 -1.000000e+00 -1.000000e+00 -2.830552e+00
1 -1.000000e+00 -1.000000e+00 -1.000000e+00 -3.823367e+00
2 -1.000000e+00 -1.000000e+00 -1.000000e+00 -3.828375e+00
'wait.generations' limit reached.
No significant improvement in 10 generations.
Solution Lexical Fitness Value:
-1.000000e+00 -1.000000e+00 -1.000000e+00 -3.828876e+00
Parameters at the Solution (parameter, gradient):
X[ 1] : 9.003194e-01 G[ 1] : 7.944467e-07
X[ 2] : 8.337576e-01 G[ 2] : 1.429784e-06
X[ 3] : -3.545071e-01 G[ 3] : 0.000000e+00
X[ 4] : 3.513948e-01 G[ 4] : 0.000000e+00
Solution Found Generation 2
Number of Generations Run 13
Mon Jul 4 17:53:23 2016
Total run time : 0 hours 0 minutes and 2 seconds
Nelder-Mead resulted in no improvement; convergence presumably achieved
> summary(efa.rotated)
Call:
Factanal(manifest = man, restrictions = res, impatient = TRUE)
Point estimates (blanks, if any, are exact zeros):
F1 F2 Uniqueness
general 0.474 0.374 0.455
picture 0.658 -0.035 0.589
blocks 0.913 -0.060 0.218
maze 0.498 -0.036 0.769
reading -0.062 1.003 0.052
vocab 0.034 0.798 0.334
F1 1.000 0.510
F2 0.510 1.000
> pairs(efa.rotated)
> ## See the example for Factanal() for more post-estimation commands
>
>
>
>
>
> dev.off()
null device
1
>