Nothing
#' Extract Parameters from Lavaan Models
#'
#' This function extracts parameters (loadings, variances, etc.) from a lavaan model.
#' P-values are formatted appropriately (e.g., <0.001 for very small values).
#'
#' @param model A fitted lavaan model.
#' @param type Type of parameters to extract: "loadings", "variances", or "all". Default is "loadings".
#' @param standardized Logical; if TRUE, returns standardized estimates. Default is FALSE.
#' @param digits Number of decimal places for p-value formatting (default=3)
#' @param ... Additional arguments passed to \code{lavaan::parameterEstimates} or \code{lavaan::standardizedSolution}.
#'
#' @return A data frame containing the extracted parameters with formatted p-values.
#' @export
#'
#' @examples
#' \donttest{
#' library(lavaan)
#' model <- 'F1 =~ x1 + x2 + x3'
#' fit <- cfa(model, data = HolzingerSwineford1939)
#' extract_latent_parameters(fit, type = "loadings")
#' }
extract_latent_parameters <- function(model, type = "loadings",
standardized = FALSE, digits = 3, ...) {
if (!inherits(model, "lavaan")) {
stop("Model must be a lavaan object")
}
if (!type %in% c("loadings", "variances", "all")) {
stop("type must be one of: 'loadings', 'variances', 'all'")
}
# Internal helper function for p-value formatting
.format_pvalues <- function(pvals, digits = 3) {
sapply(pvals, function(p) {
if (is.na(p) || is.null(p)) return(NA)
if (p < 10^(-digits)) {
return(paste0("<0.", paste(rep("0", digits-1), collapse=""), "1"))
}
return(format(round(p, digits), nsmall = digits))
})
}
# Get parameters based on standardization request
if (standardized) {
params <- tryCatch({
lavaan::standardizedSolution(model, ...)
}, error = function(e) {
warning("Could not get standardized solution: ", e$message)
# Fall back to parameterEstimates
lavaan::parameterEstimates(model, ...)
})
# Check what columns we have and ensure we have what we need
col_names <- colnames(params)
# Determine which column to use as the estimate
if ("std.all" %in% col_names) {
# Create an 'est' column from std.all for backward compatibility
params$est <- params$std.all
} else if ("est.std" %in% col_names) {
# Some lavaan versions use est.std
params$est <- params$est.std
if (!"std.all" %in% col_names) {
params$std.all <- params$est.std
}
} else if ("est" %in% col_names) {
# Already has est, check if we need std.all
if (!"std.all" %in% col_names) {
params$std.all <- params$est
}
} else {
# No estimate column found
warning("Standardized solution does not contain expected columns. Using 'est' from parameterEstimates.")
params <- lavaan::parameterEstimates(model, ...)
params$std.all <- params$est
}
} else {
# Unstandardized parameters
params <- lavaan::parameterEstimates(model, ...)
}
# Format p-values if they exist
if ("pvalue" %in% colnames(params)) {
params$pvalue <- .format_pvalues(params$pvalue, digits = digits)
}
# Extract based on type
if (type == "loadings") {
result <- params[params$op == "=~", ]
} else if (type == "variances") {
# Variances are covariances with same lhs and rhs
result <- params[params$op == "~~" & params$lhs == params$rhs, ]
} else if (type == "all") {
result <- params
}
# Ensure we have at least an 'est' column
if (!"est" %in% colnames(result) && "std.all" %in% colnames(result)) {
result$est <- result$std.all
}
# Reorder columns for better readability
preferred_order <- c("lhs", "op", "rhs", "est", "se", "z", "pvalue",
"ci.lower", "ci.upper", "std.all")
existing_cols <- colnames(result)
ordered_cols <- c()
for (col in preferred_order) {
if (col %in% existing_cols) {
ordered_cols <- c(ordered_cols, col)
existing_cols <- setdiff(existing_cols, col)
}
}
# Add any remaining columns
if (length(existing_cols) > 0) {
ordered_cols <- c(ordered_cols, existing_cols)
}
result <- result[, ordered_cols]
# Reset row names
rownames(result) <- NULL
return(result)
}
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.