% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/esem.from.mods.R
\name{esem.from.mods}
\alias{esem.from.mods}
\title{Runs ESEM based on CFA and EFA model outputs.}
\usage{
esem.from.mods(
  data,
  efa_fit,
  cfa_fit = NULL,
  bif_fit = NULL,
  fit_save = FALSE,
  fit_measures = "all",
  miss = "ML",
  est = "default",
  name = "esem",
  check = FALSE,
  save_out = FALSE
)
}
\arguments{
\item{data}{A dataframe or object coercible to a dataframe.
Data must include all observed variables used in any of the models.}

\item{efa_fit}{A fitted lavaan object of an EFA model.}

\item{cfa_fit}{A named list of fitted lavaan objects of CFA models.
Can be \code{NULL} if \code{bif_fit} is not \code{NULL}.}

\item{bif_fit}{A named list of fitted lavaan objects of bifactor models.
Can be \code{NULL} if \code{cfa_fit} is not \code{NULL}.}

\item{fit_save}{Logical.
\code{TRUE} indicates model fit measures should be included in the output;
\code{FALSE} indicates model fit measures should not be included in the output.
\code{FALSE} may be desirable when fit measures are of little interest and when
they may take a long time to estimate.
Fit can still be examined for individual models with,
\verb{lavaan::fitMeasures(fit$fit$[model name])}.}

\item{fit_measures}{A vector of fit measures to save or 'all' to select all fit measures,
as per the \code{fit.measures} parameter from lavaan's \code{\link[lavaan:fitMeasures]{lavaan::fitMeasures()}}
function.
Defaults to 'all'. Irrelevant if \code{fit_save = FALSE}.}

\item{miss}{A string.
Sets the \code{missing} parameter, as per lavaan (see \code{\link[lavaan:lavOptions]{lavaan::lavOptions()}}).
Defaults to 'ML'.}

\item{est}{A string.
Sets the \code{estimator} parameter, as per lavaan (see \code{\link[lavaan:lavOptions]{lavaan::lavOptions()}}).
The default ('default') uses the lavaan default for the model being run.}

\item{name}{A string indicating a subdirectory where model outputs will be saved when
\code{save_out = TRUE} and checked against when \code{check = TRUE}.
Defaults to "esem".
Irrelevant if both \code{save_out = FALSE} and \code{check = FALSE}.
The name should be unique for each set of models, or outputs from calls with
the same name will be overwritten.}

\item{check}{Logical.
\code{TRUE} indicates that current inputs should be compared to previous inputs
if they exist and that the model should not be rerun if nothing has changed;
\code{FALSE} indicates that these checks should not be made and the model should
be run regardless of the existence of previous inputs.}

\item{save_out}{Logical.
\code{TRUE} indicates that model code, a hash of the data, important input
parameter values, and output will be saved;
\code{FALSE} indicates that nothing will be saved.
Selecting \code{save_out = TRUE} enables the function to not rerun models next
time if \code{check = TRUE} the next time the code is run and nothing has changed
in the meantime.}
}
\value{
Returns a list of length 4 (if \code{fit_save = FALSE}) or
5 (if \code{fit_save = TRUE}).
The elements of the list are: a list of lavaan model output objects;
a list of parameter estimates from the models (standardized if \code{std = TRUE});
if \code{fit_save = TRUE}, a matrix of fit measures for each model;
a list of regression beta parameters from each model;
and a dataframe of R-squared values from each model.
}
\description{
\code{esem.from.keys} runs exploratory structural equation models (ESEM) in lavaan
where the exploratory factor analysis (EFA) factors predict confirmatory
factor analysis (CFA) factors and/or bifactor factors in separate models
for each CFA or bifactor model.
The function takes a fitted lavaan object from an EFA and lists of fitted
CFA and/or bifactor lavaan model objects as inputs so will typically
use outputs from \code{\link[=efa.from.keys]{efa.from.keys()}}, and \code{\link[=cfa.from.keys]{cfa.from.keys()}} or
\code{\link[=bifactor.from.keys]{bifactor.from.keys()}}.
}
\details{
The function was designed to streamline running exploratory structural
equation models (ESEM) where EFA factors predict a series of latent variables
in separate models using Burt's (1976) 2-stage procedure to prevent
interpretational confounding. The function is designed to run analyses
equivalent to that of Bainbridge, Ludeke, and Smillie (2022).

The function requires fitted lavaan objects as inputs in order to properly
employ the 2-stage procedure.
Using \code{\link[=efa.from.keys]{efa.from.keys()}}, \code{\link[=cfa.from.keys]{cfa.from.keys()}}, and/or \code{\link[=bifactor.from.keys]{bifactor.from.keys()}}
should make this relatively straight-forward.

Matching the philosophy of the package, the function is designed to run for
multiple models with a similar design. If you are using the function for a
single model, transform inputs into lists as appropriate.

The model relies on \code{\link[=sem.check]{sem.check()}} for the back-end of running the models.
This enables saving inputs and outputs from model runs
(with \code{save_out = TRUE}) and checking to see if anything has changed from
prior runs before running again (with \code{check = TRUE}).
The functionality was included for a number of very slow models or a lot of
faster models, such that time spent rerunning them would be onerous.
For further details on how this works, see the \code{\link[=sem.check]{sem.check()}} function
documentation.

Although the function will take any lavaan models that have successfully
produced standard lavaan outputs,
it will not complain if these have poor fit or other undesirable
characteristics (beyond warnings and errors produced by lavaan).
If this matters to you, it would be worth checking the outputs of upstream
functions prior to running \code{esem.from.mods()}.

There is some disagreement about how to deal with interpretational
confounding.
The standard solution (other than ignoring it) is to create good fitting
measurement models first, then freely estimate the structural model with
checks to ensure adequate fit of the model and
that interpretational confounding is not an issue.
A problem with this is that changes to measurement models can require
entirely different factors (e.g., where original authors suggested a 4-factor
scale and subsequent analyses suggest a 2-factor scale) or items to be
removed.
How ought one to assess whether the scale measures the same thing(s) with
different factors or omitted items?
When a single scale is being assessed, these issues can be resolved;
however, when many scales are being assessed this solution is impractical.

An alternative solution is to fix measurement model parameters in a model
estimating structural parameters.
This method means that less than ideal fit at the measurement level does not
propagate though the model as the measurement parameters are fixed.
It also solves interpretational confounding because the measurement of the
latent variables is fixed so their interpretation cannot change with the
inclusion of other variables in a model.
However, it is not a perfect solution because it underestimates uncertainty
in the measurement part of the structural model (e.g., Nagy et al., 2017),
which results in biased standard errors.

A final option (among those noted here) was proposed by
Nagy and colleagues (2017).
It involves allowing item residuals to correlate with external variables
(or factors) and constrains those relationships such that the model is
identifiable.
If the sums of squares of correlations between all combinations of factors'
items and external factors are minimised,
measurement parameters in isolated measurement models are preserved in the
structural model without having to constrain them directly.
As a result, unbiased standard errors are preserved while simultaneously
eliminating interpretational confounding.
Unfortunately, estimating these models becomes increasingly slow with more
items and factors, such that it quickly becomes untenable,
especially for ESEM and when many models have to be run.

As a result of these considerations, the 2-stage procedure of fixing
measurement parameters in the structural models was chosen for the current
function due to its simplicity and scalability.

A further complication occurs for bifactor models.
Recall that bifactor models require orthogonal relationships between the
general and group factors.
When a factor is an outcome of a regression in a structural model,
it is not possible to include such a constraint because the instructions
normally used to do so will constrain residual variance instead.

There are three solutions to this problem.
First, avoid using bifactor models.
This may be possible in some cases (e.g., if the scale can be modified into
a unidimentional scale), but frequently it is not.
Second, avoid using regressions in models with bifactor models and compute
regressions based on latent variable correlations.
(This can be done by, e.g., creating a correlation matrix from the factor
correlations and using the \code{\link[psych:setCor]{psych::setCor()}} function).
This method produces accurate point estimates in the regressions,
but standard errors are biased as the method cannot account for uncertainty
in the correlations.
Finally, if the 2-stage procedure is employed, then there is little room for
measurement models to change to allow factor correlations to change.
Therefore, the parameter can be relaxed and implied correlations between the
group and general factors should remain close to zero.
Given that the function already uses the 2-stage procedure,
this method is employed when bifactor models are used in \code{esem.from.mods()}.
}
\examples{
# Create CFA keys
keys0 <- c("grit_c", "grit_p", "hope_a", "hope_p")
keys <- sapply(
  keys0, function(x) names(BFIGritHope)[grep(x, names(BFIGritHope))]
)
# Create EFA keys
# Using only 3 factors and fewer items to save time for a simple example
# (This results in a less than ideal solution but it doesn't matter for an
# example)
keys_e0 <- paste0("bfi_", c("e", "a", "c"))
keys_e <- sapply(
  keys_e0,
  function(x) {
    names(BFIGritHope)[grep(paste0(x, "\\\\d_[1-2]"), names(BFIGritHope))]
  },
  simplify = FALSE
)
# Create fitted objects to use as inputs
cfa_fit <- cfa.from.keys(keys, BFIGritHope, fit_save = FALSE)
efa_fit <- efa.from.keys(keys_e, BFIGritHope, fit_save = FALSE)
# Run models
esem_fit <- esem.from.mods(
  efa_fit$fit$efa, cfa_fit$fit, data = BFIGritHope,
  fit_save = FALSE, check = FALSE
)
# Examine results
summary(esem_fit$fit$grit_c)  # Standard lavaan summary
esem_fit$r2                   # R-squareds
esem_fit$b                    # Betas
}
\references{
Bainbridge, T. F., Ludeke, S. G., & Smillie, L. D. (2022).
Evaluating the Big Five as an organizing framework for commonly used
psychological trait scales.
Journal of Personality and Social Psychology, 122(4), 749-777.
https://doi.org/10.1037/pspp0000395.

Burt, R. S. (1976).
Interpretational confounding of unobserved variables in Structural Equation
Models. Sociological Methods & Research, 5(1), 3-52.
https://doi.org/10.1177/004912417600500101.

Eid, M., Geiser, C., Koch, T., & Heene, M. (2017).
Anomalous results in G-factor models: Explanations and alternatives.
Psychological Methods, 22(3), 541-562.
https://doi.org/10.1037/met0000083.

Nagy, G., Brunner, M., Lüdtke, O., and Greiff, S. (2017).
Extension Procedures for Confirmatory Factor Analysis.
Journal of Experimental Education, 85(4).
https://doi.org/10.1080/00220973.2016.1260524.
}
\seealso{
\code{\link[=sem.check]{sem.check()}}, which this function uses for all the back-end;
\code{\link[=cfa.from.keys]{cfa.from.keys()}}, \code{\link[=efa.from.keys]{efa.from.keys()}}, and \code{\link[=bifactor.from.keys]{bifactor.from.keys()}},
which are useful functions for creating inputs into \code{esem.from.mods()}; and
\code{\link[lavaan:sem]{lavaan::sem()}}, which is used to estimate the models.
}
