Create an outcome generator for simulate_data(). Outcomes are simulated on
a Gaussian scale, optionally as ILR coordinates that are back-transformed to
strictly positive compositions. If ar1() appears in the location formula,
it defines a residual VAR(1) process, not an observed lagged-outcome
predictor.
Arguments
- formula
Outcome location formula. The left-hand side may be a single outcome (
y) ormvbind(y1, y2, ...). The right-hand side may include ordinary model terms,between(x),within(x),ar1(), interactions, and one brms/lme4-style grouping term.- scale
Required scale formula with
sigmaon the left-hand side, for examplesigma ~ 1orsigma ~ treatment + (1 | ID). The scale model is on the log conditional standard-deviation scale.- params
List of true parameters. Required components are
params$location$beta,params$scale$beta, and, for multivariate outcomes,params$scale$correlation. When AR terms are present,params$ar$betais required. When grouping terms are present,params$random[[group]]$covarianceis required.- burnin
Fixed non-negative integer burn-in length used when AR is active. Ignored when no AR terms are present.
- composition
List controlling optional ILR back-transformation. Use
partsorsbpto request compositional output,totalfor the closure total, andkeep_ilrto keep ILR coordinates alongside parts.- ar_stability
Handling for unstable AR matrices:
"resample","shrink", or"error".- max_stability_attempts
Positive integer maximum number of resampling or shrinkage attempts.
- shrink_target_radius
Target spectral radius used by
ar_stability = "shrink".
Value
An mlsim_generator_spec object for use in simulate_data().
Time spacing
When ar1() is present, time must be complete and equally spaced within
each participant (or within the single series). Participants may have
different start times, end times, and numbers of observations, and the
simulator does not check or enforce equal spacing between participants:
different participants may also use different step sizes. AR and VAR
coefficients are defined per observation step, not per unit of real time,
so dynamic parameters are only comparable across participants in real-time
units when all participants share the same step size.
AR stability and realized moderator draws
Stability is enforced through the row-wise spectral radius of the assembled
AR coefficient matrices for every observed row. When ar1() interacts with
predictors (for example within(stress):ar1()), the row-specific AR matrix
depends on the moderator values realized earlier in the generator pipeline.
Stability is therefore a property of the AR parameters jointly with the
realized predictor data, not of the parameters alone: the same AR parameter
values may be accepted in one simulated data set and rejected in another
with more extreme moderator draws, and the chance of an unstable row grows
with the number of rows. ar_stability = "resample" redraws only
group-level effects, so it cannot repair instability caused by the
population-level part of a moderated AR term; that case errors instead.
Performance
The simulator is written to scale to large designs without changing the data-generating model. Innovations are drawn in one vectorized step from the fixed conditional correlation matrix and scaled by the row-wise conditional SDs (an exact draw from the row-specific innovation distribution, since its covariance is the SD-scaled correlation matrix). Row-specific AR matrices are assembled with vectorized array operations, spectral radii are computed once per unique AR matrix so row-constant AR designs cost one eigendecomposition per participant, and stability resampling or shrinkage re-evaluates only the affected participant's rows. Because the order in which random numbers are consumed is part of the implementation, a given seed maps to a particular realization only within a package version; the distribution of simulated data is unaffected.
See also
Other predictor generators:
continuous-generators,
count-generators,
gen_categorical(),
gen_custom(),
gen_mvn(),
gen_template()
Examples
beta_location <- matrix(
c(0, 0, 0.2, -0.1),
nrow = 2,
dimnames = list(c("(Intercept)", "treatmenttreatment"), c("ilr1", "ilr2"))
)
beta_scale <- matrix(
log(c(0.4, 0.35)),
nrow = 1,
dimnames = list("(Intercept)", c("ilr1", "ilr2"))
)
beta_ar <- array(
c(0.25, 0.02, -0.01, 0.2),
dim = c(1, 2, 2),
dimnames = list("ar1()", c("ilr1", "ilr2"), c("ilr1", "ilr2"))
)
corr <- diag(2)
dimnames(corr) <- list(c("ilr1", "ilr2"), c("ilr1", "ilr2"))
sim <- simulate_data(
n_groups = 4,
n_per_group = 4,
group_id = "ID",
time_id = "day",
seed = 1,
generators = list(
treatment = gen_categorical(
"treatment",
level = "level2",
categories = c("control", "treatment"),
fixed_intercept = stats::qlogis(0.5)
),
outcome = gen_outcome(
mvbind(ilr1, ilr2) ~ treatment + ar1(),
scale = sigma ~ 1,
params = list(
location = list(beta = beta_location),
scale = list(beta = beta_scale, correlation = corr),
ar = list(beta = beta_ar)
),
burnin = 10,
composition = list(parts = c("sleep", "active", "sedentary"), total = 24)
)
)
)
head(sim$data)
#> ID obs_id day treatment ilr1 ilr2 sleep active
#> <int> <int> <int> <fctr> <num> <num> <num> <num>
#> 1: 1 1 1 control -0.2064913 -0.03609880 6.710760 8.424008
#> 2: 1 2 2 control -0.2868224 0.70699869 5.708368 13.371705
#> 3: 1 3 3 control -0.4443665 0.41099101 5.225170 12.041240
#> 4: 1 4 4 control -0.4260561 -0.05385306 5.488733 8.903350
#> 5: 2 1 1 control -0.1319125 0.28382912 7.062593 10.145892
#> 6: 2 2 2 control 0.7619243 0.47254122 13.108039 7.200856
#> sedentary
#> <num>
#> 1: 8.865232
#> 2: 4.919927
#> 3: 6.733590
#> 4: 9.607916
#> 5: 6.791514
#> 6: 3.691105