Skip to contents

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 occasions is supplied (the two are mutually exclusive). A character vector of column names, or a numeric vector of column indexes, from data that 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 spaced angles (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 NULL or a character vector of column names from data that contains one or more variables to be correlated with the circumplex scales and analyzed using correlation-based SSM analyses.

grouping

Optional. Either NULL or a string that contains the column name from data of 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 grouping alphabetically, unless grouping is already a factor with an explicit level order, in which case that order is used. For two measures, this is simply the second entry of measures as given (no reordering). For two occasions, it is the second listed element of occasions minus 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 NULL or a character vector providing a label for each measure provided in measures (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 given set.seed() are identical regardless of the parallel and ncpus settings.

ncpus

Optional. A single positive whole number indicating how many CPU cores to use when parallel is 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 parallel and ncpus arguments apply only to the bootstrap.

occasions

Optional. Either NULL or 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 length length(angles) (e.g., occasions = list(T1 = c("PA_1", ..., "NO_1"), T2 = c("PA_2", ..., "NO_2"))). Mutually exclusive with scales (and not combinable with measures). 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 an Occasion column (labels are names(occasions), defaulting to T1..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-identical results, regardless of the parallel/ncpus settings (see their descriptions below), because boot::boot() draws all resample indices from the seed before any work is parallelized.

  • Monte Carlo (method = "montecarlo"): the same seed gives byte-identical results. Adding a group or measure, or reordering scales/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 boots changes the CI by design (more resamples/draws should tighten Monte Carlo error), so results are not expected to be stable across different boots values, 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).

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                      
#> 
# }