% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/sem.check.R
\name{sem.check}
\alias{sem.check}
\title{Runs lavaan models after checking for code or data changes.}
\usage{
sem.check(
  mods,
  data,
  keys_s = NULL,
  keys_e = NULL,
  fit_save = FALSE,
  fit_measures = "all",
  miss = "ML",
  est = "default",
  std.lv = FALSE,
  std = TRUE,
  orthogonal = FALSE,
  target = NULL,
  name = "sem",
  check = FALSE,
  save_out = FALSE
)
}
\arguments{
\item{mods}{A named list of lavaan models to run.}

\item{data}{A dataframe or object coercible to a dataframe.
Data must include all observed variables used in any of the models.}

\item{keys_s}{A named keys list matching the names and length of mod.}

\item{keys_e}{A named keys list of the factors in an ESEM to be included.}

\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{std.lv}{Logical.
Sets the \code{std.lv} parameter, as per lavaan (see \code{\link[lavaan:lavOptions]{lavaan::lavOptions()}}).
\code{TRUE} indicates that factor variances should be fixed to 1.
\code{FALSE} indicates that loadings of the first items of factors should be fixed
to 1.
Defaults to \code{FALSE}.}

\item{std}{Logical.
\code{TRUE} indicates that standardised parameter estimates should be saved;
\code{FALSE} indicates that unstandardised parameters estimates should be saved.}

\item{orthogonal}{Logical.
Sets the \code{orthogonal} parameter, as per lavaan (see \code{\link[lavaan:lavOptions]{lavaan::lavOptions()}}).
\code{TRUE} indicates that unspecified latent variable correlations should be
fixed at 0;
\code{FALSE} indicates that unspecified latent variable correlations should be
freely estimated.
Defaults to \code{FALSE}.}

\item{target}{A matrix indicating a rotation target,
as used in the \code{rotation.args} argument in lavaan (see \code{\link[lavaan:efa]{lavaan::efa()}}.
If \code{NULL} (default),
target is not specified and lavaan uses default behaviour.
Irrelevant when the model does not include an EFA or ESEM.}

\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 "sem".
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 2 (if \code{fit_save = FALSE}) or
3 (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});
and, if \code{fit_save = TRUE}, a matrix of fit measures for each model.
}
\description{
sem.check takes a model list, keys lists, and data, and
produces outputs from a series of lavaan models.
The function is primarily used as a function to be called by other function
within the package but it can also be run independently.

For each model, the code optionally checks for previously saved model code,
a hash of data, and important parameter inputs.
If they exist and match values for the current code and data,
the model is not run, the previous output is loaded instead.
If either the code has changed, the hash of the data has changed, or
important parameter inputs have change, or any of these do not exist,
then the models are run as normal.
}
\details{
The function is largely intended to be used as a helper function to upstream
functions,
including \code{\link[=cfa.from.keys]{cfa.from.keys()}}, \code{\link[=bifactor.from.keys]{bifactor.from.keys()}}, \code{\link[=efa.from.keys]{efa.from.keys()}}, and
\code{\link[=esem.from.mods]{esem.from.mods()}}.
Although it is recommended to use the appropriate upstream function whenever
possible,
there are not (currently) options to do so when customised lavaan models are
required;
for example, when allowing two items' residuals to correlate in a CFA.
\code{sem.check()} can be used in these cases (see example).

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 or simply use lavaan
without the assistance of semFromKeys.

The function includes functionality designed to save time re-running code
when lots of slow models are included.
To do this, when \code{save_out = TRUE} and a cache directory has been set,
the model will save various inputs and outputs from the function call, and,
when \code{check = TRUE}, the model will look for any previously saved outputs
from earlier model runs in the same cache directory and
only run again if nothing has changed.
In cases where something has changed,
then the function will re-run the models where something has changed
(but it will not for those where nothing has changed).
Changes to arguments that influence all lavaan model runs (e.g., miss or est)
will trigger all models to be re-run.

For either \code{save_out = TRUE} or \code{check = TRUE},
the function will look for a cache directory set and created by the
\code{\link[=cache.setup]{cache.setup()}} function.
If a cache directory has not been set for the current session,
then the function will exit with an error suggesting that either
\code{\link[=cache.setup]{cache.setup()}} be run or \code{save_out} and \code{check} set to \code{FALSE}.

When the cache directory is found and output from previous runs are detected,
the comparisons performed are for:
\itemize{
\item model code;
\item hashes of the data (using \code{\link[openssl:md5]{openssl::md5()}});
\item values of the \code{miss}, \code{est}, \code{std}, \code{std.lv}, and \code{orthogonal}parameters;
\item the class of model objects (i.e., class lavaan); and,
\item the class of parameter estimates (i.e., class lavaan.data.frame).
}

For most applications, the checking feature can be safely ignored by not
saving outputs (i.e., \code{fit_save = FALSE})
and not checking for past saves (i.e., \code{check = FALSE}, both default),
but may be beneficial in cases with lots of models or very slow models.
However, the functionality can be safely used for faster runs too.
}
\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 model code
mods <- mapply(
  x = keys, y = names(keys), SIMPLIFY = FALSE,
  FUN = function(x, y) paste(y, "=~", paste(x, collapse = " + "))
)
# Edit model code to add correlated residuals
mods[[1]] <- paste0(mods[[1]], "\ngrit_c_1 ~~ grit_c_2")
# Estimate the models with sem.check()
cfa_fit <- sem.check(mods, BFIGritHope, keys, name = "cfa", check = FALSE)
}
\seealso{
\code{\link[=cfa.from.keys]{cfa.from.keys()}}, \code{\link[=efa.from.keys]{efa.from.keys()}}, \code{\link[=bifactor.from.keys]{bifactor.from.keys()}}, and
\code{\link[=esem.from.mods]{esem.from.mods()}}---all these function depend upon \code{sem.check()} to work;
\code{\link[lavaan:sem]{lavaan::sem()}}, which is used to estimate the models;
\code{\link[lavaan:parameterEstimates]{lavaan::parameterEstimates()}}, which is used to estimate parameter values;
and \code{\link[lavaan:fitMeasures]{lavaan::fitMeasures()}}, which is used to estimate fit statistics when
\code{fit_save = TRUE}.
}
