View source: R/model_exchangeable_covariance.R
| recover_exchangeable_covariance | R Documentation |
Back-transforms covariance matrices from paired shared and member-difference random-effect blocks to the covariance structure of two exchangeable members. The result is on the fitted random effects' linear-predictor scale. In non-Gaussian models, it therefore describes a Gaussian latent covariance, not response-scale residual covariance. For the model specification, derivation, and interpretation, see the exchangeable APIM vignette.
recover_exchangeable_covariance(
model,
block_pairings = NULL,
posterior = c("mean", "median", "draws")
)
model |
A fitted |
block_pairings |
|
posterior |
For |
Automatic matching recognizes the compact .member_contrast_arbitrary and
composition-qualified .member_contrast_*_arbitrary names. It first looks
for the corresponding .is_* shared block. It requires
the two blocks to use the same grouping factor and the same underlying
terms. Most models fitted with dyadMLM-generated columns therefore need
only:
result <- dyadMLM::recover_exchangeable_covariance(model) print(result)
Supply block_pairings when automatic matching is ambiguous or when a
model uses custom indicators or deliberately omitted blocks or terms.
To specify one pair with a custom difference indicator:
result <- dyadMLM::recover_exchangeable_covariance(
model,
block_pairings = list(
shared_block = "(1 + time | coupleID)",
difference_block = "(0 + my_diff + I(my_diff * time) | coupleID)",
difference_indicator = "my_diff"
)
)
For multiple covariance levels, wrap the pairings in an outer list. For example,
in a Gaussian glmmTMB model fitted with dispformula = ~ 0, this call
recovers both a stable dyad-level covariance with an omitted difference
time slope and the same-occasion partner residual covariance:
result <- dyadMLM::recover_exchangeable_covariance(
model,
block_pairings = list(
dyad = list(
shared_block = "(1 + diaryday | coupleID)",
difference_block = "(0 + .member_contrast_arbitrary | coupleID)",
difference_indicator =
".member_contrast_arbitrary"
),
same_occasion = list(
shared_block = "(1 | coupleID:diaryday)",
difference_block = "(0 + .member_contrast_arbitrary | coupleID:diaryday)",
difference_indicator =
".member_contrast_arbitrary"
)
)
)
At the dyad level, the fitted model includes a shared time slope but no
difference time slope. Thus, the two members' time random effects are
identical at this level, with correlation +1 whenever the shared slope
variance is non-zero; at zero variance, the correlation is undefined.
Covariances involving the diary-day slope are therefore supplied entirely by
the shared block.
The random-effect terms may be copied exactly from the model formula.
Equivalent backend syntax is also recognized, such as
(1 + time | group) and us(1 + time | group), or
(0 + x || group) and diag(0 + x | group). A custom difference-indicator
name is supplied literally. Difference slopes may be written in either
interaction order or as a simple product inside I().
When a difference block is supplied and the fitted model frame retains the
indicator columns, difference_indicator must assign -1 and +1 to the
two arbitrary member positions consistently within each dyad. For
composition-specific blocks, it must be zero where shared_indicator is
zero.
The function checks whether both positions occur within each supported
fitted grouping unit. It rejects coding when no group contains both
positions. For custom difference indicators supplied through
block_pairings, it also warns when only some groups are one-sided, which
can result from fitted-row filtering, and when stable member assignments
cannot be verified across repeated rows without a member identifier.
An exchangeable_covariance object: a named list with one element per
matched block pairing. Each element contains shared_term and
difference_term (each a fitted term string or NULL), plus the member-level
variance-covariance matrix in varcov and its standard-deviation/correlation
representation in sdcor, with standard deviations on the diagonal and
correlations off the diagonal. Covariance dimension labels member_1 and
member_2 denote arbitrary exchangeable positions, not substantive roles
or encodings. Caller-supplied outer names are preserved; unnamed pairings
receive stable names pair_1, pair_2, and so on in resolved order.
varcov and sdcor are matrices, except when posterior = "draws" for a
brms model, where they are draw by coefficient by coefficient arrays.
brms quantities are transformed draw by draw before summarizing.
recover_exchangeable_covariance() only describes constraints that were already imposed
when the model was fitted. It does not remove a block, set a variance to zero,
or otherwise constrain the supplied model. Describe only the structure that
was actually fitted.
If a term occurs in only one selected block, the function represents the missing coordinate as a structural zero:
A term present only in the shared block has no difference component, so the two members have identical random effects for that term.
A term present only in the difference block has no shared component, so the two members have equal-magnitude, opposite-sign random effects for that term.
Setting difference_block = NULL or shared_block = NULL applies the corresponding rule
to the entire omitted block. This is valid only when that block is truly
absent from the fitted model. Do not use NULL merely to ignore an existing
block; the resulting back-transformation would be incorrect.
See the constrained-block example in the exchangeable APIM vignette.
For glmmTMB, random effects in non-conditional components are ignored with
a warning. See the vignette's
extension to exchangeable random slopes
section for the manual calculation.
In brms, cross-sectional and same-occasion partner dependence can be
represented directly with
unstr(time = member_position, gr = residual_group). With Gaussian
outcomes, sigma ~ 1 supplies the common residual scale. For families
such as Poisson and negative binomial, unstr() adds a latent residual
scale and correlation on the linear-predictor scale.
Here,
member_position identifies the same two arbitrary positions within every
group, and residual_group identifies dyads in cross-sectional data or
dyad-occasions in longitudinal data. This direct specification applies when
one covariance structure is sufficient. Separate composition-specific
unstr() structures for mixed dyad types are not currently supported in a
standard single-response brms model. For Gaussian mixed-dyad residual
covariance, use glmmTMB. Shared/difference blocks remain relevant for
higher-level random effects and can represent latent link-scale covariance
in non-Gaussian models.
The
exchangeable APIM vignette
for the model specification, covariance derivation, and constrained-block
example. Run vignette("apim", package = "dyadMLM") to open the installed
version.
if (requireNamespace("glmmTMB", quietly = TRUE)) {
example_data <- prepare_dyad_data(
dyads_cross,
dyad = coupleID,
member = personID,
role = gender,
model_types = "none",
# All three observed compositions in `dyads_cross` are detected and retained
# by default. This example focuses on `female-female` dyads, so we restrict
# the analysis here.
keep_compositions = "female-female",
seed = 123
)
model <- glmmTMB::glmmTMB(
closeness ~ 1 +
us(1 | coupleID) +
us(0 + .member_contrast_arbitrary | coupleID),
dispformula = ~ 0,
data = example_data
)
recover_exchangeable_covariance(model)
}
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.