| Title: | Equivalent Models in Structural Equation Models |
| Version: | 0.1.0 |
| Description: | For identifying the sets of empirically equivalent models for structural equation models fitted by the 'lavaan' package developed by Rosseel (2012) <doi:10.18637/jss.v048.i02>. |
| License: | GPL (≥ 3) |
| Encoding: | UTF-8 |
| Suggests: | knitr, rmarkdown, testthat (≥ 3.0.0), dagitty |
| Config/testthat/edition: | 3 |
| Config/testthat/parallel: | true |
| Imports: | lavaan (≥ 0.7.2), modelbpp (≥ 0.4.0), digest, manymome (≥ 0.3.7), igraph, semPlot, semptools (≥ 0.4.0), RColorBrewer, cli |
| Depends: | R (≥ 4.1.0) |
| URL: | https://sfcheung.github.io/semeqmodels/ |
| LazyData: | true |
| Config/roxygen2/version: | 8.1.0 |
| VignetteBuilder: | knitr |
| NeedsCompilation: | no |
| Packaged: | 2026-09-13 04:52:57 UTC; shufa |
| Author: | Shu Fai Cheung |
| Maintainer: | Shu Fai Cheung <shufai.cheung@gmail.com> |
| Repository: | CRAN |
| Date/Publication: | 2026-09-23 03:50:02 UTC |
semeqmodels: Equivalent Models in Structural Equation Models
Description
For identifying the sets of empirically equivalent models for structural equation models fitted by the 'lavaan' package developed by Rosseel (2012) doi:10.18637/jss.v048.i02.
Author(s)
Maintainer: Shu Fai Cheung shufai.cheung@gmail.com (ORCID)
Authors:
Shu Fai Cheung shufai.cheung@gmail.com (ORCID)
Borui Yang (ORCID)
Wenting Xu (ORCID)
Wendie Yang (ORCID)
See Also
Useful links:
Make a Covariance a Curve
Description
Identify covariances
in a qgraph object and set
their curve values.
Usage
auto_curve_covariance(qgraph_obj, base_curve = 3)
Arguments
qgraph_obj |
A qgraph object. |
base_curve |
The curve value used
to make a line a curve. The same value
used by the argument |
Details
This function can be used to automatically identify covariances in a model, which are represented by bidirectional edges, and set each of the line as a curve.
Value
An object of the same class
as the qgraph_obj, with lines of
covariances set to curves, if any.
Examples
library(lavaan)
# Model 1
mod1 <-
"
fx =~ x1 + x2 + x3
fm =~ m1 + m2 + m3
fy =~ y1 + y2 + y3
fm ~ fx
fy ~ fm + fx
"
fit1 <- sem(
model = mod1,
data = data_test_3_factor_3_item
)
fit1_1_more <- drop_k(fit1)
fit1_1_more_1_less <- lapply(
fit1_1_more,
add_k
)
partables1 <- combine_partables(fit1_1_more_1_less)
eq_out_1 <- eq_models(
partables1,
original_model = fit1,
parallel = FALSE
)
eq_out_1 <- eq_models(
partables1,
original_model = fit1,
parallel = FALSE
)
layout_i <- matrix(c( NA, "fm", NA,
"fx", NA, "fy"),
ncol = 3,
nrow = 2,
byrow = TRUE)
layout_i
p <- partables_plots(
eq_out_1,
original_model = fit1,
layout = layout_i,
label.cex = 1.5,
sizeLat = 15,
edge.width = 5,
asize = 5,
structural = TRUE,
par_diff_settings = list(
color = "blue",
width = 10
)
)
plot(
p,
ncol = 3,
nrow = 2
)
# Process the covariances
p2 <- p %p>% auto_curve_covariance()
plot(
p2,
ncol = 3,
nrow = 2
)
Test Dataset: 3-Factor-3-Item
Description
A dataset for testing.
Usage
data_test_3_factor_3_item
Format
A data frame with 200 rows and 3 variables:
- x1
Numeric.
- x2
Numeric.
- x3
Numeric.
- m1
Numeric.
- m2
Numeric.
- m3
Numeric.
- y1
Numeric.
- y2
Numeric.
- y3
Numeric.
Examples
library(lavaan)
data(data_test_3_factor_3_item)
mod <-
"
fx =~ x1 + x2 + x3
fm =~ m1 + m2 + m3
fy =~ y1 + y2 + y3
"
fit <- sem(mod, data_test_3_factor_3_item)
parameterEstimates(fit)
Test Dataset: 3 Observed Variables
Description
A dataset for testing.
Usage
data_test_3obvs
Format
A data frame with 200 rows and 3 variables:
- fx
Numeric.
- fm
Numeric.
- fy
Numeric.
Examples
library(lavaan)
data(data_test_3obvs)
mod <-
"
fm ~ fx
fy ~ fm + fx
"
fit <- sem(mod, data_test_3obvs)
parameterEstimates(fit)
Test Dataset: 4-Factor-3-Item
Description
A dataset for testing.
Usage
data_test_4_factor_3_item
Format
A data frame with 500 rows and 4 variables:
- x1
Numeric.
- x2
Numeric.
- x3
Numeric.
- m1
Numeric.
- m2
Numeric.
- m3
Numeric.
- m4
Numeric.
- m5
Numeric.
- m6
Numeric.
- y1
Numeric.
- y2
Numeric.
- y3
Numeric.
Examples
library(lavaan)
data(data_test_4_factor_3_item)
mod <-
"
fx =~ x1 + x2 + x3
fm1 =~ m1 + m2 + m3
fm2 =~ m4 + m5 + m6
fy =~ y1 + y2 + y3
"
fit <- sem(mod, data_test_4_factor_3_item)
parameterEstimates(fit)
Test Dataset: 4 Observed Variables
Description
A dataset for testing.
Usage
data_test_4obvs
Format
A data frame with 500 rows and 4 variables:
- fx
Numeric.
- fm1
Numeric.
- fm2
Numeric.
- fy
Numeric.
Examples
library(lavaan)
data(data_test_4obvs)
mod <-
"
fm1 ~~ fm2
fm1 ~ fx
fm2 ~ fx
fy ~ fm1 + fm2 + fx
"
fit <- sem(mod, data_test_4obvs)
parameterEstimates(fit)
Helpers to Compare Models
Description
Helper functions that compute and use hash digests for models (parameter tables) to facilitate comparisons.
Usage
digest_partable(
partable,
cols = getOption("semeqmodels.digest_cols", default = c("lhs", "op", "rhs", "block",
"group", "free", "ustart", "start")),
digits = getOption("semeqmodels.digest_digits", default = 6),
sort_rows = TRUE,
sort_by = getOption("semeqmodels.digest_sort_by", default = c("lhs", "op", "rhs",
"block", "group")),
algo = getOption("semeqmodels.algo", default = "xxhash32"),
...
)
add_digest(partable, ..., overwrite = FALSE)
get_digest(partable, ...)
add_digest_partables(partables, ..., overwrite = FALSE)
get_digest_partables(partables, ...)
Arguments
partable |
A |
cols |
The columns to be used
to compute the hash value. Note that
|
digits |
The number of digits
when rounding |
sort_rows |
Whether the
parameter tables will be sorted
by |
sort_by |
The columns used when
sorting the rows, if |
algo |
The algorithm used to
by |
... |
For |
overwrite |
Logical. If |
partables |
A list of |
Details
The function digest_partable() uses
digest::digest() to compute a
hash value for a parameter, after
sorting some essential columns
(see the cols argument)
If two lavaan parameter tables
are identical on the values for these
columns, they should have the same
hash value and will be considered as
identical.
Note that there may be cases in which two models cannot be correctly identified using this approach. Nevertheless, they should be sufficient for typical models used in this package.
The function add_digest() computes
the hash value of a parameter table
and adds it to the attribute "digest"
of the table. If the attribute is
already set, it will not overwrite
it unless overwrite is set to TRUE.
The function get_digest() retrieves
the stored hash value from a
parameter table, if available. If
not available, it will call digest_partable()
to compute the hash value.
The function add_digest_partables
calls add_digest() on a list of
parameter tables.
The function get_digest_partables
calls get_digest() on a list of
parameter tables.
Value
The function digest_partable() returns
a character string, the output of
digest::digest().
The function add_digest() returns
the parameter table, with the
hash value stored in the attribute
"digest".
The function get_digest() returns
the hash value of a parameter table.
The function add_digest_partables returns the list of parameter tables, with hash values stored.
The function get_digest_partables
returns a character vector, the
outputs of get_digest() for the
parameter tables.
Examples
library(lavaan)
# Model 1
mod1 <-
"
fx =~ x1 + x2 + x3
fm =~ m1 + m2 + m3
fy =~ y1 + y2 + y3
fm ~ fx
fy ~ fm + fx
"
fit1 <- sem(
model = mod1,
data = data_test_3_factor_3_item,
do.fit = FALSE
)
mod2 <-
"
fy =~ y1 + y2 + y3
fx =~ x1 + x2 + x3
fm =~ m1 + m2 + m3
fy ~ fm + fx
fm ~ fx
"
fit2 <- sem(
model = mod2,
data = data_test_3_factor_3_item,
do.fit = FALSE
)
pt1 <- parameterTable(fit1)
pt2 <- parameterTable(fit2)
pt1
pt2
digest_partable(pt1)
digest_partable(pt2)
Generate Models with the Same Degrees of Freedom
Description
Generate a list of models with df equal to a fitted model.
Usage
eq_df_models(
sem_out,
fit_models = FALSE,
loadings_to_exclude_from_drop = "all",
must_not_drop = NULL,
must_not_add = NULL,
se = "none",
exclude_x_y_ecov = TRUE,
parallel = TRUE,
ncores = max(parallel::detectCores(logical = FALSE) - 1, 1),
progress = interactive(),
gen_models_progress = FALSE,
short_names = TRUE,
must_not_add_nil_parameters = TRUE,
save_history = FALSE
)
Arguments
sem_out |
A |
fit_models |
Whether the models
will be fitted to the data. To be
passed to |
loadings_to_exclude_from_drop |
How factor loadings will be handled.
Default is |
must_not_drop |
A character vector
of parameters that must not be removed,
and so will not be modified. To be
passed to |
must_not_add |
A character
vector of parameters that must not
be added. To be passed to |
se |
Whether standard error will
be computed. This argument will be
passed to |
exclude_x_y_ecov |
If |
parallel |
Whether parallel
processing will be used. If possible,
should be set to |
ncores |
The number of CPU cores
to be used if |
progress |
If |
gen_models_progress |
If |
short_names |
If |
must_not_add_nil_parameters |
If |
save_history |
Logical. If |
Details
The following steps will be repeated to generate models with the same df as a fitted model:
First, models with one more df than
the fitted model will be generated,
by fixing more free parameters to zero.
This step is conducted by drop_k().
Second, for each of the one-more-df
model, models with one less df will
be generated, usually by setting one
fixed parameter to free (e.g., adding
a regression path). These models will
then have the same model df as the
fitted model. This step is conducted
by add_k().
These two steps will be repeated until no more new models are found.
Value
The function eq_df_models()
returns an eq_partables object
(a subclass of partables),
which is a list of models represented
by parameter tables.
Examples
library(lavaan)
# Model 1
mod1 <-
"
fm ~ fx
fy ~ fm
"
fit1 <- sem(
model = mod1,
data = data_test_3obvs,
fixed.x = FALSE
)
# Remove 'parallel = FALSE' or set parallel to TRUE
# for faster generation.
out <- eq_df_models(
sem_out = fit1,
parallel = FALSE
)
out
Empirical Equivalent Models
Description
Identify model(s) in a list of models (parameter tables) empirically equivalent to the original model.
Usage
eq_models(
partables = NULL,
original_model = NULL,
...,
se = "none",
parallel = TRUE,
ncores = max(parallel::detectCores(logical = FALSE) - 1, 1),
make_cluster_args = list(),
progress = interactive(),
tolerance = c(chisq = 1e-05),
eq_df_models_args = list()
)
is_eq(
partables = NULL,
original_model = NULL,
...,
se = "none",
parallel = TRUE,
ncores = max(parallel::detectCores(logical = FALSE) - 1, 1),
make_cluster_args = list(),
progress = interactive(),
tolerance = c(chisq = 1e-05),
eq_df_models_args = list()
)
Arguments
partables |
A list of the class
|
original_model |
The original
model, fitted by |
... |
Optional arguments to be
used when fitting models to the data,
to be passed to |
se |
How standard errors are to
be computed. To be passed to |
parallel |
Whether parallel
processing will be used when fitting
models. Default is |
ncores |
The number of CPU cores
to use when parallel processing is used.
To be passed
to |
make_cluster_args |
Additional
arguments to be passed to
|
progress |
Whether the testing progress will be displayed on screen. |
tolerance |
The maximum absolute
difference
in a fit measure for two models
to be considered empirically equivalent.
It should be a named numeric vector,
with the names being an acceptable
value of the name of fit measures
in |
eq_df_models_args |
If |
Details
eq_models()
The function eq_models()
checks the model degrees of freedom
and model chi-squares of a list of
models (represented by lavaan
parameter tables) against an original model,
fitted to a sample, to identify models
that are empirically equivalent
to the original model in this sample.
Two models are empirically equivalent
if they (a) have the same model degrees
of freedom and (b) have a difference
in model chi-squares equal to or less
than a tolerance (controlled by the
argument tolerance).
If two models are mathematically equivalent, then they must be empirically equivalent.
However, even if two models are not mathematically equivalent, they may still be empirically equivalent for a sample.
How to Generate the List of Models to Check
Usually, the alternative models can be generated
automatically by leaving partables
at its default value (NULL). The function
eq_df_models() will be called using
original_model as the original model.
The generation can be customized by setting
the argument eq_df_models_args.
Alternatively, the function eq_df_models()
can be called directly to generate
an initial list of models. This list
can then be filtered by helpers
in partable_select, such as
must_be_y() or must_not_have_paths(),
and use the resulting list as partables.
is_eq()
The function is_eq() is similar to
eq_models(), but returns a logical
vector to indicate which models in
partables are
empirically equivalent to the original
model.
Value
The function eq_models()
returns a list of the class eq_partables
(a subclass of partables)
of models that are empirically
equivalent to the original model.
The function is_eq() returns a
logical vector of the same length
of patables, with TRUE denoting
that a model is empirically equivalent
to original_model.
References
Pesigan, I. J. A., Cheung, S. F., Wu, H., Chang, F., & Leung, S. O. (2026). How plausible is my model? Assessing model plausibility of structural equation models using Bayesian posterior probabilities (BPP). Behavior Research Methods, 58(3), 73. doi:10.3758/s13428-025-02921-x
See Also
modelbpp::fit_many() for
the function used to fit the models.
Examples
library(lavaan)
# For illustration, only a few models are generated below,
# using drop_k() and add_k manually.
# These two functions are usually not used directly.
# Model 1
mod1 <-
"
fx =~ x1 + x2 + x3
fm =~ m1 + m2 + m3
fy =~ y1 + y2 + y3
fm ~ fx
fy ~ fm + fx
"
fit1 <- sem(
model = mod1,
data = data_test_3_factor_3_item
)
fit1_1_more <- drop_k(fit1)
fit1_1_more_1_less <- lapply(
fit1_1_more,
add_k
)
# Model 3
mod3 <-
"
fx =~ x1 + x2 + x3
fm =~ m1 + m2 + m3
fy =~ y1 + y2 + y3
fm ~ fx
fy ~ fm
"
fit3 <- sem(
model = mod3,
data = data_test_3_factor_3_item
)
fit3_1_more <- drop_k(fit3)
fit3_1_more_1_less <- lapply(
fit3_1_more,
add_k
)
# All equivalent
partables1 <- combine_partables(fit1_1_more_1_less)
# Some equivalent
partables3 <- combine_partables(fit3_1_more_1_less)
eq_out_1 <- eq_models(
partables1,
original_model = fit1,
parallel = FALSE
)
eq_out_3 <- eq_models(
partables3,
original_model = fit3,
parallel = FALSE
)
# The usual way to use eq_models:
# 'parallel' should be set to TRUE or omitted
# eq_out_all <- eq_models(
# original_model = fit1
# )
# eq_out_all
# Using is_eq()
is_eq(
partables1,
original_model = fit1,
parallel = FALSE
)
is_eq(
partables3,
original_model = fit3,
parallel = FALSE
)
Helpers for 'eq_partables' Object
Description
Helpers to work
with an
eq_partables object.
Usage
eq_lavInspect(object, ..., simplify = FALSE)
eq_fitMeasures(object, ..., output_format = c("data.frame", "list"))
eq_df(object)
eq_chisq(object)
eq_fits(object)
## S3 method for class 'eq_partables'
x[i]
## S3 replacement method for class 'eq_partables'
x[i] <- value
## S3 replacement method for class 'eq_partables'
x[[i]] <- value
## S3 method for class 'eq_partables'
print(
x,
max_models = NULL,
names_to_use = c("default", "long"),
wrap_long_names = TRUE,
readable_long_names = TRUE,
...
)
## S3 method for class 'eq_partables'
c(..., drop_duplicated = TRUE)
eq_partables(...)
as_eq_partables(sem_out = NULL, model_name = "original")
## S3 method for class 'eq_partables'
duplicated(x, incomparables = FALSE, ...)
## S3 method for class 'eq_partables'
unique(x, incomparables = FALSE, ...)
Arguments
object |
An |
... |
For |
simplify |
To be passed to
|
output_format |
The format of
the output of |
x |
An |
i |
A numeric vector of model position(s), a character vector of model name(s), or a logical vector of model(s) to be selected. |
value |
The value(s) to be
assigned to the |
max_models |
The maximum number
of models to print. If |
names_to_use |
If |
wrap_long_names |
If |
readable_long_names |
If |
drop_duplicated |
Logical. Whether duplicated models will be removed. |
sem_out |
A |
model_name |
The name of the model in the output. |
incomparables |
Not used. |
Details
Although the functions are designed
to work with the output of eq_models(),
they also work for a list of models
(parameter tables), except for the
methods specifically for an eq_partables
object.
The function eq_lavInspect()
calls lavaan::lavInspect() on the
elements of an eq_partables object.
The function eq_fitMeasures()
calls lavaan::fitMeasures() on the
elements of an eq_partables object.
The function eq_df() is a wrapper
that calls eq_fitMeasures() with
fit.measures set to "df". It
always returns a numeric vector.
The function eq_chisq() is a wrapper
that calls eq_fitMeasures() with
fit.measures set to "chisq". It
always returns a numeric vector.
The function eq_fits() extracts
the lavaan outputs stored for each
model, if present.
The class eq_partables has
[, [<-, and [[<- methods for extracting
and changing elements.
Though available, it is not advised
to assign models to an eq_partables
object because there is no guarantee
that the names still reflect how the
models are created.
The print-method of eq_partables
object handles a zero-length list.
If not of zero length, the print-method
for partables will be used.
The c-method of eq_partables
objects combines eq_partables elements
into one single eq_partables element.
The function eq_partables()
creates an eq_partables object
from lavaan parameter tables
or lavaan outputs.
The function as_eq_partables() is
not a usual as function. It works
only on a lavaan output or
lavaan parameter table. It converts
sem_out to a one-element
list of the class eq_partables,
with the parameter table as the
element and the lavaan output,
if sem_out is a lavaan output, in
the attribute "fit". If sem_out
is not a lavaan object nor a
lavaan parameter table, a zero-length
eq_partables object will be returned.
The duplicated-method of eq_partables
checks whether any models are
identical. If yes, the duplicated
models, except for the first one,
will be denoted as duplicated.
The unique-method of eq_partables
returns an eq_partables object with
duplicated models, if any, removed.
Value
The function eq_lavInspect()
returns the output of
lavaan::lavInspect(). Whether it
is a vector, list, or other type of
objects depends on the argument
simplify, used by sapply().
The function eq_fitMeasures()
returns the output of
lavaan::fitMeasures(). The format
is determined by output_format.
The function eq_fits() returns a
list of lavaan outputs for the
models in object. If absent for
a model, the value returned is NULL.
The [, [<-, and [[<- methods return
an eq_partables object.
The print-method of eq_partables
returns x invisibly. It is called
for its side-effect.
The c-method of eq_partables
returns a list of the class
eq_partables.
The function eq_partables()
returns an eq_partables object
created from one or more
lavaan outputs or lavaan
parameter tables.
The function as_eq_partables()
returns a one-element
eq_partables object if sem_out is
a lavaan output or a lavaan
parameter table. It returns
a zero-length eq_partables object
otherwise.
The duplicated-method of eq_partables
returns a logical vector to indicate
which models, if any, are identical
to other models earlier in the list.
The unique-method of eq_partables
returns an eq_partables object.
Examples
library(lavaan)
# Model 1
mod1 <-
"
fm ~ fx
fy ~ fm
"
fit1 <- sem(
model = mod1,
data = data_test_3obvs,
fixed.x = FALSE
)
# Remove 'parallel = FALSE' or set parallel to TRUE
# for faster generation.
out <- eq_models(
original_model = fit1,
parallel = FALSE
)
out
eq_lavInspect(out, "implied")
eq_fitMeasures(out, c("cfi", "tli"))
eq_df(out)
eq_fits(out)
out1 <- out[2:3]
out1
Compare Two Models
Description
Helper functions to compare two models (parameter tables) and find the differences.
Usage
model_diff(
model_x,
model_y,
cols = getOption("semeqmodels.digest_cols", default = c("lhs", "op", "rhs", "block",
"group", "free", "ustart", "start")),
digits = 6,
model_x_name = NULL,
model_y_name = NULL
)
model_diff_many(
target_model,
other_models,
...,
target_model_name = NULL,
other_models_names = NULL
)
## S3 method for class 'model_diff'
print(x, format = c("summary", "data.frame"), ...)
## S3 method for class 'model_diff_many'
print(x, format = "summary", ...)
Arguments
model_x, model_y |
Models as
parameter
tables (the output lavaan::parameterTable) to be compared.
They can also be |
cols |
The columns to be compared.
Two parameters are considered to
be identical if they are identical
on these columns (but see Details
on how |
digits |
The number of decimal
places used to round |
model_x_name, model_y_name |
The
names of the models used in the output.
If |
target_model |
A model
( |
other_models |
A list of models
( |
... |
For |
target_model_name, other_models_names |
Names of the models to be passed to
|
x |
The object to be printed. |
format |
The format of the output
when printing model differences.
Either a user-friendly summary
( |
Details
model_diff()
The functions model_diff() takes
two models (parameter tables) and identifies
their differences, if any.
The columns compared are specified
by the argument cols.
For the free column, the actual values are
ignored. Two parameters are considered
identical if they are both free
(have non-zero values on free).
For the ustart and start columns,
the values are used only if a parameter
is fixed. If a parameter is free,
they will be recoded to NA when
being compared.
model_diff_many()
The function model_diff_many()
compares one model (target_model)
against several other models (other_models)
using model_diff().
The print method of the output of model_diff()
The print method of the output
of model_diff() prints the differences
between models in a user-friendly
way.
The print method of the output of model_diff_many()
The print method of the output
of model_diff_many() prints the
list of model differences in a
user-friendly
way.
Value
The function model_diff()
returns a list with two elements,
model_x_only and model_y_only.
Each element is a parameter table
with parameters that are present only
in one of the models. If there is
no parameter that is present only in
a model, then the element is still
a parameter table, though with zero
row. The list is of the class
model_diff, with a print method.
The function model_diff_many()
returns a list of the results
of model_diff().
The list is of the class
model_diff_many, with a print method.
The print-method of the output
of model_diff() returns x
invisibly.
It is called for its side effect.
The print-method of the output
of model_diff_many() returns x
invisibly.
It is called for its side effect.
Examples
library(lavaan)
mod1 <-
"
m ~ x
y ~ m + x
"
mod2 <-
"
m ~ x
y ~ m
"
mod3 <-
"
y ~ m + x
"
pt1 <- parameterTable(sem(mod1, do.fit = FALSE))
pt2 <- parameterTable(sem(mod2, do.fit = FALSE))
pt3 <- parameterTable(sem(mod3, do.fit = FALSE))
model_diff(pt1, pt2)
model_diff(pt1, pt3)
model_diff(pt2, pt3)
Modified Models
Description
Generate a list of models with a certain number of degrees different from an original model.
Usage
drop_k(
object,
...,
sem_out = NULL,
loadings_to_exclude_from_drop = "all",
df_change_drop = 1,
must_not_drop = NULL,
se = "none",
progress = interactive(),
fit_models = FALSE,
parallel = TRUE,
ncores = max(parallel::detectCores(logical = FALSE) - 1, 1),
make_cluster_args = list(),
drop_original = TRUE,
add_digest = TRUE,
dat = NULL
)
add_k(
object,
...,
sem_out = NULL,
df_change_add = 1,
must_not_add = NULL,
exclude_x_y_ecov = TRUE,
partable_name = NULL,
se = "none",
progress = interactive(),
fit_models = FALSE,
parallel = TRUE,
ncores = max(parallel::detectCores(logical = FALSE) - 1, 1),
make_cluster_args = list(),
remove_dropped = TRUE,
remove_zeros = FALSE,
add_name = FALSE,
add_digest = TRUE,
dat = NULL,
return_error_msg = FALSE
)
Arguments
object |
The original model. It
can be a |
... |
Optional arguments to be
passed to |
sem_out |
A |
loadings_to_exclude_from_drop |
How factor loadings will be handled.
Default is |
df_change_drop |
The change in
the degrees of freedom when generating
simplified models. Default is one.
To be passed to |
must_not_drop |
A character vector
of parameters that must not be removed,
and so will not be modified. To be
passed to |
se |
Whether standard error will
be computed. This argument will be
passed to |
progress |
Whether the model generation process will be displayed on screen. |
fit_models |
Whether the models will be fitted to the data. |
parallel |
Whether parallel
processing will be used when fitting
the models.
To be passed to |
ncores |
The number of CPU cores
to be used if |
make_cluster_args |
An optional
named list of arguments to be used
in |
drop_original |
Logical. Whether
the original model will be dropped from
the output. Default is |
add_digest |
Logical. If |
dat |
The dataset to be used
when |
df_change_add |
The change in
the degrees of freedom when adding
free parameters.
To be passed to |
must_not_add |
A character
vector of parameters that must not
be added. To be passed to |
exclude_x_y_ecov |
If |
partable_name |
The name of the
original model. Used only if it cannot
be generated from |
remove_dropped |
Whether the previously dropped parameter, if stored, will be removed from the original parameter table. This is necessary for reversing a path. For internal use. Should not be changed. |
remove_zeros |
Whether a parameter
explicitly fixed to |
add_name |
Whether the name of the original model will be added as a prefix to the names of the generated models. |
return_error_msg |
If an error
occurred when calling |
Details
The function drop_k() is
a helper
to generate a list of models k more
degrees of freedom different from an original
model fitted by lavaan, such as
lavaan::sem().
The function add_k() is a
helper
to generate a list of models k less
degrees of freedom different from an
original model fitted by lavaan,
such as lavaan::sem().
Value
The function drop_k()
returns a list of the class eq_partables,
a subclass of partables. It is
an output of modelbpp::gen_models(),
which are simplified versions of the
original model, usually with one or
more paths removed (fixed to zero).
The function add_k()
returns a list of the class eq_partables,
a subclass of the
output of modelbpp::gen_models(),
which are more complicated versions of the
original model, usually with one or
more paths added (set to free).
References
Pesigan, I. J. A., Cheung, S. F., Wu, H., Chang, F., & Leung, S. O. (2026). How plausible is my model? Assessing model plausibility of structural equation models using Bayesian posterior probabilities (BPP). Behavior Research Methods, 58(3), 73. doi:10.3758/s13428-025-02921-x
See Also
modelbpp::gen_models() for
how the model generation is implemented.
Examples
library(lavaan)
mod <-
"
fx =~ x1 + x2 + x3
fm =~ m1 + m2 + m3
fy =~ y1 + y2 + y3
fm ~ fx
fy ~ fm + fx
"
fit <- sem(
model = mod,
data = data_test_3_factor_3_item
)
pt <- parameterTable(fit)
# ==== Generate models one-less-df ====
# ==== drop_k ====
fit_1_more1 <- drop_k(fit)
fit_1_more1
fit_1_more2 <- drop_k(pt)
fit_1_more2
# ==== add_k ====
# Remove 'parallel = FALSE' or use 'parallel = TRUE'
# to enable parallel processing, which is recommended.
fit_1_less <- add_k(
fit_1_more1[[1]],
add_name = TRUE,
parallel = FALSE
)
fit_1_less
Parameter Table Helpers
Description
Helper functions to manipulate parameter tables. They are exported for advanced users.
Usage
combine_partables(object_list, drop_duplicated = TRUE)
setdiff_eq_partables(x, y)
setdiff_partables(x, y)
union_eq_partables(x, y)
intersect_eq_partables(x, y)
setequal_eq_partables(x, y)
setequal_partables(x, y)
is_element_eq_partables(el, set)
is_element_partables(el, set)
match_eq_partables(x, table, nomatch = NA_integer_)
match_partables(x, table, nomatch = NA_integer_)
x %pt_in% table
x %pt_notin% table
is_partable(object, colchk = c("id", "lhs", "op", "rhs"))
is_partables(object, colchk = c("id", "lhs", "op", "rhs"))
Arguments
object_list |
A list of objects
of the class
|
drop_duplicated |
Logical. Whether duplicated models will be removed. |
x, y |
List of parameter tables,
such as |
el |
A parameter table. |
set |
A list of parameter tables. |
table |
A list of parameter tables. |
nomatch |
The same argument from
|
object |
The object to be checked whether it is a parameter table. |
colchk |
The columns to be checked. |
Details
The function combine_partables()
combines a list of partables objects
or eq_partables objects
to one single object of the same type.
The function setdiff_eq_partables()
(and setdiff_partables())
removes from x models that are
also in y.
The function union_eq_partables()
combines the models in x and y,
with duplicated models removed.
The function intersect_eq_partables()
finds the models common in x and y.
The function setequal_eq_partables()
(and setequal_partables())
checks whether x and y has the
same set of models. Orders are ignored.
The function is_element_eq_partables()
checks whether el is one of the
models in set.
The function match_eq_partables()
(and match_partables())
is similar to match(), but check
matches based on the results of
get_digest() applied to the
parameter tables.
%pt_in% is similar to %in%,
but works on parameter tables using
match_eq_partables().
%pt_notin% is similar to %notin%,
but works on parameter tables using
match_eq_partables().
The function is_partable() checks
whether an object is probably a
parameter table. It checks whether
(a) the object is a data.frame-like
object (by is.data.frame()) and (b)
the columns in colchk exist. If
both conditions are met, then the
object is considered a parameter
table.
The function is_partables() checks
whether a list is likely a list of parameter
tables. It simply calls is_partable()
on all the elements.
Value
The function combine_partables()
always returns an object of the class
eq_partables, which is a subclass
of partables.
The function setdiff_eq_partables()
returns a list of parameter tables,
of the same class of x, with models
present in y removed.
The function union_eq_partables()
returns a list of parameter tables,
of the class eq_partables.
The function intersect_eq_partables()
returns a list of parameter tables,
of the class eq_partables, common
in both x and y.
The function setequal_eq_partables()
returns TRUE or FALSE, based on
the results of get_digest_partables()
applied to x and y.
The function is_element_eq_partables()
(and is_element_partables())
returns TRUE or FALSE, based on
the results of is.element() applied
to the hash values from get_digest()
and get_digest_partables().
The function match_eq_partables()
(and match_partables())
returns the results of match() applied
to the hash values generated by
get_digest().
%pt_in% returns a logical vector,
the output of %in% applied to
the has values of x and table.
%pt_notin% returns a logical vector,
the output of %notin% applied to
the has values of x and table.
The function is_partable() returns
either TRUE or FALSE. It is
TRUE if the two conditions mentioned
in Details are met.
The function is_partables() returns
either TRUE or FALSE. It is
TRUE only if is_partable() returns
TRUE for all its elements.
Examples
library(lavaan)
# Model 1
mod1 <-
"
fx =~ x1 + x2 + x3
fm =~ m1 + m2 + m3
fy =~ y1 + y2 + y3
fm ~ fx
fy ~ fm + fx
"
fit1 <- sem(
model = mod1,
data = data_test_3_factor_3_item
)
fit1_1_more <- drop_k(fit1)
fit1_1_more_1_less <- lapply(
fit1_1_more,
add_k
)
partables1 <- combine_partables(fit1_1_more_1_less)
partables1
Select Models (Parameter Tables)
Description
Helper functions to select models (parameter tables) based on various criteria.
Usage
have_pars_all(
partables,
pars = NULL,
output = c("models", "partables", "logical")
)
have_pars_any(
partables,
pars = NULL,
output = c("models", "partables", "logical")
)
have_pars_none(
partables,
pars = NULL,
output = c("models", "partables", "logical")
)
remove_x_y_ecov(
partables,
output = c("models", "partables", "logical"),
cl = NULL
)
must_not_be_y(
partables,
vars = NULL,
output = c("models", "partables", "logical")
)
must_be_y(partables, vars = NULL, output = c("models", "partables", "logical"))
must_not_have_paths(
partables,
y_on_x = NULL,
output = c("models", "partables", "logical")
)
must_have_paths(
partables,
y_on_x = NULL,
output = c("models", "partables", "logical")
)
Arguments
partables |
A list of parameter
tables, such as a
|
pars |
A character vector
of |
output |
The type of output.
If |
cl |
A cluster created by
|
vars |
A character vector of variables to be checked. |
y_on_x |
A character vector of
pairs of variables, specified as
|
Details
The select functions can be used both
for a list of models in the form
of parameter tables (the output
of lavaan::parameterTable()) or
a list of plots based on these models,
generated by partables_plots().
They return an object of the same type.
Therefore, they can be used to filter
both models and plots of models.
Select by free parameters
The function
have_pars_all() selects models
that have all the free parameters
specified in pars.
The function
have_pars_any() identifies models
that have any of the free parameters
specified in pars.
The function
have_pars_none() identifies models
that have none of the free parameters
specified in pars.
Select by covariances with an error term
The function remove_x_y_ecov()
removes models from partables that
have a covariance between
an observed or latent variable
(or its error term) and the error
term of another variable it predicts,
either directly or indirectly.
Select by the role of a variable
The function must_not_be_y()
keeps only models with selected variables
(observed or latent) not
appearing as the outcome in a
regression equation (indicators
not counted). They are
defined as variables not
in "eqs.y"
as returned by lavaan::lavNames().
The function must_be_y()
keeps only models with selected variables
(observed or latent)
appearing as the outcome in at least one
regression equation (indicators
not counted). They are
defined as variables
in "eqs.y"
as returned by lavaan::lavNames().
Select by paths
The function must_not_have_paths()
keeps only models that do not
have any paths, direct or indirect,
between selected pairs of variables.
The function must_have_paths()
keeps only models
with at least one path, direct or indirect,
between selected pairs of variables.
Value
Each of the select functions, by default,
returns a list of parameter tables (models)
that meet the criterion of that function,
or a list of plots of the parameter tables
if partables is the output of partables_plots().
If output is set to "logical",
each of these functions returns
a logical vector to indicate models or plots
that meet the criterion. The vector
can then be used to extract objects meeting
the criterion.
Examples
library(lavaan)
# Model 1
mod1 <-
"
fx =~ x1 + x2 + x3
fm =~ m1 + m2 + m3
fy =~ y1 + y2 + y3
fm ~ fx
fy ~ fm + fx
"
fit1 <- sem(
model = mod1,
data = data_test_3_factor_3_item
)
fit1_1_more <- drop_k(fit1)
fit1_1_more_1_less <- lapply(
fit1_1_more,
add_k
)
partables1 <- combine_partables(fit1_1_more_1_less)
partables1
# === have_pars_all ====
have_pars_all(partables1, c("fx ~~ fm", "fy ~ fx"))
have_pars_all(partables1, c("fx ~~ fm", "fy ~ fx"),
output = "logical")
# === have_pars_any ====
have_pars_any(partables1, c("fx ~~ fm", "fm ~ fx"))
have_pars_any(partables1, c("fx ~~ fm", "fm ~ fx"),
output = "logical")
# === have_pars_none ====
have_pars_none(partables1, c("fx ~~ fm", "fm ~ fx"))
have_pars_none(partables1, c("fx ~~ fm", "fm ~ fx"),
output = "logical")
# === must_not_be_y ====
must_not_be_y(partables1, c("fx"))
must_not_be_y(partables1, c("fx"),
output = "logical")
# === must_be_y ====
must_be_y(partables1, c("fm"))
must_be_y(partables1, c("fm"),
output = "logical")
# === must_not_have_paths ====
must_not_have_paths(partables1, y_on_x = c("fx ~ fm"))
must_not_have_paths(partables1, y_on_x = c("fx ~ fm"),
output = "logical")
# === must_not_have_paths ====
must_have_paths(partables1, y_on_x = c("fm ~ fx"))
must_have_paths(partables1, y_on_x = c("fm ~ fx"),
output = "logical")
Plot Functions for a List of Models
Description
Various plot functions
for the output of eq_models(),
eq_df_models(), and
similar functions.
Usage
partables_plots(
object,
...,
partables = NULL,
original_model = NULL,
auto_node_color = TRUE,
par_diff_settings = list(color = "blue", width = 2),
fix_pars_fixed_zero = TRUE,
par_fixed_zero_settings = list(color = "white", width = 0),
exclude_original_model = FALSE,
curve_cov = TRUE,
curve_cov_settings = list(base_curve = 1.5)
)
## S3 method for class 'partables_plots'
plot(
x,
...,
title_mode = c("digest", "name", "none"),
title_adj = 1.4,
title_args = list(),
ncol = 1,
nrow = 1,
scale_plots = c("auto", "always"),
scale = NULL,
elements_to_scale = c("Nodes:width", "Nodes:height", "Edges:width", "Edges:asize"),
original_model_mode = c("include", "exclude", "side_by_side")
)
## S3 method for class 'partables_plots'
print(x, ...)
lhs %p>% rhs
Arguments
object |
If it is a list of models
(parameter tables), such as the output
of |
... |
For |
partables |
It should be a list of
models in the form of parameter tables,
such as the output
of |
original_model |
The model to
which models in |
auto_node_color |
If |
par_diff_settings |
A named list of
settings to configure the change of
a parameter from |
fix_pars_fixed_zero |
If |
par_fixed_zero_settings |
A named
settings to configure edges (arrows)
fixed to zero. For now,
two settings are supported: |
exclude_original_model |
If |
curve_cov |
If |
curve_cov_settings |
A named list
of arguments to be passed to
|
x |
The output of |
title_mode |
What will be used
as the title. If |
title_adj |
Adjust the position of the title. Increase this value if the plot is too close to the title, and decrease this value if the space between the plot and its title is too large. |
title_args |
A named list of
arguments to be passed to |
ncol, nrow |
The number of columns
and rows when drawing the models. Used
by |
scale_plots |
How the models will
be scaled. If |
scale |
How the model will
be further scaled when drawn. If this
value is greater than one, then
elements in |
elements_to_scale |
Elements
in the |
original_model_mode |
How original
model, if present, will be handled when
drawing the models. If |
lhs |
A |
rhs |
A function call to be applied to all stored plots. Each plot will be inserted as the first argument. |
Details
The functions provide different ways
to visualize the models. Basic knowledge
of semPlot::semPaths() from the
package semPlot is required to
customize the plots.
Value
The function partables_plots() returns
a list of qgraph objects generated
from semPlot::semPaths(), of the
class partables_plots.
The plot method of the output
of partables_plots() returns x
invisibly. Called for its side effect.
The print method of the output
of partables_plots() returns x
invisibly. Called for its side effect.
The %p>% operator returns a
partables_plots object, processed
by the right-hand side function.
See Also
See eq_models() on the
type of output supported.
Examples
library(lavaan)
# Model 1
mod1 <-
"
fx =~ x1 + x2 + x3
fm =~ m1 + m2 + m3
fy =~ y1 + y2 + y3
fm ~ fx
fy ~ fm + fx
"
fit1 <- sem(
model = mod1,
data = data_test_3_factor_3_item
)
fit1_1_more <- drop_k(fit1)
fit1_1_more_1_less <- lapply(
fit1_1_more,
add_k
)
partables1 <- combine_partables(fit1_1_more_1_less)
eq_out_1 <- eq_models(
partables1,
original_model = fit1,
parallel = FALSE
)
eq_out_1 <- eq_models(
partables1,
original_model = fit1,
parallel = FALSE
)
layout_i <- matrix(c( NA, "fm", NA,
"fx", NA, "fy"),
ncol = 3,
nrow = 2,
byrow = TRUE)
layout_i
p <- partables_plots(
eq_out_1,
original_model = fit1,
layout = layout_i,
label.cex = 1.5,
sizeLat = 15,
edge.width = 5,
asize = 5,
structural = TRUE,
par_diff_settings = list(
color = "blue",
width = 10
)
)
plot(p)