Estimate the Structural Summary Method profile that one or more external
measures show against the latent circumplex content of a set of
scales -- the disattenuated analog of the correlation-based
ssm_analyze() -- from a structural equation model with the scale angles
held fixed at their theoretical values. The measurement model is generated
by ssm_sem_syntax() and fitted with lavaan on raw covariances;
confidence intervals for all SSM parameters are constructed in-package by
propagating draws of the model's free parameters through the profile and
SSM transforms and applying the same percentile/circular-quantile machinery
as ssm_analyze(). No lavaan delta-method or percentile interval is ever
used for amplitude or displacement (their intervals must respect the
angular branch cut, which lavaan's := machinery does not).
ssm_sem(
data,
scales,
angles = octants(),
measures = NULL,
grouping = NULL,
contrast = FALSE,
model = c("scaled", "strict"),
invariance = NULL,
invariance_alpha = 0.05,
ci_method = c("mvn", "boot"),
boots = 2000,
interval = 0.95,
estimator = "MLR",
se = "robust.huber.white",
missing = c("listwise", "fiml"),
parallel = "no",
ncpus = 1,
...
)A circumplex_ssm_sem object (a subclass of circumplex_ssm, so
ssm_table() and the ssm_plot_* functions work on it), containing
results (estimates and intervals), scores (the latent profile
vectors), details, call, plus sem (the fitted lavaan model: the
gate rung's fit for grouped analyses, or the configural fit when the
gate was rejected), invariance (for grouped analyses: the ladder
table -- including the dcfi column and its cr retain/reject label,
NA outside the criterion's validated scope -- the comparable flag,
the verdict text, the gate and required rungs, the alpha used, and
dcfi_scope recording that scope; NULL for single-group analyses),
and model (tier,
generated syntax for single-group fits, and the OLS projection
weights).
Inadmissible parameter draws (a nonpositive common-part or measure
variance, or a disattenuated correlation at or beyond 1) are dropped
whole with a warning naming the causes; if more than 5% of draws are
inadmissible the analysis stops with advice to use ci_method = "boot"
or revise the model. Degenerate profiles (flat or zero-amplitude) keep
the same per-parameter NA contract as ssm_analyze().
Required. A data frame or matrix containing at least the circumplex scales and measures.
Required. A character vector of column names, or a numeric
vector of column indexes, from data that contains the circumplex scale
scores.
Optional. A numeric vector containing the angular displacement
of each circumplex scale included in scales, in degrees
(default = octants()). The angles are fixed theoretical constants in the
measurement model, never free parameters.
Optional with grouping, required otherwise. A character
vector (or numeric indexes) of one or more columns of data to be
related to the latent circumplex content (the disattenuated correlation
path). With grouping and measures = NULL, the latent MEAN path is
analyzed instead: each group's model-implied latent mean profile, on the
raw-score metric. (A single-group latent mean profile is not a product:
factor means are not identified in one group.)
Optional. A string naming the column of data indicating
group membership. With grouping, the fixed-angle measurement model is
fitted as a multi-group model under an invariance ladder
(configural, then metric, then -- when required -- scalar), and the
latent SSM profiles are reported per group. The FIRST factor level is
the reference group. With measures = NULL and grouping, the latent
MEAN path is analyzed (each group's model-implied latent mean profile).
Optional. A logical (default = FALSE) requesting a
difference of latent SSM parameters, always second minus first with the
displacement contrast in (-180, 180] degrees. Without grouping:
exactly two measures (second measure minus first). With grouping:
exactly two groups (second factor level minus first) and at most one
measure -- one measure gives the group contrast on that measure's
latent profile, none gives the latent mean-path group contrast. The
group contrast is invariance-gated; see invariance.
Optional. The measurement-model tier passed to
ssm_sem_syntax(): "scaled" (default) or "strict".
Optional. The highest invariance rung to fit and REPORT
("configural", "metric", "scalar", or "strict_residuals").
NULL (default) uses the path's required rung: "metric" for the
measure-profile path, "scalar" for the latent mean path. A group
contrast is only computed if EVERY tested rung up through the path's
required rung is retained by lavaan's own nested test (the scaled
difference test under robust estimators) -- a rejection at any lower
rung rejects the constraints the contrast would be computed under.
Rungs fitted ABOVE the required one are reported but never gate the
contrast. On rejection, the returned object states the non-comparison
and reports each group's separate configural profile instead (no
contrast is rendered by any method). Under the strict tier the metric
rung is vacuous (all loadings fixed) and is reported as such.
The ladder table also reports dcfi, the change in CFI from the previous
fitted rung (NA for configural and for the strict tier's vacuous metric
rung), as a labeled secondary criterion: Cheung and Rensvold's (2002)
general rule rejects an invariance step when CFI drops by more than .01
(their alpha = .01). It is reported and never gates: comparable, the
verdict, and the fit the estimation layer consumes are decided by the
nested test alone, and the two criteria can legitimately disagree (a
change in CFI is insensitive to sample size where the nested test is not).
The retain/reject label prints only inside the envelope that simulation
covers: exactly two groups, ML estimation, and a plain (non-robust) CFI.
Three separate things put a fit outside it, and the printed note names
which one applies. A robust estimator -- the default "MLR", or "MLM"
-- makes lavaan report a robust CFI; so does missing = "fiml", even
under estimator = "ML", so plain ML is necessary for the label but not
sufficient. "GLS", "WLS", "ULS" and "DWLS" are not ML estimation
at all, though their CFI is plain-named. And more than two groups is
outside the simulation whatever the estimator. In each case the dcfi
value still prints, marked as not validated for that configuration and
with no verdict attached.
Cheung and Rensvold simulated two groups, ML estimation, multivariate normal data, and Type I error only; robust CFI variants were not in their study, so no cutoff here was validated for one.
Optional. The alpha level for the invariance gating decision (default = 0.05). The gate is a modeling decision with a default test, not an oracle; the invariance table is always returned so other criteria can be applied.
Optional. How to generate parameter replicates: "mvn"
(default) draws from a multivariate normal with lavaan's asymptotic
covariance of the free parameters (fast; one model fit); "boot" refits
the model on boots bootstrap resamples via
lavaan::bootstrapLavaan() (slow; robust to the normal approximation).
Both engines feed the same in-package interval machinery.
Optional. A single positive whole number indicating how many draws or bootstrap refits to use (default = 2000).
Optional. A single number between 0 and 1 (exclusive) indicating the confidence level (default = 0.95).
Optional. The lavaan estimator (default = "MLR": maximum
likelihood with robust "Huber-White" standard errors and a scaled test
statistic, the standard choice for the skewed distributions typical of
circumplex scale scores). The parameter estimates are identical to
"ML"; what changes is the covariance the "mvn" engine propagates
(already robust via se) and the test statistic behind the global fit
indices that print() reports (robust/scaled versions are used when
available).
Optional. The lavaan standard-error method for the fitted model
(default = "robust.huber.white", the sandwich estimator). This does not
affect the parameter estimates, only the covariance the "mvn" engine
propagates: the fixed-angle measurement model is an approximation for
real data, and the package's coverage validation found that
sandwich-based draws keep the intervals calibrated for the
model-conditional estimand under that misspecification where the plain
ML covariance undercovers (displacement ~0.88 instead of 0.95, not
improving with n). Set se = "standard" for the classical ML
covariance.
Optional. Either "listwise" (default; complete cases) or
"fiml" (full-information maximum likelihood via lavaan's
missing = "ml").
Optional. Passed to lavaan::bootstrapLavaan() when
ci_method = "boot" (defaults "no" and 1): the bootstrap refits are
independent and can be distributed across cores. Results for a given
set.seed() are reproducible regardless of these settings (the seed
lavaan receives drives its own parallel-safe RNG streams). Ignored by
the "mvn" engine.
Optional. Additional arguments passed to lavaan::cfa() (e.g.,
bounds or estimator-control settings).
This function consumes R's random number stream for both ci_method
settings ("mvn" through the package's own draws; "boot" through a
seed handed to lavaan's bootstrap). Call set.seed() immediately before
ssm_sem() for reproducible confidence intervals.
The latent profile of a measure is its vector of model-implied
disattenuated correlations with each scale's common (circumplex)
content: the scale's error and unique parts are removed from the
denominator, and the covariance is restricted to common content in the
numerator. All latent quantities are conditional on the fixed-angle
measurement model being adequate: global fit is reported by print(), and
a poorly fitting measurement model makes the latent SSM parameters
uninterpretable, not merely imprecise. The fixed angles are theoretical
claims, not estimates (use cpm_fit() to examine an instrument's real
geometry). Latent displacement is the first-harmonic direction of the
saturation-modulated disattenuated profile -- heterogeneous scale
saturations rotate it exactly as they rotate the observed displacement;
the latent layer removes the reliability modulation, nothing more.
Model-implied disattenuated correlations at or beyond 1 indicate
misspecification and are refused rather than summarized.
The point estimates and intervals are reported for elevation, x-value,
y-value, amplitude, and displacement (no standard errors are printed
anywhere, matching the package's estimate-plus-interval reporting surface).
Unlike ssm_analyze()'s closed-form estimator, the latent transform is the
ordinary-least-squares projection onto the cosine basis, so for unequally
spaced angles the two functionals genuinely differ (they coincide exactly
for equally spaced angles, and more generally under first- and
second-harmonic balance); under OLS the fit value is a bounded R-squared in
[0, 1] at any spacing.
With grouping, the latent contrast this function computes and the observed
contrast that ssm_analyze() computes answer different questions and are not
substitutes. The observed contrast (ssm_analyze() with grouping) asks
whether the groups' measured profiles differ: it is a difference of SSM
parameters computed from each group's observed scores or correlations. It
confounds structural difference, differential reliability, and measurement
non-invariance -- that is a property of its estimand, documented rather than
a defect, and it requires no invariance assumption. The latent contrast
(ssm_sem() with grouping) asks whether the groups' constructs differ,
granted the instrument measures the same thing in both groups: it is a
contrast on latent SSM parameters computed under cross-group equality
constraints, disattenuated and conditional on measurement invariance. When
the required invariance rung is rejected the latent contrast is not "more
principled" -- it is misspecified, and the function therefore returns an
explicit non-comparison (the verdict plus each group's separate configural
profile; no contrast is computed or rendered by any method). Neither estimand
replaces the other; they answer different questions and can legitimately
disagree.
The displacement contrast is reported as the second group level minus the
first, in (-180, 180] degrees, with branch-aligned circular intervals
(endpoints may legitimately exceed +/-180 degrees near the boundary). Under
the scaled tier the general-plane covariances are fixed to zero in all groups
at all rungs (a stationarity-type assumption): a cross-group difference in a
general factor's lean into the plane surfaces as misfit, and the strict tier
is the tier that can express it. Under the strict tier the metric rung is
vacuous (all loadings fixed) and is reported as such.
Cheung, G. W., & Rensvold, R. B. (2002). Evaluating
goodness-of-fit indexes for testing measurement invariance.
Structural Equation Modeling, 9(2), 233-255. (The dcfi secondary
criterion. Their p. 251 sentence states the direction of the -.01 rule
backwards relative to their own Table 5, whose critical values are the 1%
lower tails of the simulated null distributions; this package follows the
simulation.)
ssm_analyze() for the observed-score SSM, ssm_sem_syntax() for
the generated measurement model, and ssm_sem_parameters() to reuse a
lavaan fit you have modified or fitted yourself.
Other ssm functions:
plot.circumplex_ci_accuracy(),
ssm_analyze(),
ssm_analyze_long(),
ssm_ci_accuracy(),
ssm_draws(),
ssm_parameters(),
ssm_parameters_id(),
ssm_score(),
ssm_sem_parameters(),
ssm_table(),
summary.circumplex_ssm_id()
Other analysis functions:
cpm_fit(),
cpm_simulate(),
ssm_analyze(),
ssm_analyze_long(),
ssm_ci_accuracy(),
ssm_draws(),
ssm_parameters(),
ssm_parameters_id(),
ssm_score(),
ssm_sem_parameters(),
summary.circumplex_ssm_id()
if (FALSE) { # requireNamespace("lavaan", quietly = TRUE)
# \donttest{
data("jz2017")
set.seed(12345)
res <- ssm_sem(
jz2017,
scales = c("PA", "BC", "DE", "FG", "HI", "JK", "LM", "NO"),
measures = "NARPD",
boots = 500
)
res
summary(res)
# }
}
Run the code above in your browser using DataLab