Calculate SSM parameters with confidence intervals (bootstrapped by
default, or Monte Carlo via method) for a variety of different analysis
types. Depending on what arguments are supplied, either mean-based or
correlation-based analyses will be performed, one or more groups will be
used to stratify the data, and contrasts between groups or measures will be
calculated.
Usage
ssm_analyze(
data,
scales = NULL,
angles = octants(),
measures = NULL,
grouping = NULL,
contrast = FALSE,
boots = 2000,
interval = 0.95,
listwise = TRUE,
measures_labels = NULL,
parallel = "no",
ncpus = 1,
method = "bootstrap",
occasions = NULL
)Arguments
- data
Required. A data frame or matrix containing at least circumplex scales.
- scales
Required unless
occasionsis supplied (the two are mutually exclusive). A character vector of column names, or a numeric vector of column indexes, fromdatathat contains the circumplex scale scores to be analyzed.- angles
Optional. A numeric vector containing the angular displacement of each circumplex scale included in
scales(in degrees). (default =octants()). The closed-form SSM estimator used here equals the ordinary-least-squares cosine fit for equally spacedangles(e.g., octants at 45-degree intervals) – more generally, for any angle set satisfying first- and second-harmonic balance. For angle sets violating that balance (generic unequally spaced sets), it is the conventional Gurtman estimator, not a least-squares fit, and the reported model fit is then no longer a bounded R-squared in[0, 1](it can fall below 0).- measures
Optional. Either
NULLor a character vector of column names fromdatathat contains one or more variables to be correlated with the circumplex scales and analyzed using correlation-based SSM analyses.- grouping
Optional. Either
NULLor a string that contains the column name fromdataof the variable that indicates the group membership of each observation.- contrast
Optional. A logical indicating whether to output the difference between two measures', two groups', or two occasions' SSM parameters. Can only be set to TRUE when exactly one of these holds: two measures and one group; one measure and two groups; no measures and two groups; or two occasions and one group (default = FALSE). The contrast is always the second level minus the first. For two groups, this is the second level of
groupingalphabetically, unlessgroupingis already a factor with an explicit level order, in which case that order is used. For two measures, this is simply the second entry ofmeasuresas given (no reordering). For two occasions, it is the second listed element ofoccasionsminus the first (list order as supplied – temporal order – never alphabetical). The direction is shown in the result's Label (e.g., "Male - Female").- boots
Optional. A single positive whole number indicating how many bootstrap resamples (or, when
method = "montecarlo", Monte Carlo draws) to use when estimating the confidence intervals (default = 2000).- interval
Optional. A single positive number between 0 and 1 (exclusive) that indicates what confidence level to use when estimating the confidence intervals (default = 0.95).
- listwise
Optional. A logical indicating whether missing values should be handled by listwise deletion (TRUE) or pairwise deletion (FALSE). Note that pairwise deletion may result in different missing data patterns in each bootstrap resample and is slower to compute (default = TRUE). Occasions analyses require
listwise = TRUE: a person missing any occasion is dropped from all occasions (complete cases across waves), so the paired contrast stays a within-person comparison. Note the selection caution: complete-cases-across-waves estimates completers' change, which can differ from population change when dropout relates to the outcome.- measures_labels
Optional. Either
NULLor a character vector providing a label for each measure provided inmeasures(in the same order) to appear in the results as well as tables and plots derived from the results.- parallel
Optional. A string indicating whether to distribute the bootstrap computation across multiple CPU cores: "no" (default), "multicore" (process forking; available on macOS and Linux, ignored on Windows), or "snow" (a local PSOCK cluster; available on all platforms). Passed to
boot. Because the bootstrap resample indices are drawn in the main R process before any work is distributed, results for a givenset.seed()are identical regardless of theparallelandncpussettings.- ncpus
Optional. A single positive whole number indicating how many CPU cores to use when
parallelis not "no" (default = 1).- method
Optional. A string indicating how to estimate the confidence intervals: "bootstrap" (default) resamples the data, whereas "montecarlo" draws parameter replicates from the asymptotic sampling distribution of the group mean vector (mean-based analyses) or the measure-scale correlation vector (correlation-based analyses) – a multivariate normal with empirically estimated covariance – and propagates them through the SSM parameter transformation. The Monte Carlo method is much faster for large samples but relies on the asymptotic normality of the means or correlations, so prefer the bootstrap for small samples; it also requires listwise-complete data. Correlations are drawn jointly across measures within each group on the Fisher z scale and back-transformed. The
parallelandncpusarguments apply only to the bootstrap.- occasions
Optional. Either
NULLor a named list of character or numeric vectors, each selecting the same circumplex scales measured at one occasion, in the same scale order, all of lengthlength(angles)(e.g.,occasions = list(T1 = c("PA_1", ..., "NO_1"), T2 = c("PA_2", ..., "NO_2"))). Mutually exclusive withscales(and not combinable withmeasures). Data must be wide – one row per person – so persons remain the resampling unit and within-person dependence across occasions is preserved in both engines. Results gain anOccasioncolumn (labels arenames(occasions), defaulting toT1..Tk); this column is present only for occasions analyses. Grouping is time-invariant by construction (one group per person-row). Cross-occasion column alignment is validated by stem matching; when the columns have no common stem structure, positional alignment is assumed and messaged.
Value
A list containing the results and description of the analysis.
- results
A data frame with the SSM parameter estimates
- details
A list with the number of bootstrap resamples or Monte Carlo draws (boots), the confidence interval percentage level (interval), the angular displacement of scales (angles), and the interval estimation method (method)
- call
A language object containing the function call that created this object
- scores
A data frame containing the mean scale scores
- type
A string indicating what type of SSM analysis was done
The profile displacement parameter is reported in the half-open interval
[0, 360) degrees. A profile that peaks exactly at the 0/360 degree
boundary is reported as approximately 360 (equivalently 0, the same
direction); which of the two appears is a floating-point detail and both
denote the same pole. A displacement confidence-interval endpoint that
lands exactly on that pole is always reported as 360 (never 0), matching
the package's LM = 360 labeling. Contrast displacements are instead
reported as a signed difference in (-180, 180] degrees (see the
"Contrast" block in the printed output).
Degenerate profiles (flat or zero-amplitude) have undefined displacement
(and fit, if flat), which is reported as NA with a warning. Bootstrap
resamples that produce degenerate profiles (e.g., a resampled measure
with zero variance) are excluded from the confidence intervals with a
warning reporting how many were dropped; the intervals are then
conditional on estimability.
[0, 360)degrees. A profile that peaks exactly at the 0/360 degree boundary is reported as approximately 360 (equivalently 0, the same direction); which of the two appears is a floating-point detail and both denote the same pole. A displacement *confidence-interval endpoint* that lands exactly on that pole is always reported as 360 (never 0), matching the package's LM = 360 labeling. Contrast displacements are instead reported as a signed difference in(-180, 180]: R:0,%20360)%60%20degrees.%20A%20profile%20that%20peaks%20exactly%20at%20the%200/360%20degree%0A%20%20boundary%20is%20reported%20as%20approximately%20360%20(equivalently%200,%20the%20same%0A%20%20direction);%20which%20of%20the%20two%20appears%20is%20a%20floating-point%20detail%20and%20both%0A%20%20denote%20the%20same%20pole.%20A%20displacement%20confidence-interval%20endpoint%20that%0A%20%20lands%20exactly%20on%20that%20pole%20is%20always%20reported%20as%20360%20(never%200),%20matching%0A%20%20the%20package's%20LM%20=%20360%20labeling.%20Contrast%20displacements%20are%20instead%0A%20%20reported%20as%20a%20signed%20difference%20in%20%60(-180,%20180
Reproducibility
This function consumes R's random number stream (so do
cpm_fit(ci_method = "bootstrap"), cpm_simulate(), and
ssm_ci_accuracy(); ssm_score()/ssm_parameters() and the tidying
functions are deterministic). Call set.seed() immediately before
ssm_analyze() for reproducible confidence intervals:
Bootstrap (
method = "bootstrap", the default): the same seed gives byte-identicalresults, regardless of theparallel/ncpussettings (see their descriptions below), becauseboot::boot()draws all resample indices from the seed before any work is parallelized.Monte Carlo (
method = "montecarlo"): the same seed gives byte-identicalresults. Adding a group or measure, or reorderingscales/measures, changes the random draw sequence, so results are reproducible for a fixed call but will not match after such structural edits even with the same seed.The two methods are not expected to agree numerically for the same seed – they consume the random stream in unrelated ways. Their statistical agreement (validated on real data; see
vignette("introduction-to-ssm-analysis")) is a separate property from RNG reproducibility.Increasing
bootschanges the CI by design (more resamples/draws should tighten Monte Carlo error), so results are not expected to be stable across differentbootsvalues, only within a fixed call.
Occasions (repeated measures)
Supplying occasions analyzes the same circumplex scales measured at
k >= 2 occasions on the same persons (wide data, one row per person).
Each occasion yields its own profile row; with contrast = TRUE
(exactly 2 occasions, single group) the paired within-person contrast
is estimated with both engines preserving the within-person dependence
(the bootstrap resamples persons; the Monte Carlo engine draws the
stacked occasion mean vectors jointly).
Interpretation notes. A paired displacement-contrast CI is interpretable only when both occasions' amplitudes are reliably nonzero (both profiles print without the amplitude note); if only one occasion's profile is interpretable, do not read the contrast as directional change. Paired designs are not unconditionally more efficient than independent groups: the paired elevation contrast has a narrower CI exactly when the within-person elevation correlation is positive, while for the amplitude and displacement contrasts the paired CI is narrower only when the gradient-projected cross-occasion covariance is positive – under isotropic dependence this is proportional to cos(displacement change), so paired CIs are narrower for displacement changes under 90 degrees and can be wider than independent-groups CIs for changes beyond 90 degrees, even with strongly positive within-person correlation.
With method = "montecarlo" the per-group draw has dimension k x p
(occasions times scales); group sizes should comfortably exceed k x p
for the asymptotic covariance to be well estimated (the percentile
bootstrap is the safer small-sample choice). Grouping is time-invariant
by construction (one group per person-row).
See also
Other ssm functions:
plot.circumplex_ci_accuracy(),
ssm_analyze_long(),
ssm_ci_accuracy(),
ssm_draws(),
ssm_parameters(),
ssm_parameters_id(),
ssm_score(),
ssm_sem(),
ssm_sem_parameters(),
ssm_table(),
summary.circumplex_ssm_id()
Other analysis functions:
cpm_fit(),
cpm_simulate(),
ssm_analyze_long(),
ssm_ci_accuracy(),
ssm_draws(),
ssm_parameters(),
ssm_parameters_id(),
ssm_score(),
ssm_sem(),
ssm_sem_parameters(),
summary.circumplex_ssm_id()
Examples
# Load example data
data("jz2017")
# Single-group mean-based SSM
ssm_analyze(
jz2017,
scales = c("PA", "BC", "DE", "FG", "HI", "JK", "LM", "NO")
)
#>
#> # Profile [All]:
#>
#> Estimate Lower CI Upper CI
#> Elevation 0.917 0.889 0.946
#> X-Value 0.351 0.324 0.378
#> Y-Value -0.252 -0.281 -0.224
#> Amplitude 0.432 0.402 0.461
#> Displacement 324.292 320.751 327.676
#> Model Fit 0.878
#>
# Single-group correlation-based SSM
ssm_analyze(
jz2017,
scales = c("PA", "BC", "DE", "FG", "HI", "JK", "LM", "NO"),
measures = c("NARPD", "ASPD")
)
#>
#> # Profile [NARPD]:
#>
#> Estimate Lower CI Upper CI
#> Elevation 0.202 0.169 0.237
#> X-Value -0.062 -0.094 -0.028
#> Y-Value 0.179 0.145 0.214
#> Amplitude 0.189 0.155 0.226
#> Displacement 108.967 99.002 118.680
#> Model Fit 0.957
#>
#>
#> # Profile [ASPD]:
#>
#> Estimate Lower CI Upper CI
#> Elevation 0.124 0.090 0.157
#> X-Value -0.099 -0.134 -0.064
#> Y-Value 0.203 0.168 0.240
#> Amplitude 0.226 0.190 0.266
#> Displacement 115.927 107.286 124.541
#> Model Fit 0.964
#>
# Monte Carlo confidence intervals (faster for large samples)
ssm_analyze(
jz2017,
scales = c("PA", "BC", "DE", "FG", "HI", "JK", "LM", "NO"),
method = "montecarlo"
)
#>
#> # Profile [All]:
#>
#> Estimate Lower CI Upper CI
#> Elevation 0.917 0.889 0.945
#> X-Value 0.351 0.323 0.379
#> Y-Value -0.252 -0.282 -0.223
#> Amplitude 0.432 0.403 0.463
#> Displacement 324.292 320.840 327.907
#> Model Fit 0.878
#>
# \donttest{
# Multiple-group mean-based SSM
ssm_analyze(
jz2017,
scales = c("PA", "BC", "DE", "FG", "HI", "JK", "LM", "NO"),
grouping = "Gender"
)
#>
#> # Profile [Female]:
#>
#> Estimate Lower CI Upper CI
#> Elevation 0.946 0.908 0.983
#> X-Value 0.459 0.419 0.497
#> Y-Value -0.310 -0.353 -0.265
#> Amplitude 0.554 0.509 0.598
#> Displacement 325.963 322.036 329.958
#> Model Fit 0.889
#>
#>
#> # Profile [Male]:
#>
#> Estimate Lower CI Upper CI
#> Elevation 0.884 0.843 0.926
#> X-Value 0.227 0.194 0.261
#> Y-Value -0.186 -0.227 -0.149
#> Amplitude 0.294 0.259 0.331
#> Displacement 320.685 313.535 327.870
#> Model Fit 0.824
#>
# Multiple-group mean-based SSM with contrast
ssm_analyze(
jz2017,
scales = c("PA", "BC", "DE", "FG", "HI", "JK", "LM", "NO"),
grouping = "Gender",
contrast = TRUE
)
#>
#> # Profile [Female]:
#>
#> Estimate Lower CI Upper CI
#> Elevation 0.946 0.906 0.985
#> X-Value 0.459 0.419 0.499
#> Y-Value -0.310 -0.354 -0.269
#> Amplitude 0.554 0.509 0.601
#> Displacement 325.963 322.085 329.738
#> Model Fit 0.889
#>
#>
#> # Profile [Male]:
#>
#> Estimate Lower CI Upper CI
#> Elevation 0.884 0.843 0.926
#> X-Value 0.227 0.190 0.262
#> Y-Value -0.186 -0.224 -0.149
#> Amplitude 0.294 0.255 0.332
#> Displacement 320.685 313.633 327.912
#> Model Fit 0.824
#>
#>
#> # Contrast [Male - Female]:
#>
#> Estimate Lower CI Upper CI
#> Δ Elevation -0.062 -0.117 -0.004
#> Δ X-Value -0.232 -0.285 -0.179
#> Δ Y-Value 0.124 0.066 0.180
#> Δ Amplitude -0.261 -0.318 -0.200
#> Δ Displacement -5.278 -13.287 2.978
#> Δ Model Fit -0.066
#>
# Single-group correlation-based SSM with contrast
ssm_analyze(
jz2017,
scales = c("PA", "BC", "DE", "FG", "HI", "JK", "LM", "NO"),
measures = c("NARPD", "ASPD"),
contrast = TRUE
)
#>
#> # Profile [NARPD]:
#>
#> Estimate Lower CI Upper CI
#> Elevation 0.202 0.170 0.233
#> X-Value -0.062 -0.097 -0.029
#> Y-Value 0.179 0.145 0.213
#> Amplitude 0.189 0.154 0.225
#> Displacement 108.967 99.181 119.113
#> Model Fit 0.957
#>
#>
#> # Profile [ASPD]:
#>
#> Estimate Lower CI Upper CI
#> Elevation 0.124 0.090 0.159
#> X-Value -0.099 -0.134 -0.064
#> Y-Value 0.203 0.165 0.239
#> Amplitude 0.226 0.189 0.265
#> Displacement 115.927 107.395 124.309
#> Model Fit 0.964
#>
#>
#> # Contrast [ASPD - NARPD]:
#>
#> Estimate Lower CI Upper CI
#> Δ Elevation -0.079 -0.114 -0.042
#> Δ X-Value -0.037 -0.074 0.002
#> Δ Y-Value 0.024 -0.014 0.061
#> Δ Amplitude 0.037 -0.001 0.075
#> Δ Displacement 6.960 -3.617 17.108
#> Δ Model Fit 0.007
#>
# Multiple-group correlation-based SSM
ssm_analyze(
jz2017,
scales = c("PA", "BC", "DE", "FG", "HI", "JK", "LM", "NO"),
measures = "NARPD",
grouping = "Gender"
)
#>
#> # Profile [NARPD: Female]:
#>
#> Estimate Lower CI Upper CI
#> Elevation 0.172 0.128 0.217
#> X-Value -0.080 -0.126 -0.034
#> Y-Value 0.202 0.152 0.249
#> Amplitude 0.217 0.166 0.266
#> Displacement 111.669 99.779 123.161
#> Model Fit 0.972
#>
#>
#> # Profile [NARPD: Male]:
#>
#> Estimate Lower CI Upper CI
#> Elevation 0.244 0.192 0.296
#> X-Value -0.029 -0.075 0.014
#> Y-Value 0.146 0.098 0.191
#> Amplitude 0.149 0.105 0.196
#> Displacement 101.248 84.330 119.449
#> Model Fit 0.902
#>
# Multiple-group correlation-based SSM with contrast
ssm_analyze(
jz2017,
scales = c("PA", "BC", "DE", "FG", "HI", "JK", "LM", "NO"),
measures = "NARPD",
grouping = "Gender",
contrast = TRUE
)
#>
#> # Profile [NARPD: Female]:
#>
#> Estimate Lower CI Upper CI
#> Elevation 0.172 0.128 0.217
#> X-Value -0.080 -0.128 -0.038
#> Y-Value 0.202 0.152 0.249
#> Amplitude 0.217 0.167 0.269
#> Displacement 111.669 100.674 123.270
#> Model Fit 0.972
#>
#>
#> # Profile [NARPD: Male]:
#>
#> Estimate Lower CI Upper CI
#> Elevation 0.244 0.192 0.296
#> X-Value -0.029 -0.074 0.013
#> Y-Value 0.146 0.099 0.192
#> Amplitude 0.149 0.103 0.196
#> Displacement 101.248 85.069 118.602
#> Model Fit 0.902
#>
#>
#> # Contrast [NARPD: Male - Female]:
#>
#> Estimate Lower CI Upper CI
#> Δ Elevation 0.072 0.003 0.140
#> Δ X-Value 0.051 -0.011 0.114
#> Δ Y-Value -0.056 -0.127 0.011
#> Δ Amplitude -0.068 -0.139 -0.001
#> Δ Displacement -10.421 -30.566 10.325
#> Δ Model Fit -0.071
#>
# }
