% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/sem.cor.R
\name{sem.cor}
\alias{sem.cor}
\title{Creates a latent variable correlation matrix from fitted lavaan measurement
models}
\usage{
sem.cor(
  data,
  fit_y,
  fit_x = NULL,
  items = NULL,
  item_loadings = NULL,
  nagy = TRUE,
  fit_save = FALSE,
  fit_measures = "all",
  miss = "ML",
  est = "default",
  name = "cors",
  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{fit_y}{A named list of CFA fitted objects.}

\item{fit_x}{A named list of CFA fitted objects to be correlated with fit_y variables
or 'NULL'.}

\item{items}{A vector of single-item variables to correlate with 'fit_y' latent variables.
Must not include any items contributing to the measurement of a \code{fit_y}
latent variable.}

\item{item_loadings}{When single items are specified, items are included in models with single
item latent variables. \code{item_loadings} sets the loading of the item on the
factor.
It can be a single number to set all loadings equal or a vector of
length equal to the length of items.
Defaults allows the value to be free (which assumes perfect reliability).
Irrelevant if \code{items = NULL}.}

\item{nagy}{Logical. Indicates whether to use Nagy and colleagues' (2017) extension
procedure instead of Burt's (1976) 2-stage procedure.}

\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 "cors".
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.
The first element is the fitted lavaan models ('fit').
The second element is the correlation matrix ('cor_mat').
The third and fourth elements are the upper and lower confidence intervals
from the models ('ci_lower' and 'ci_upper', respectively).
}
\description{
sem.cor takes CFA outputs and produces a correlation matrix between latent
variables and/or single items.
}
\details{
The function computes correlations between latent variables from fitted CFA
models, including either all latent variables, or between two sets of latent
variables.
To compute a full correlation matrix include all CFA models in a list as
\code{fit_y}, alternatively,
to correlate a set of dependant variables with a set of independent
variables,
set \code{fit_y} as a list of fitted CFA models of dependant variables and
set \code{fit_x} as a list of fitted CFA models of independent variables.
Correlations between the \code{fit_y} latent variables and single items can also
be optionally included by setting \code{items} as a vector of item names.
In this case, items will be treated as single item latent variables with
reliability = \code{item_loadings}.

Each correlation is calculated in a separate model.
This approach saves time for longer lists of variables compared to including
everything in one model and
it also means that excluding a variable cannot change correlations between
other variables (which is possible when all are included together).
The function uses either Burt's 2-stage procedure when \code{nagy = FALSE} or
Nagy and colleagues' (2017) extension procedure when \code{nagy = TRUE}
to control for interpretational confounding (Burt, 1976).

Burt's method works by fixing measurement model parameters in the 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 means that the latent variables interpretation cannot change with the
addition of different variables,
thereby solving interpretational confounding.
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 and fit statistics.

Alternatively, Nagy's method 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 the structural model match those of isolated
measurement models without having to constrain them directly.
As a result, unbiased standard errors are preserved while simultaneously
eliminating interpretational confounding.

Burt's method is faster but artificially constrains parameters,
thereby biasing standard errors and model fit indices.
They should, however, give very similar point estimates for correlations.
Therefore, Nagy's method should be preferred whenever confidence intervals
or model fit matter, except for extremely large sets of variables.

It is possible for latent variable correlations to produce a non-positive
definite correlation matrix between variables included in \code{fit_y},
especially when closely related factors are included.
If the matrix of latent variables is not positive definite,
then the matrix will be adjusted to the nearest positive definite
matrix using the \code{\link[Matrix:nearPD]{Matrix::nearPD()}} function,
which employs the method developed by Higham (2002),
and a message will state that the matrix was adjusted and the maximum
adjustment to any cell.
Confidence intervals will be adjusted by the same amount.

The model relies on \code{\link[=sem.check]{sem.check()}} for the back-end of running the models,
which 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.
In the case of \code{sem.cor()}, the number of correlations can add up quickly,
so the functionality may be useful
(e.g., with 20 scales, there are 19 + 18 + 17 + ... + 1 = 190 correlations).
For further details on how this works, see the \code{\link[=sem.check]{sem.check()}} function
documentation.
}
\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))]
)
# Run CFA models
cfa_fit <- cfa.from.keys(keys, BFIGritHope, check = FALSE, fit_save = FALSE)
# Find correlations between all cfa_fit constructs.
cors <- sem.cor(BFIGritHope, cfa_fit$fit, nagy = FALSE)
# View the correlation matrix
cors$cor_mat

# Correlations of grit facets with hope facets and the first item from each
# Big Five factor.
items <- names(BFIGritHope)[grep("bfi_.*1_1", names(BFIGritHope))]
cors2 <- sem.cor(
  BFIGritHope, cfa_fit$fit[1:2], cfa_fit$fit[3:4], items, nagy = FALSE
)
# View correlations
cors2$cor_mat
}
\references{
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.

Higham, N. J. (2002).
Computing the nearest correlation matrix—a problem from finance.
IMA Journal of Numerical Analysis, 22(3), 329-343.
https://doi.org/10.1093/imanum/22.3.329.

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 \code{sem.cor()} uses for all the back-end;
\code{\link[lavaan:sem]{lavaan::sem()}}, which is used to estimate the models;
\link[matrixcalc:is.positive.definite]{matrixcalc::is.positive.definite}, which is used to assess whether the
correlation matrix between \code{fit_y} constructs is positive definite; and
\code{\link[Matrix:nearPD]{Matrix::nearPD()}} for the function used to transform non-positive definite
matrices into positive definite matrices.
}
