% Generated by roxygen2: do not edit by hand
% Please edit documentation in R/lav_cv.R
\name{lav_cv}
\alias{lav_cv}
\alias{print.lav_cv}
\alias{summary.lav_cv}
\title{Repeated holdout (Monte Carlo) cross-validation of \eqn{R^2} for structural equation models ('lavaan' objects)}
\usage{
lav_cv(
  fit,
  data = NULL,
  times = "auto",
  train_prop = 0.8,
  seed = 42L,
  quiet = TRUE,
  digits = 3L,
  plot = TRUE,
  tol = 0.001,
  window = 50L,
  max_times = 3000L,
  min_r2_for_pct = 0.05
)

\method{print}{lav_cv}(x, digits = x$digits \%||\% 3L, ...)

\method{summary}{lav_cv}(object, ...)
}
\arguments{
\item{fit}{A fitted 'lavaan' object (required).}

\item{data}{The data frame used to fit the model; if NULL, it is extracted from 'fit' when available (default: NULL).}

\item{times}{Integer indicating the number of random splits, or "auto" for stabilization-based early stopping (default: "auto").}

\item{train_prop}{Numeric in (0,1). Proportion of cases in the training split for each repetition (default: 0.8).}

\item{seed}{Integer. Random seed for reproducibility of the splits (default: 42).}

\item{quiet}{Logical. Suppress 'lavaan' refit messages when TRUE (default: TRUE).}

\item{digits}{Integer. Number of digits to print in summaries (default: 3).}

\item{plot}{Logical. Show convergence plots of the running mean \eqn{R^2} per outcome (default: TRUE).}

\item{tol}{Numeric. Tolerance for the auto-stop rule on the running mean (default: 0.001).}

\item{window}{Integer. Trailing window size (number of successful splits) used by the auto-stop rule (default: 50).}

\item{max_times}{Integer. Maximum number of splits when \code{times} = "auto" (default: 3000).}

\item{min_r2_for_pct}{Numeric in (0,1). Minimum in-sample \eqn{R^2} required to compute percent drop; below this, \%_drop is set to NA (default: 0.05).}

\item{x}{A 'lav_cv' object.}

\item{...}{Additional arguments; unused.}

\item{object}{A 'lav_cv' object.}
}
\value{
A list with class 'lav_cv' and elements:
\describe{
  \item{\code{table}}{Data frame with columns:
    \code{outcome}, \code{type} ("observed" or "latent"),
    \code{r2_in}, \code{r2_cv_mean}, \code{r2_cv_median}, \code{r2_cv_sd},
    \code{drop_mean_pct}, \code{drop_med_pct}, \code{splits_used}.}
  \item{\code{split_matrix}}{Matrix of split-wise test-set \eqn{R^2} values (rows = splits, columns = outcomes).}
  \item{\code{times}}{Character or integer indicating the number of splits used (e.g., \code{"auto(534)"} or \code{500}).}
  \item{\code{train_prop}}{Numeric. Training proportion used in each split.}
  \item{\code{N}}{Integer. Number of rows in the input data.}
  \item{\code{seed}}{Integer. Random seed used to generate the splits.}
  \item{\code{tol}}{Numeric. Tolerance used by the auto-stop rule.}
  \item{\code{window}}{Integer. Trailing window size for the auto-stop rule.}
  \item{\code{min_r2_for_pct}}{Numeric. Minimum in-sample \eqn{R^2} required to compute percent drop.}
  \item{\code{call}}{\code{match.call()} of the function call.}
  \item{\code{digits}}{Integer. Default number of digits for printing.}
}
}
\description{
Estimate out-of-sample predictive performance for structural relations in a
fitted 'lavaan' model using repeated holdout (Monte Carlo cross-validation,
leave-group-out CV). At each repetition, the model is refitted on a random
training subset and evaluated on a disjoint test subset.
}
\details{
For observed outcomes, \eqn{R^2} is computed by comparing test-set observed values
with predictions obtained by applying the training-set structural coefficients
to the test-set predictors.

For latent outcomes, the outcome is not directly observed in the test set.
Factor scores for the outcome are first computed in the test set using the
measurement model learned on the training set; these scores serve as the
outcome values. Predictions are then formed by applying the training-set
structural coefficients to the test-set predictors (including factor scores
for any latent predictors). \eqn{R^2} is computed by comparing the test-set factor
scores of the outcome with these predicted scores.

The in-sample baseline \eqn{R^2} is computed on the full dataset using the same
metric as in cross-validation: observed outcomes use observed-versus-predicted
\eqn{R^2}; latent outcomes use score-versus-predicted-score R^2.

By default, repetitions continue until the running mean \eqn{R^2} for each outcome
stabilizes within a specified tolerance over a trailing window of successful
splits, or until a maximum number of splits is reached.

The summary table reports the in-sample baseline \eqn{R^2}, the median cross-validated
\eqn{R^2}, its standard deviation, and the percent drop (baseline vs. median CV) with
heuristic threshold markers. The percent drop is suppressed when the in-sample
\eqn{R^2} is very small.
}
\examples{
set.seed(42)
model <- "
ind60 =~ x1 + x2 + x3
dem60 =~ y1 + y2 + y3 + y4
dem65 =~ y5 + y6 + y7 + y8

dem60 ~ ind60
dem65 ~ ind60 + dem60

y1 ~~ y5
y2 ~~ y6
"
fit <- lavaan::sem(
model = model, 
data = lavaan::PoliticalDemocracy,
std.lv = TRUE, 
estimator = "MLR", 
meanstructure = TRUE)
result <- lav_cv(
fit = fit, 
data = lavaan::PoliticalDemocracy, 
times = 5)
print(result)

}
\references{
Cudeck, R., & Browne, M. W. (1983). Cross-validation of covariance
structures. \emph{Multivariate Behavioral Research}, \emph{18}(2), 147-167.
\doi{10.1207/s15327906mbr1802_2}

Hastie, T., Tibshirani, R., & Friedman, J. (2001). \emph{The elements of
statistical learning: Data mining, inference, and prediction}. Springer.
\doi{10.1007/978-0-387-21606-5}

Kvålseth, T. O. (1985). Cautionary note about \eqn{R^2}.
\emph{The American Statistician}, \emph{39}(4), 279-285.
\doi{10.1080/00031305.1985.10479448}

Shmueli, G. (2010). To explain or to predict?
\emph{Statistical Science}, \emph{25}(3), 289-310.
\doi{10.1214/10-STS330}

Yarkoni, T., & Westfall, J. (2017). Choosing prediction over explanation in
psychology: Lessons from machine learning. \emph{Perspectives on
Psychological Science}, \emph{12}(6), 1100-1122.
\doi{10.1177/1745691617693393}
}
\seealso{
\code{\link[lavaan]{sem}}, \code{\link[lavaan]{lavPredict}},
  \code{\link[lavaan]{inspect}}
}
