Draw J latent site effects from a user-supplied callback g_fn(J, ...)
under one of two conventions: Convention A (g_returns = "standardized",
the default) — the callback returns mean-0 unit-variance residuals
\(z_j\) that the package rescales by sigma_tau and shifts by
tau (and any covariate adjustment) to form tau_j. Convention B
(g_returns = "raw") — the callback returns response-scale effects
directly; the package leaves them untouched and back-derives z_j for
provenance.
Arguments
- J
Integer. Number of sites.
- tau
Numeric. Grand mean on the response scale. Default
0.- sigma_tau
Numeric (\(\ge 0\)). Between-site standard deviation on the response scale. Default
0.20.- g_fn
Function. Required user callback with signature
function(J, ...). Must return a finite numeric vector of lengthJ. Under Convention A, the vector should be mean-0 unit-variance; under Convention B, the vector is the response-scale effect directly.- g_returns
Character.
"standardized"(Convention A, default) — the callback returns standardized residuals \(z_j\) and the package rescales."raw"(Convention B) — the callback returns response-scaletau_jdirectly; the package back-derivesz_j.- formula
One-sided formula for site-level covariates, or
NULL.- beta
Numeric coefficient vector matching
formula, orNULL.- data
A
data.framewith the predictors named informula, orNULL.- g_args
Named list forwarded to
g_fnas extra arguments afterJ. Defaultlist().- audit_g
Logical. Whether to validate (Convention A only) that the callback's draws meet the unit-moment contract. Default
TRUE. No-op underg_returns = "raw".
Value
A tibble with one row per site and columns site_index
(integer 1:J), z_j (standardized residual; back-derived under
Convention B), tau_j (response-scale effect), plus any covariate
columns from data.
Details
Use the user callback when none of the seven built-in shapes (Gaussian, Student-t, skew-normal, ALD, mixture, point-mass slab, DPM) captures the effect distribution you need. Typical use cases: a DPM draw fitted offline, a custom skew-mixture, a deconvolution-derived empirical \(G\), or a numerical sampler from a non-standard distribution.
Convention A vs B. Convention A is the default and integrates
cleanly with downstream diagnostics
(informativeness, heterogeneity_ratio,
compute_shrinkage) without further work. Convention B is
for callbacks where standardization is meaningless or the package's
linear rescaling is not what you want; you carry the responsibility for
the scale. The package back-derives z_j = (tau_j - tau - X*beta) / sigma_tau
so downstream Layer 2 / 3 / 4 code still has a z_j column to reason
about.
Audit. When audit_g = TRUE (default) and
g_returns = "standardized", the package draws an extra 100,000-site
audit sample from g_fn (in a side RNG stream that does not disturb
the caller's state) and warns if the empirical mean is more than 0.1
off zero or the empirical variance is more than 0.1 off 1. This catches
the most common contract violations without aborting the run.
For the formal g_fn contract and worked examples, see the
Custom G distributions
vignette.
References
Lee, J., Che, J., Rabe-Hesketh, S., Feller, A., & Miratrix, L. (2025). Improving the estimation of site-specific effects and their distribution in multisite trials. Journal of Educational and Behavioral Statistics, 50(5), 731–764. doi:10.3102/10769986241254286 .
See also
gen_effects for the dispatcher and the full eight-shape
catalog;
gen_effects_dpm for the bridged DPM route;
gen_effects_gaussian and the seven built-in shapes;
the M5 Custom G
distributions vignette.
Other family-effects:
gen_effects(),
gen_effects_ald(),
gen_effects_dpm(),
gen_effects_gaussian(),
gen_effects_mixture(),
gen_effects_pmslab(),
gen_effects_skewn(),
gen_effects_studentt()
Examples
# Convention A: callback returns standardized residuals.
my_g <- function(J) rnorm(J) # mean 0, variance 1 by construction
gen_effects_user(J = 50L, g_fn = my_g)
#> # A tibble: 50 × 3
#> site_index z_j tau_j
#> <int> <dbl> <dbl>
#> 1 1 1.05 0.210
#> 2 2 -0.584 -0.117
#> 3 3 -0.527 -0.105
#> 4 4 -0.122 -0.0244
#> 5 5 -0.586 -0.117
#> 6 6 -0.248 -0.0496
#> 7 7 0.801 0.160
#> 8 8 2.53 0.505
#> 9 9 0.270 0.0540
#> 10 10 -0.886 -0.177
#> # ℹ 40 more rows
# Convention B: callback returns response-scale effects directly.
raw_g <- function(J) rnorm(J, mean = 0.3, sd = 0.15)
gen_effects_user(J = 50L, g_fn = raw_g, g_returns = "raw",
tau = 0.3, sigma_tau = 0.15)
#> # A tibble: 50 × 3
#> site_index z_j tau_j
#> <int> <dbl> <dbl>
#> 1 1 0.265 0.340
#> 2 2 0.317 0.348
#> 3 3 -0.149 0.278
#> 4 4 0.322 0.348
#> 5 5 -0.324 0.251
#> 6 6 -0.783 0.182
#> 7 7 -0.0181 0.297
#> 8 8 -0.169 0.275
#> 9 9 -0.165 0.275
#> 10 10 0.714 0.407
#> # ℹ 40 more rows
# Skipping the audit (deterministic callback at small J).
gen_effects_user(
J = 10L,
g_fn = function(J) seq(-1, 1, length.out = J),
audit_g = FALSE
)
#> # A tibble: 10 × 3
#> site_index z_j tau_j
#> <int> <dbl> <dbl>
#> 1 1 -1 -0.2
#> 2 2 -0.778 -0.156
#> 3 3 -0.556 -0.111
#> 4 4 -0.333 -0.0667
#> 5 5 -0.111 -0.0222
#> 6 6 0.111 0.0222
#> 7 7 0.333 0.0667
#> 8 8 0.556 0.111
#> 9 9 0.778 0.156
#> 10 10 1 0.2