Fit Structural Equation Models using the SAM approach
sam.RdFit a Structural Equation Model (SEM) using the Structural After Measurement (SAM) approach.
Usage
sam(model = NULL, data = NULL, aux = NULL, cmd = "sem", se = "twostep",
mm_list = NULL, mm_args = list(bounds = "wide.zerovar"),
struc_args = list(estimator = "ML"),
sam_method = "local", ...,
local_options = list(M.method = "ML", lambda.correction = TRUE,
alpha.correction = 0L, twolevel.method = "h1"),
global_options = list(),
bootstrap = list(R = 1000L, type = "ordinary", show.progress = FALSE),
output = "lavaan",
bootstrap_args = bootstrap
)Arguments
- model
A description of the user-specified model. Typically, the model is described using the lavaan model syntax. See
model.syntaxfor more information. Alternatively, a parameter table (e.g., the output of thelavParTable()function) is also accepted.- data
A data frame containing the observed variables used in the model.
- aux
Character vector. Names of auxiliary observed variables, forwarded to the underlying measurement and structural model fits. See the
lavaanfunction for more details.- cmd
Character. Which command is used to run the sem models. The possible choices are
"sem","cfa"or"lavaan", determining how we deal with default options.- se
Character. The type of standard errors that are used in the final (structural) model. If
"twostep"(the default), the standard errors take the estimation uncertainty of the first (measurement) stage into account. If"standard", this uncertainty is ignored, and we treat the measurement information as known. If"none", no standard errors are computed. The experimental"twostep.huber.white"variant computes the two-step correction as a stacked (Murphy-Topel type) sandwich with casewise-score based (first-order) meat – the two-step analogue ofse = "robust.huber.white"insem; it is currently available for continuous complete ormissing = "ml"data (single- or multigroup, single level, no equality constraints), and falls back to"twostep.robust"or"twostep"otherwise. If the data are clustered (acluster=argument is provided, without multilevel model syntax),se = "twostep"is automatically replaced byse = "twostep.robust", and the standard errors (also forse = "local"andse = "bootstrap", which resamples whole clusters) account for the clustering. For two-level models,se = "local"is available for the single-group continuous complete-data setting; it uses the cluster-sandwich covariance of the saturated (h1) estimates, and also enables the corrected structural test statistic. Forestimator = "PML",se = "local"is the only available two-step correction (single group, complete data, all-ordinal indicators): it combines the casewise influences of the saturated thresholds/polychoric correlations with the casewise pairwise-likelihood influences of the measurement-block estimates, and also enables the corrected structural test statistic.- mm_list
List. Define the measurement blocks. Each element of the list should be either a single name of a latent variable, or a vector of latent variable names. If omitted, a separate measurement block is used for each latent variable.
- mm_args
List. Optional arguments for the fitting function(s) of the measurement block(s) only. See
lavOptionsfor a complete list.- struc_args
List. Optional arguments for the fitting function of the structural part only. See
lavOptionsfor a complete list.- sam_method
Character. Can be set to
"local","global"or"fsr". In the latter case, the results are the same as if Bartlett factor scores were used, without any bias correction.- ...
Many more options can be specified, using 'name = value'. See
lavOptionsfor a complete list. These options affect both the measurement blocks and the structural part.- local_options
List. Options specific for local SAM method (these options may change over time). If
lambda.correction = TRUE, we ensure that the variance matrix of the latent variables (VETA) is positive definite. Thealpha.correctionoption must be an integer. Acceptable values are in the range 0 to N-1. If zero (the default), no small sample correction is performed, and the bias-correction is the same as with local SAM. When equal to N-1, the bias-correction is eliminated, and the results are the same as naive FSR. Typical values are 0, P+1 (where P is the number of predictors in the structural model), P+5, and (N-1)/2.- global_options
List. Options specific for global SAM method (not used for now).
- bootstrap
List. Only used when
se = "bootstrap". Typical elements of this list areR: the number of bootstrap samples, andtype, which can be set to"ordinary"(the default) or"parametric". A single number is also accepted (as insem()) and is interpreted asR, the number of bootstrap draws.- output
Character. If
"lavaan", a lavaan object is returned. If"list", a list is returned with all the ingredients from the different stages.- bootstrap_args
List. Deprecated, use
bootstrapinstead.
Details
The sam function automates the SAM approach by first
estimating the measurement part of the model and then the structural
part of the model. See the reference for more details.
Note that in the current implementation, all indicators of latent variables must be observed. As a result, second-order factor structures are not yet supported.
If sam.method is "local", "fsr" or "cfsr",
the structural part of the model is fitted to the estimated latent
(co)variances (and means) from step 1. This step-2 structural model is
stored in the @internal slot of the returned object, and can be
retrieved by lavInspect(fit, "sam.struc.fit.object"). The
functions fitMeasures (and
summary(fit, fit.measures = TRUE)), lavResiduals
(and summary(fit, residuals = TRUE)), modindices
and lavTestLRT (when all compared models are local SAM
models) operate on this structural model: the reported quantities
describe the fit of the structural part only, conditional on the (fixed)
measurement model of step 1. When available, the reported (scaled) test
statistic and the robust fit measures are corrected for the estimation
of the measurement model in step 1.
If sam.method is "global", the returned object is an
ordinary (joint) lavaan object, and fitMeasures returns the usual
fit measures of the joint model. Note, however, that the parameters were
estimated using a two-step procedure; the behavior of fit measures in
this setting has not been studied, and they should be interpreted with
caution.
Exogenous covariates and conditional.x
Observed exogenous covariates may enter the structural part of the
model. With continuous data, they are simply treated as (pseudo) latent
variables (the default conditional.x = FALSE), but
conditional.x = TRUE is supported as well (single-group,
single-level models): the structural part is then fitted to the latent
intercepts, the latent-on-covariate slopes, and the residual latent
(co)variances, all conditional on the covariates.
With categorical (ordered) data, conditional.x = TRUE is the
lavaan default (when exogenous covariates are present), and this is also
the recommended setting: the covariates are conditioned on (as in a
probit regression), rather than being absorbed into the joint polychoric
correlation matrix – which would (wrongly) treat them as jointly normal,
a real concern for binary/dummy covariates. In this setting, the
measurement blocks of step 1 are estimated with
conditional.x = TRUE as well (each block latent variable is
regressed on all exogenous covariates, MIMIC style), so that the
measurement parameters live on the same conditional latent-response
scale (Var(y*|x) = 1, delta parameterization) as the joint model.
An ordered endogenous variable in the structural part is
supported too (with or without covariates): it enters the structural
model on its latent-response scale, while its thresholds are fixed at
their sample-based values.
When conditional.x = TRUE is combined with a local
sam.method, the default se = "twostep" is automatically
replaced by se = "twostep.robust": the classic two-step formula is
built on the joint information matrix, which does not describe the local
step-2 estimator in this setting (it underestimates the sampling
variability, especially for binary covariates). The robust variant is
computed as a structural-space sandwich here, and coincides with
se = "local".
Not (yet) available in combination with conditional.x = TRUE:
multiple groups (for the local standard errors and the corrected test
statistic), multilevel models, latent interactions, and the Yuan-Chan
scaled global test statistic of sam_method = "global" (the
standard, unscaled test is reported instead, with a warning).
Value
If output = "lavaan", an object of class
lavaan, for which several methods
are available, including a summary method. If output = "list",
a list.
References
Rosseel and Loh (2021). A structural-after-measurement approach to Structural Equation Modeling. Psychological Methods. Advance online publication. https://dx.doi.org/10.1037/met0000503
Examples
## The industrialization and Political Democracy Example
## Bollen (1989), page 332
model <- '
# latent variable definitions
ind60 =~ x1 + x2 + x3
dem60 =~ y1 + a*y2 + b*y3 + c*y4
dem65 =~ y5 + a*y6 + b*y7 + c*y8
# regressions
dem60 ~ ind60
dem65 ~ ind60 + dem60
# residual correlations
y1 ~~ y5
y2 ~~ y4 + y6
y3 ~~ y7
y4 ~~ y8
y6 ~~ y8
'
fit.sam <- sam(model, data = PoliticalDemocracy,
mm.list = list(ind = "ind60", dem = c("dem60", "dem65")))
summary(fit.sam)
#> This is lavaan 0.7-1.3097 -- using the SAM approach to SEM
#>
#> SAM method LOCAL
#> Mapping matrix M method ML
#> Number of measurement blocks 2
#> Estimator measurement part ML
#> Estimator structural part ML
#>
#> Number of observations 75
#>
#> Summary Information Measurement + Structural:
#>
#> Block Latent Nind Chisq Df
#> 1 ind60 3 0.00 0
#> 2 dem60,dem65 8 15.32 16
#>
#> Model-based reliability latent variables:
#>
#> ind60 dem60 dem65
#> 0.966 0.868 0.87
#>
#> Summary Information Structural part:
#>
#> chisq df pvalue cfi rmsea srmr
#> 0 0 NA 1 0 0
#>
#> Parameter Estimates:
#>
#> Standard errors Twostep
#> Information Expected
#> Information saturated (h1) model Structured
#>
#> Regressions:
#> Estimate Std.Err z-value P(>|z|)
#> dem60 ~
#> ind60 1.454 0.389 3.741 0.000
#> dem65 ~
#> ind60 0.558 0.225 2.480 0.013
#> dem60 0.871 0.076 11.497 0.000
#>
#> Variances:
#> Estimate Std.Err z-value P(>|z|)
#> ind60 0.446 0.087 5.135 0.000
#> .dem60 3.766 0.848 4.439 0.000
#> .dem65 0.189 0.224 0.843 0.399
#>