Skip to content

Commit 092f6e0

Browse files
authored
support lavaan.mi models (#1188)
* support `lavaan.mi` models Fixes #1187 * fix * fixes * fix * fix * minor
1 parent f200a1b commit 092f6e0

7 files changed

Lines changed: 286 additions & 52 deletions

File tree

DESCRIPTION

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Type: Package
22
Package: parameters
33
Title: Processing of Model Parameters
4-
Version: 0.28.3
4+
Version: 0.28.3.1
55
Authors@R:
66
c(person(given = "Daniel",
77
family = "Lüdecke",
@@ -148,6 +148,7 @@ Suggests:
148148
ivreg,
149149
knitr,
150150
lavaan,
151+
lavaan.mi,
151152
lcmm,
152153
lfe,
153154
lm.beta,

NAMESPACE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,7 @@ S3method(model_parameters,ivFixed)
278278
S3method(model_parameters,ivprobit)
279279
S3method(model_parameters,kmeans)
280280
S3method(model_parameters,lavaan)
281+
S3method(model_parameters,lavaan.mi)
281282
S3method(model_parameters,lcmm)
282283
S3method(model_parameters,list)
283284
S3method(model_parameters,lm_robust)

R/methods_lavaan.R

Lines changed: 29 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,21 @@
11
# Packages lavaan, blavaan
22

3-
43
# model parameters ---------------------------
54

65
#' @rdname model_parameters.principal
76
#' @export
8-
model_parameters.lavaan <- function(model,
9-
ci = 0.95,
10-
standardize = FALSE,
11-
component = c("regression", "correlation", "loading", "defined"),
12-
keep = NULL,
13-
drop = NULL,
14-
verbose = TRUE,
15-
...) {
16-
params <- .extract_parameters_lavaan(model,
7+
model_parameters.lavaan <- function(
8+
model,
9+
ci = 0.95,
10+
standardize = FALSE,
11+
component = c("regression", "correlation", "loading", "defined"),
12+
keep = NULL,
13+
drop = NULL,
14+
verbose = TRUE,
15+
...
16+
) {
17+
params <- .extract_parameters_lavaan(
18+
model,
1719
ci = ci,
1820
standardize = standardize,
1921
keep_parameters = keep,
@@ -37,21 +39,23 @@ model_parameters.lavaan <- function(model,
3739

3840

3941
#' @export
40-
model_parameters.blavaan <- function(model,
41-
centrality = "median",
42-
dispersion = FALSE,
43-
ci = 0.95,
44-
ci_method = "eti",
45-
test = "pd",
46-
rope_range = "default",
47-
rope_ci = 0.95,
48-
diagnostic = c("ESS", "Rhat"),
49-
component = "all",
50-
standardize = NULL,
51-
keep = NULL,
52-
drop = NULL,
53-
verbose = TRUE,
54-
...) {
42+
model_parameters.blavaan <- function(
43+
model,
44+
centrality = "median",
45+
dispersion = FALSE,
46+
ci = 0.95,
47+
ci_method = "eti",
48+
test = "pd",
49+
rope_range = "default",
50+
rope_ci = 0.95,
51+
diagnostic = c("ESS", "Rhat"),
52+
component = "all",
53+
standardize = NULL,
54+
keep = NULL,
55+
drop = NULL,
56+
verbose = TRUE,
57+
...
58+
) {
5559
# Processing
5660
params <- .extract_parameters_bayesian(
5761
model,
@@ -95,7 +99,6 @@ model_parameters.blavaan <- function(model,
9599

96100
# ci ---------------------------
97101

98-
99102
#' @export
100103
ci.lavaan <- function(x, ci = 0.95, ...) {
101104
out <- .extract_parameters_lavaan(model = x, ci = ci, ...)
@@ -106,7 +109,6 @@ ci.lavaan <- function(x, ci = 0.95, ...) {
106109

107110
# SE ---------------------------
108111

109-
110112
#' @export
111113
standard_error.lavaan <- function(model, ...) {
112114
out <- .extract_parameters_lavaan(model, ...)
@@ -127,7 +129,6 @@ standard_error.blavaan <- function(model, ...) {
127129

128130
# p-value ---------------------------
129131

130-
131132
#' @export
132133
p_value.lavaan <- function(model, ...) {
133134
out <- .extract_parameters_lavaan(model, ...)

R/methods_lavaan.mi.R

Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
#' @export
2+
model_parameters.lavaan.mi <- function(
3+
model,
4+
ci = 0.95,
5+
standardize = FALSE,
6+
component = c("regression", "correlation", "loading", "defined"),
7+
keep_parameters = NULL,
8+
drop_parameters = NULL,
9+
verbose = TRUE,
10+
...
11+
) {
12+
params <- .extract_parameters_lavaan_mi(
13+
model,
14+
ci = ci,
15+
standardize = standardize,
16+
keep_parameters = keep_parameters,
17+
drop_parameters = drop_parameters,
18+
verbose = verbose,
19+
...
20+
)
21+
22+
# Filter
23+
if (all(component == "all")) {
24+
component <- c("regression", "correlation", "loading", "variance", "defined", "mean")
25+
}
26+
params <- params[tolower(params$Component) %in% component, ]
27+
28+
# add class-attribute for printing
29+
class(params) <- c("parameters_sem", "see_parameters_sem", class(params))
30+
attr(params, "ci") <- ci
31+
attr(params, "model") <- model
32+
params
33+
}
34+
35+
36+
.extract_parameters_lavaan_mi <- function(
37+
model,
38+
ci = 0.95,
39+
standardize = FALSE,
40+
keep_parameters = NULL,
41+
drop_parameters = NULL,
42+
verbose = TRUE,
43+
...
44+
) {
45+
insight::check_if_installed("lavaan.mi")
46+
47+
if (is.null(ci)) {
48+
ci <- 0.95
49+
}
50+
51+
# set proper default
52+
if (is.null(standardize)) {
53+
standardize <- FALSE
54+
}
55+
56+
# check for valid parameters
57+
valid_std_options <- c("all", "std.all", "latent", "std.lv", "no_exogenous", "std.nox")
58+
if (!is.logical(standardize) && !(standardize %in% valid_std_options)) {
59+
if (verbose) {
60+
insight::format_alert(
61+
"`standardize` should be one of `TRUE`, \"all\", \"std.all\", \"latent\", \"std.lv\", \"no_exogenous\" or \"std.nox\".", # nolint
62+
"Returning unstandardized solution."
63+
)
64+
}
65+
standardize <- FALSE
66+
}
67+
68+
# CI
69+
if (length(ci) > 1L) {
70+
ci <- ci[1]
71+
if (verbose) {
72+
insight::format_alert(paste0(
73+
"lavaan models only accept one level of CI. Keeping the first one: `ci = ",
74+
ci,
75+
"`."
76+
))
77+
}
78+
}
79+
80+
# collect dots
81+
dot_args <- list(...)
82+
83+
# list all argument names from the `lavaan` function
84+
# fmt: skip
85+
dot_args <- dot_args[names(dot_args) %in% c(
86+
"zstat", "pvalue", "standardized", "fmi", "level", "boot.ci.type", "cov.std",
87+
"fmi.options", "rsquare", "remove.system.eq", "remove.eq", "remove.ineq",
88+
"remove.def", "remove.nonfree", "add.attributes", "output", "header"
89+
)]
90+
91+
# Get estimates
92+
sem_data <- do.call(
93+
lavaan.mi::parameterEstimates.mi,
94+
c(list(object = model, se = TRUE, ci = TRUE, level = ci), dot_args)
95+
)
96+
97+
label <- sem_data$label
98+
99+
# check if standardized estimates are requested, and if so, which type
100+
if (isTRUE(standardize) || !is.logical(standardize)) {
101+
if (is.logical(standardize)) {
102+
standardize <- "all"
103+
}
104+
105+
type <- switch(
106+
standardize,
107+
all = ,
108+
std.all = "std.all",
109+
latent = ,
110+
std.lv = "std.lv",
111+
no_exogenous = ,
112+
std.nox = "std.nox",
113+
"std.all"
114+
)
115+
116+
# this function errors on unknown arguments
117+
f <- utils::getFromNamespace("standardizedSolution.mi", "lavaan.mi")
118+
valid <- names(formals(f))
119+
dots <- list(...)
120+
dots <- dots[names(dots) %in% valid]
121+
fun_args <- c(list(model, se = TRUE, level = ci, type = type), dots)
122+
sem_data <- do.call(f, fun_args)
123+
names(sem_data)[names(sem_data) == "est.std"] <- "est"
124+
}
125+
126+
# extract statistic column - different to normal lavaan objects
127+
if (!is.null(sem_data$t)) {
128+
statistic <- sem_data$t
129+
stat_col <- "t"
130+
} else if (!is.null(sem_data$z)) {
131+
statistic <- sem_data$z
132+
stat_col <- "z"
133+
} else {
134+
statistic <- NULL
135+
}
136+
137+
params <- data.frame(
138+
To = sem_data$lhs,
139+
Operator = sem_data$op,
140+
From = sem_data$rhs,
141+
Coefficient = sem_data$est,
142+
SE = sem_data$se,
143+
CI_low = sem_data$ci.lower,
144+
CI_high = sem_data$ci.upper,
145+
stringsAsFactors = FALSE
146+
)
147+
148+
if (!is.null(statistic)) {
149+
params[[stat_col]] <- statistic
150+
}
151+
152+
params$p <- sem_data$pvalue
153+
154+
if (!is.null(label)) {
155+
params$Label <- label
156+
}
157+
158+
params$Component <- NA_character_
159+
params$Component[params$Operator == "=~"] <- "Loading"
160+
params$Component[params$Operator == "~"] <- "Regression"
161+
params$Component[params$Operator == "~~"] <- "Correlation"
162+
params$Component[params$Operator == ":="] <- "Defined"
163+
params$Component[params$Operator == "~1"] <- "Mean"
164+
165+
params$Component[as.character(params$From) == as.character(params$To)] <- "Variance"
166+
167+
if ("p" %in% colnames(params)) {
168+
params$p[is.na(params$p)] <- 0
169+
}
170+
171+
if ("group" %in% names(sem_data)) {
172+
params$Group <- sem_data$group
173+
}
174+
175+
# filter parameters, if requested
176+
if (!is.null(keep_parameters) || !is.null(drop_parameters)) {
177+
params <- .filter_parameters(
178+
params,
179+
keep = keep_parameters,
180+
drop = drop_parameters,
181+
verbose = verbose
182+
)
183+
}
184+
185+
params
186+
}

0 commit comments

Comments
 (0)