Dyad-Individual Model

knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)

diagram_helper <- if (file.exists("diagram-helpers.Rinc")) {
  "diagram-helpers.Rinc"
} else {
  file.path("vignettes", "diagram-helpers.Rinc")
}
sys.source(diagram_helper, envir = knitr::knit_global())

dim_grid_helper <- if (file.exists("dim-grid.Rinc")) {
  "dim-grid.Rinc"
} else {
  file.path("vignettes", "dim-grid.Rinc")
}
sys.source(dim_grid_helper, envir = knitr::knit_global())

diagram_device <- .vignette_diagram_device()
knitr::opts_chunk$set(
  dev = diagram_device,
  fig.ext = diagram_device,
  dev.args = list(bg = "transparent")
)
library(dyadMLM)
has_glmmTMB <- requireNamespace("glmmTMB", quietly = TRUE)
has_htmltools <- requireNamespace("htmltools", quietly = TRUE)
dim_fitted_alt <- "Fitted DIM diagram unavailable."

This vignette focuses on the Dyad-Individual Model (DIM) for dyadic multilevel models and its relationship to the exchangeable Actor-Partner Interdependence Model (APIM). The DIM separates a predictor into the dyad's shared level and each member's deviation from that level. While the APIM expresses effects in terms of two interdependent individuals, the DIM expresses them in terms of the dyad's shared level and the contrast between partners.

Under exchangeability constraints, the reduced, label-invariant DSM is also equivalent to the DIM, as discussed below. For the broader package workflow and an overview of the available model-specific vignettes, including the Actor-Partner Interdependence Model and Dyadic Score Model, see the online package overview.

Cross-Sectional Gaussian DIM

The current DIM implementation needs one exchangeable dyad composition. Exchangeability means that swapping the two member labels does not change the model [@kenny2006dyadic]. Whether roles can and should be treated as exchangeable is a substantive assumption (see Testing distinguishability in the APIM vignette).

Here, we retain the female-female dyads with keep_compositions. Because both members have the same role, this gives us one genuinely exchangeable dyad composition. Omitting role is another option when all dyads should be treated as one exchangeable composition. Refer to the Getting Started vignette for how to retain, pool, and constrain dyad compositions.

cross_exchangeable_data <- dyadMLM::prepare_dyad_data(
  dyads_cross,
  dyad = coupleID,
  member = personID,
  role = gender,
  predictors = provided_support,
  # Create both APIM and DIM columns for comparison.
  model_types = c("apim", "dim"),
  add_apim_gmc_predictors = TRUE,
  # 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
)

# Print the first two dyads.
print(cross_exchangeable_data, n = 4)

For the exchangeable random-effects specification, dyadMLM::prepare_dyad_data() creates a member-difference contrast .member_contrast_*, coded as +1 for one partner and -1 for the other. Because these member labels are arbitrary, setting seed makes their assignment reproducible.

Example DIM Model

Here $x_{ij}$ denotes provided support centered with the pooled mean from complete predictor pairs. prepare_dyad_data() creates the corresponding DIM dyad-mean column; using the original zero requires shifting it manually.

For member $i \in {1, 2}$ of dyad $j$, define the dyad mean and within-dyad member deviation as:

$$ \bar{x}j = \frac{x{1j} + x_{2j}}{2}, \qquad x_{\mathrm{dev},ij} = x_{ij} - \bar{x}_j. $$

Because each $x_{ij}$ uses the same grand-mean reference, $\bar{x}_j$ is already grand-mean centered. The within-dyad deviation is unchanged by this common shift.

APIM GMC uses all retained non-missing values, whereas DIM uses complete pairs. The constants agree here; with one-sided missingness, intercept references may differ although the slope reparameterization still holds.

The deviations of the two partners have equal magnitude and opposite signs: (x_{\mathrm{dev},1j} = -x_{\mathrm{dev},2j}). Outcome means and deviations are defined analogously. The variables that enter the DIM fixed effects then separate two associations:

  1. The between-dyad effect, $b_{\mathrm{mean}}$: whether dyads with a higher dyad mean than other dyads also have a higher outcome mean.
  2. The within-dyad effect, $b_{\mathrm{dev}}$: whether the member who is above the dyad's predictor mean is also above the dyad's outcome mean. With two members, each deviation is half the corresponding signed partner difference.

The dyad mean varies between dyads, whereas member deviations vary within a dyad. Accordingly, the upper path is the between-dyad effect and the lower path is the within-dyad effect. Switching members reverses both deviations and therefore leaves the pooled $b_{\mathrm{dev}}$ unchanged.

draw_dim_diagram()

Uncorrelated $r_{\mathrm{m}}$ and $r_{\mathrm{d},i}$ in the conceptual representation do not imply that the member residuals are independent: the two component variances together determine the covariance between the members' residuals.

The second diagram translates the same decomposition to the individual-member rows used by the long-format multilevel model. Each member's outcome is predicted by the dyad mean and that member's own within-dyad member deviation. Both members share the same two coefficients, so estimation pools information across members under the exchangeability assumptions.

draw_dim_member_diagram()

The resulting estimated fixed effects are a reparameterization of the APIM actor and partner effects [@Bolger2025Unified]. And just like the exchangeable APIM, the random-effects structure comprises a dyad-level intercept and a dyad-level difference contrast indexed by .member_contrast_arbitrary. In glmmTMB, with dispformula = ~ 0, these random effects represent the two members' Gaussian residual variance and covariance.

The intercept and difference contrast are specified as separate random-effects terms. No additional correlation is needed because the two residual variances already determine the partners' residual correlation. Under exchangeability, the mean-deviation residual correlation is therefore fixed to zero [@delrosarioPracticalGuideSpecifying2025].

The full model can be estimated as:

dim_1 <- glmmTMB::glmmTMB(
  closeness ~

    # Pooled fixed intercept
    1 +

    # Between-dyad effect
    .provided_support_dyad_mean_gmc +

    # Within-dyad effect
    .provided_support_within_dyad_dev +

    # Residual Gaussian covariance structure
    us(1 | coupleID) +
    us(0 + .member_contrast_arbitrary | coupleID)
  , dispformula = ~ 0
  , family = gaussian()
  , data = cross_exchangeable_data
)

summary(dim_1)

The same mean-and-deviation diagram can now be labelled with the estimated fixed effects and residual-component standard deviations:

dim_diagram_values <- .extract_dim_diagram_values(dim_1)
dim_diagram_estimates <- dim_diagram_values$estimates
dim_diagram_residuals <- dim_diagram_values$residuals

dim_fitted_alt <- sprintf(
  paste(
    "Fitted DIM. Intercept %.2f, between-dyad effect %.2f, within-dyad",
    "effect %.2f, and mean/deviation residual SDs %.2f and %.2f; their",
    "correlation is fixed at zero."
  ),
  dim_diagram_estimates[["b0"]],
  dim_diagram_estimates[["b_mean"]],
  dim_diagram_estimates[["b_dev"]],
  dim_diagram_residuals[["sd_mean"]],
  dim_diagram_residuals[["sd_difference"]]
)
draw_dim_diagram(
  model = dim_1,
  effect_unit = "dyad",
  labels = c(predictor = "provided support", outcome = "closeness")
)

Under these exchangeability constraints, the Gaussian DIM is algebraically equivalent to the reduced, label-invariant Dyadic Score Model (DSM) [@iidaModelsInterdependentIndividuals2018]. Compared to a full DSM, the DIM's exchangeability constraints fix the outcome-deviation intercept and both cross-paths to zero and constrain the mean and deviation residual components to be uncorrelated (see the diagrams here and compare them with the conceptual DSM diagrams).

Model interpretation

Therefore, each coefficient has both an individual-member interpretation and an equivalent dyad mean/difference interpretation.

In this Gaussian model, fixed coefficients are interpreted in units of the outcome, here closeness:

Because the Gaussian DIM is the exchangeability-constrained version of the full DSM, exchangeability can also be tested by comparing these nested models. This is equivalent to the comparison shown in Testing distinguishability in the APIM vignette.

Demonstrating model equivalence to APIM

The same model can be written in APIM form. Since we have requested both sets of variables from dyadMLM::prepare_dyad_data(), we can fit one directly. For more guidance on APIM specifications and different models, see the Actor-Partner Interdependence Model vignette.

apim_1 <- glmmTMB::glmmTMB(
  closeness ~ 1 +

    # Fixed effects APIM
    .provided_support_gmc_actor + .provided_support_gmc_partner +

    # Since both models are equivalent, the same random-effects structure
    # can be used. See the APIM vignette to learn how to back-transform
    # these blocks to a full actor-partner covariance matrix.
    us(1 | coupleID) +
    us(0 + .member_contrast_arbitrary | coupleID)
  , dispformula = ~ 0
  , family = gaussian()
  , data = cross_exchangeable_data
)

The two models have identical fit statistics:

data.frame(
  model = c("DIM", "APIM"),
  AIC = c(AIC(dim_1), AIC(apim_1)),
  BIC = c(BIC(dim_1), BIC(apim_1)),
  logLik = c(as.numeric(logLik(dim_1)), as.numeric(logLik(apim_1)))
)

This demonstrates that the same statistical model is being estimated with different parameterizations and coefficient interpretations.

Once APIM estimates are present, one can easily obtain DIM estimates, and the other way around. Let $b_{\mathrm{actor}}$ and $b_{\mathrm{partner}}$ denote the APIM actor and partner slopes, and let $b_{\mathrm{mean}}$ and $b_{\mathrm{dev}}$ denote the DIM between-dyad and within-dyad slopes. Complete pairs give the GMC APIM and DIM the same zero point, so the fixed effects transform as follows. With raw APIM predictors, only the intercept requires recentering.

The shared intercept is

$$ b_{0,\mathrm{DIM}} = b_{0,\mathrm{APIM}}. $$

The slopes relate as follows:

$$ b_{\mathrm{mean}} = b_{\mathrm{actor}} + b_{\mathrm{partner}} $$

and

$$ b_{\mathrm{dev}} = b_{\mathrm{actor}} - b_{\mathrm{partner}} $$

Conversely:

$$ b_{\mathrm{actor}} = \frac{b_{\mathrm{mean}} + b_{\mathrm{dev}}}{2} $$

and

$$ b_{\mathrm{partner}} = \frac{b_{\mathrm{mean}} - b_{\mathrm{dev}}}{2} $$

In this example we can see that the transformations work:

apim_coef <- glmmTMB::fixef(apim_1)$cond
dim_coef <- glmmTMB::fixef(dim_1)$cond

b0_apim <- apim_coef[["(Intercept)"]]
b_actor <- apim_coef[[".provided_support_gmc_actor"]]
b_partner <- apim_coef[[".provided_support_gmc_partner"]]

b0_dim <- dim_coef[["(Intercept)"]]
b_mean <- dim_coef[[".provided_support_dyad_mean_gmc"]]
b_dev <- dim_coef[[".provided_support_within_dyad_dev"]]


cat("From APIM model:\n",
     "  intercept:                     ", round(b0_apim, 3), "\n",
     "  actor effect:                  ", round(b_actor, 3), "\n",
     "  partner effect:                ", round(b_partner, 3), "\n\n",

     "DIM transformation:\n",
     "  b_mean = b_actor + b_partner:  ", round(b_actor + b_partner, 3), "\n",
     "  b_dev = b_actor - b_partner:   ", round(b_actor - b_partner, 3), "\n\n",

     "From DIM model:\n",
     "  intercept:                     ", round(b0_dim, 3), "\n",
     "  between-dyad effect:           ", round(b_mean, 3), "\n",
     "  within-dyad effect:            ", round(b_dev, 3), "\n"
)

The DIM and APIM intercepts are equal up to numerical estimation tolerance because both parameterizations now use the same grand-mean reference.

Why Are These Models Equivalent? Exploring the Reparameterization

An intuitive way to think about this is:

The grid below shows the same predictor values in both coordinate systems. The horizontal and vertical axes are actor and partner values centered at the sample grand mean. The diagonal axes are their dyad mean and within-dyad member deviation.

The displayed actor and partner slopes are read from the fitted APIM. The DIM slopes are their exact sum-and-difference transformation; the directly fitted DIM estimates above confirm the equivalence. Both forms therefore make the same change in the linear predictor relative to the grand-mean reference. The intercept is omitted from both displayed equations.

dim_reparameterization_grid(
  if (has_glmmTMB && exists("apim_1")) apim_1 else NULL,
  predictor_label = "Provided support",
  outcome_label = "the linear predictor",
  limit = 5
)

Random-effect transformation

The DIM and APIM models above already use the same sum-and-difference random-effects parameterization [@delrosarioPracticalGuideSpecifying2025]. See the exchangeable residual-structure section of the APIM vignette for the derivation and back-transformation to the member-level covariance matrix.

Checking partner dependence

We can check whether the fitted DIM reproduces the response variance and partner correlation by comparing observed and simulated data.

::: {.no-invert-dark-mode}

dim_simulations <- dyadMLM::simulate_dyad_responses(dim_1, seed = 123)
dyadMLM::check_partner_dependence(
  dim_simulations,
  dyad = coupleID,
  role = gender,
  # Supply the fitting data because gender is not in the model formula.
  data = cross_exchangeable_data
)

:::

The top row shows the common member SD and partner correlation. The bottom row shows the same information using dyad averages and half the differences between partners. Histograms show simulated values and red lines mark observed values. A red line far from most simulations suggests a mismatch.

By default, the check subtracts the model's fixed-effect predictions from observed and simulated responses. Good agreement is often expected for variances and correlations estimated from the same data. See the function help for details and interpretation. Simulation studies show how often the check detects omitted partner dependence and incorrect covariance pooling, and how often it raises false alarms. For intensive longitudinal data, also supply member and time. A separate study covers this case.

The same dim_simulations can be checked with check_dyad_residuals() and check_dyad_outcomes(), as shown in the APIM vignette.

Intensive Longitudinal DIM

For longitudinal DIM, predictors are decomposed into within-person and between-person components before the dyadic decomposition [@bolgerIntensiveLongitudinalMethods2013; @gistelinckMultilevelAutoregressiveDyadic2020]. The default "auto" selects "2l" when both time and predictors are supplied. It also retains raw dyad-occasion means and within-dyad member deviations. The decomposed columns used below are:

  1. The cwp dyad mean captures a shared occasion-specific shift from the two members' usual levels (shared occasion-level variance).
  2. The cwp within-dyad member deviation captures which member is further above or below their own usual level on that occasion.
  3. The cbp dyad mean captures the dyad's shared usual level relative to the sample's grand mean (stable between-dyad differences).
  4. The cbp within-dyad member deviation captures each member's stable difference from the dyad's usual level.

The cbp terms use each member's mean across the observed occasions to estimate that member's longer-run usual level. With few occasions (small (T)), especially when the predictor has low stability over time, these person means can be unreliable. The associated between-person estimates can therefore be biased or imprecise, so they should be interpreted cautiously [@gottfredsonStraightforwardApproachCoping2019].

Use temporal_decomposition = "none" to construct only the raw dyad-occasion mean and within-dyad member deviation.

ild_exchangeable_data <- dyadMLM::prepare_dyad_data(
  dyads_ild,
  dyad = coupleID,
  member = personID,
  role = gender,
  time = diaryday,
  predictors = provided_support,
  model_types = c("apim", "dim"),
  keep_compositions = "female-female",
  seed = 123
)

print(ild_exchangeable_data)

The example below estimates same-day associations between support and closeness and includes diaryday to adjust for a linear trend across the study.

dim_ILD <- glmmTMB::glmmTMB(
  closeness ~
    1 +

    diaryday +

    # Within-person DIM
    .provided_support_cwp_dyad_mean +
    .provided_support_cwp_within_dyad_dev +

    # Between-person DIM
    .provided_support_cbp_dyad_mean +
    .provided_support_cbp_within_dyad_dev +

    # Stable exchangeable dyad-level covariance
    us(1 | coupleID) +
    us(0 + .member_contrast_arbitrary | coupleID) +

    # Residual (same-day) exchangeable dyad-level covariance
    us(1 | coupleID:diaryday) +
    us(0 + .member_contrast_arbitrary | coupleID:diaryday)

  , dispformula = ~ 0
  , family = gaussian()
  , data = ild_exchangeable_data
)

summary(dim_ILD)

This concurrent model includes stable dyad-level and same-day partner covariance. To add a persistent within-member component while pooling the AR parameters across exchangeable members, we fit the complete model with one member-series term:

dim_ILD_ar_model <- glmmTMB::glmmTMB(
  closeness ~
    1 +

    diaryday +

    # Within-person DIM
    .provided_support_cwp_dyad_mean +
    .provided_support_cwp_within_dyad_dev +

    # Between-person DIM
    .provided_support_cbp_dyad_mean +
    .provided_support_cbp_within_dyad_dev +

    # Stable exchangeable dyad-level covariance
    us(1 | coupleID) +
    us(0 + .member_contrast_arbitrary | coupleID) +

    # Same-occasion exchangeable covariance
    us(1 | coupleID:diaryday) +
    us(0 + .member_contrast_arbitrary | coupleID:diaryday) +

    # Pooled residual persistence across member series
    ar1(0 + factor(diaryday) | coupleID:personID),
  dispformula = ~ 0,
  family = gaussian(),
  data = ild_exchangeable_data,
  # Non-default settings help this example converge.
  control = glmmTMB::glmmTMBControl(profile = TRUE)
)

glmmTMB::VarCorr(dim_ILD_ar_model)

See the exchangeable APIM AR(1) section for the distinction between the persistent within-member component and same-day partner covariance. To keep this example focused, both models omit the actor random slopes that are also present in the simulation.

Interpretation of concurrent ILD DIM coefficients

The same mean-and-deviation interpretation applies longitudinally. Coefficients of dyad means describe both expected individual outcomes and expected couple-average outcomes. Coefficients of within-dyad member deviations describe both members' deviations and their expected difference.

APIM and DIM parameterizations in ILD

The corresponding APIM uses actor and partner effects on both levels, as shown in the concurrent ILD APIM example. The fixed effects below are equivalent parameterizations. The complete fitted models are equivalent only when they also use the same random-effect and temporal covariance structures.

The equivalence holds separately for the within-person (cwp) and between-person (cbp) predictor components. For the within-person component:

$$ b_{\mathrm{cwp,mean}} = b_{\mathrm{cwp,actor}} + b_{\mathrm{cwp,partner}} $$

$$ b_{\mathrm{cwp,dev}} = b_{\mathrm{cwp,actor}} - b_{\mathrm{cwp,partner}} $$

For the between-person component:

$$ b_{\mathrm{cbp,mean}} = b_{\mathrm{cbp,actor}} + b_{\mathrm{cbp,partner}} $$

$$ b_{\mathrm{cbp,dev}} = b_{\mathrm{cbp,actor}} - b_{\mathrm{cbp,partner}} $$

An APIM parameterization can therefore be used on one level and a DIM parameterization on the other without changing the implied fixed effects.

Including Random Slopes

Random slopes can be included in the DIM by adding the corresponding within-person effects to the stable dyad-level random-effect blocks. The shared block contains the DIM intercept, dyad-mean slope, and within-dyad member-deviation slope. The .member_contrast_* block contains their member-difference counterparts. Together, these blocks allow the two members to have different random slopes while preserving exchangeability.

Transforming DIM random slopes to APIM slopes

Applying the same transformation to the random-slope coefficients proceeds in two steps. First, transform the DIM dyad-mean and within-dyad member-deviation random slopes into APIM actor and partner random slopes. Random effects use $u$, with subscripts that write out actor, partner, mean, and dev. For the shared block,

$$ u_{\mathrm{actor},j} = \frac{u_{\mathrm{mean},j} + u_{\mathrm{dev},j}}{2}, \qquad u_{\mathrm{partner},j} = \frac{u_{\mathrm{mean},j} - u_{\mathrm{dev},j}}{2}, $$

and for the .member_contrast_* block, marked by a tilde,

$$ \widetilde{u}{\mathrm{actor},j} = \frac{\widetilde{u}{\mathrm{mean},j} + \widetilde{u}{\mathrm{dev},j}}{2}, \qquad \widetilde{u}{\mathrm{partner},j} = \frac{\widetilde{u}{\mathrm{mean},j} - \widetilde{u}{\mathrm{dev},j}}{2}. $$

The shared and .member_contrast_* random intercepts remain unchanged.

We now have the shared and .member_contrast_* actor and partner effects which are then back-transformed into the complete and more readily interpretable member-specific actor-partner covariance matrix. This is described in the exchangeable random-slope back-transformation in the APIM vignette. The APIM vignette also shows how to test constraints on these random effects.

Dynamic ILD models

Dynamic dyadic models are most directly expressed in APIM terms: a member's own lagged outcome represents an own-lag association, whereas the partner's lagged outcome represents a partner-lag association. Interpreting either causally requires stronger assumptions. See the dynamic ILD APIM example for data preparation, a model specification, and important cautions about outcome lags in short time series.

Under exchangeability, the same fixed effects can be reparameterized as lagged DIM effects. The lagged dyad mean describes how the members' shared prior outcome level relates to their current outcomes, while the lagged within-dyad member deviation describes how their prior difference relates to their current difference. This changes the coefficient parameterization, not the fitted values.


Return to the Actor-Partner Interdependence Model vignette, see the Dyadic Score Model vignette for a related model specification, or return to the online package overview.

References

::: {#refs} :::



Try the dyadMLM package in your browser

Any scripts or data that you put into this service are public.

dyadMLM documentation built on Oct. 28, 2026, 1:06 a.m.