View source: R/predictive_checks_dependence.R
| check_partner_dependence | R Documentation |
A dyadic model should reproduce how much responses vary and how strongly
partners' responses are related. This check compares the observed response
variances and partner correlations with those of responses simulated from the
fitted model. This helps identify mismatches in the model's assumptions.
This check is especially useful when a less restricted model does not
converge and so cannot be used for model comparison. For repeated occasions,
supply
member and time.
check_partner_dependence(
simulations,
dyad,
role = NULL,
member = NULL,
time = NULL,
plot = TRUE,
response = c("model-centred", "raw"),
ask = NULL,
panels = TRUE,
data = NULL
)
simulations |
An object returned by |
dyad |
The dyad column name. Looked up first
in the fitted model frame, then in |
role |
The role column name. Looked up first
in the fitted model frame, then in |
member |
The column name identifying each member.
Only needed for repeated occasions, ignored without a |
time |
The column name identifying each occasion. Only needed for
repeated occasions. Requires |
plot |
If |
response |
|
ask |
Whether to pause between figures on an interactive device.
|
panels |
If |
data |
Optional: the unchanged data frame used to fit the model. Supply
it when |
The comparison plots (shown by default) are the main output. The
function invisibly returns a dyadMLM_partner_check object containing the
compositions table with pair counts and a statistics tibble for each
composition. Compositions with fewer than three complete dyads are skipped
and have NULL statistics. Each tibble has one observed row
followed by one row per simulation, identified by dataset. summary
compares each observed statistic with the middle 95% of its simulations
(lower, upper) and marks those outside it. Rows with missing dyad IDs
or roles and incomplete dyads are omitted with a warning. The object includes
omission counts and settings, and can be saved and plotted later.
With repeated occasions, compositions has a level column ("between"
or "within"), and each label ends with its level. Within-level rows count the
dyads that share at least one occasion.
Blue histograms show simulated summaries. Red lines mark observed values. Dashed lines enclose the middle 95% of simulations (no formal confidence intervals). The heading shows the dyad composition, its number of usable dyads, and the total across all compositions.
The top row compares:
Response SDs: one for each role, or one common SD for exchangeable members.
Partner correlation: how strongly partners' responses are related.
The bottom row shows the same information using dyad averages and half-differences:
Dyad-average SD: how much dyads differ in their average response.
Half-difference SD or RMS: each partner difference is divided by two. With distinct roles, the SD shows how much signed differences vary across dyads. For exchangeable members, the RMS (root mean square) shows their typical size, regardless of partner order.
Dyad-average/role-difference correlation: shown only for distinct roles, because it depends on how partners are ordered. Positive values indicate greater variance for the first named role. Negative values indicate greater variance for the second.
An observed value far from most simulated values may indicate that the model does not reproduce that feature of the data well. Even if simulated and observed values agree, this does not show that omitted dependence is negligible, especially with few dyads. The partner-dependence study illustrates how sample size affects detection when residual partner correlation is omitted.
Checking each composition separately can reveal differences hidden by
pooling. With few dyads in a composition, the simulated ranges are wide, so
its panels lack sensitivity.
Flags (observed values outside the middle 95%, marked * when printed) can
occur by chance, especially when checking several summaries.
They are a starting point for further investigation, not necessarily a
reason to reject the model. The
covariance-pooling study
illustrates detection and false alarms when checking each composition.
A flexible covariance model will usually reproduce features it estimated from
the same data. Agreement alone therefore does not establish good fit.
For example, pooled summaries (role = NULL) of a Gaussian model with an
unconstrained exchangeable covariance, as below, agree almost by construction.
Use a suitable model comparison to formally test a specific covariance
restriction when both models can be fitted (see compare_nested_models()).
With repeated occasions, partners can be related in two ways: in their
mean responses, and in being above or below their own means on the same
occasions. A model should reproduce both. With member and time,
every dataset (observed and simulated) is split into two levels after any
model-centring. Each level is checked like cross-sectional data:
Between: each member's mean over all their fitted occasions, paired within the dyad. Each dyad counts once.
Within: each response minus its member's mean, paired with the partner's deviation on the same occasion. Each shared occasion counts once.
An occasion without the partner still counts in the member's mean.
The within check is related to repeated-measures correlation (Bakdash & Marusich, 2017).
The longitudinal study examines detection and false alarms. With 50 or fewer dyads, the check often missed omitted partner covariance.
Known limitations and caveats:
A misfit at one level can also impact the other level's summaries, especially with few occasions (due to member means including occasion-level variance) or nonlinear links. Thus, both levels should be interpreted together.
Check dependence across occasions (e.g., autocorrelation) separately. If the model omits temporal dependence, its covariance estimates can be biased, and these checks may not reveal it.
These checks can be misleading when the model includes lagged outcomes as predictors.
After any centring, paired responses a and b are used to compute
dyad averages M = (a + b) / 2 and half-differences D = (a - b) / 2.
Roles follow factor levels or sorted values.
For exchangeable members, common member variance is var(M) + mean(D^2) and
partner covariance is var(M) - mean(D^2). Partner correlation is
covariance divided by variance. Half-difference RMS is sqrt(mean(D^2)).
The variance and covariance calculations for exchangeable dyads follow Woody and Sadler (2005).
Woody, E., & Sadler, P. (2005). Structural equation models for interchangeable dyads: Being the same makes a difference. Psychological Methods, 10(2), 139–158. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.1037/1082-989X.10.2.139")}
Bakdash, J. Z., & Marusich, L. R. (2017). Repeated measures correlation. Frontiers in Psychology, 8, 456. \Sexpr[results=rd]{tools:::Rd_expr_doi("10.3389/fpsyg.2017.00456")}
check_dyad_residuals(), check_dyad_outcomes()
# Data contains three compositions: female-female, female-male, and male-male.
example_data <- prepare_dyad_data(
dyads_cross,
dyad = coupleID,
member = personID,
model_types = "none",
seed = 123
)
# This model pools all compositions and treats every dyad as exchangeable.
model <- glmmTMB::glmmTMB(
closeness ~ 1 +
us(1 | coupleID) +
us(0 + .member_contrast_arbitrary | coupleID),
dispformula = ~ 0,
data = example_data
)
# Fewer simulations for a quick example (the default is 1000).
simulations <- simulate_dyad_responses(
model,
nsim = 100,
seed = 123
)
# Check whether pooling fits the data. Each composition is checked
# separately, with role-specific summaries for distinguishable compositions.
check_partner_dependence(
simulations,
dyad = coupleID,
role = gender,
# Supply the fitting data because gender is not in the model formula.
data = example_data
)
# Optionally, suppress plot, store object, and plot later.
check <- check_partner_dependence(
simulations,
dyad = coupleID,
role = gender,
data = example_data,
plot = FALSE
)
plot(check, ask = FALSE, panels = TRUE)
print(check)
# For repeated occasions, also supply `member` and `time`.
example_diary_data <- prepare_dyad_data(
dyads_ild[dyads_ild$coupleID <= 80, ], # Couples 1 to 80 are female-male.
dyad = coupleID,
member = personID,
role = gender,
time = diaryday,
model_types = "none",
seed = 123
)
diary_model <- glmmTMB::glmmTMB(
closeness ~ 0 + gender + gender:diaryday +
# In this example, we omit the correlation between partners' random
# intercepts on level 2 with a diagonal covariance structure. This is
# sometimes done when a model does not otherwise converge cleanly.
diag(0 + gender | coupleID) +
# Keep the full structure for the level 1 residuals.
us(0 + gender | coupleID:diaryday),
dispformula = ~ 0,
data = example_diary_data
)
# The between level flags the omitted partner correlation.
check_partner_dependence(
simulate_dyad_responses(diary_model, nsim = 100, seed = 123),
dyad = coupleID,
role = gender,
member = personID,
time = diaryday,
# Supply the fitting data because personID is not in the model formula.
data = example_diary_data
)
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.