Installation
You can install the released version of dyadMLM from
CRAN with:
install.packages("dyadMLM")You can install the development version from GitHub with:
# install.packages("pak")
pak::pak("Pascal-Kueng/dyadMLM")About this Vignette
dyadMLM helps researchers prepare cross-sectional and
intensive longitudinal dyadic data for (generalized) multilevel models.
It automatically creates model-ready columns for dyadic multilevel model
parameterizations such as Actor-Partner Interdependence Models (APIM),
Dyad-Individual Models (DIM), and Dyadic Score Models (DSM). DIM
currently supports one exchangeable dyad composition, whereas DSM
supports one distinguishable dyad composition.
This vignette focuses on automatic data preparation for multilevel models (MLMs). For a comparison of MLM and structural equation modeling (SEM) approaches to dyadic data, see Ledermann and Kenny (2017).
The available model-specific vignettes include the Actor-Partner Interdependence Model, Dyad-Individual Model, and Dyadic Score Model.
The online package overview provides the current online versions of these vignettes and the complete function reference.
Prerequisites
The basic data structure needed for dyadMLM is a long
data frame where dyads are stacked on top of each other and both members
of a dyad appear as separate rows.
If your raw data are currently in wide format (for time or dyads or
both), reshape them to this long structure first. See the tidyr pivoting
vignette or the pivot_longer()
reference.
Roughly, the expected structure for dyadMLM is:
- For cross-sectional data: one row per
dyad x member
| dyad | member | x | y |
|---|---|---|---|
| 1 | 1 | 4.2 | 7.1 |
| 1 | 2 | 5.0 | 6.4 |
| 2 | 1 | 3.8 | 5.9 |
| 2 | 2 | 4.5 | 6.8 |
- For intensive longitudinal data: at most one row per
dyad x time x member
| dyad | time | member | x | y |
|---|---|---|---|---|
| 1 | 1 | 1 | 4.2 | 7.1 |
| 1 | 1 | 2 | 5.0 | 6.4 |
| 1 | 2 | 1 | 4.0 | 6.9 |
| 1 | 2 | 2 | 5.3 | 6.6 |
Measured variables may contain missing values. The structural
dyad, member, and optional time
variables must not contain missing values.
In intensive longitudinal data, missing measurement occasions can be represented by absent rows, as long as the time variable preserves the observed measurement occasions. For example:
| dyad | personID | time | x | y |
|---|---|---|---|---|
| 1 | 1 | 1 | 4.2 | 7.1 |
| 1 | 1 | 3 | 4.0 | 6.9 |
| 1 | 2 | 1 | 5.3 | 6.6 |
| 1 | 2 | 2 | 4.7 | 6.1 |
| 1 | 2 | 3 | 5.1 | 6.4 |
In this example, the row for person 1 at time 2 is absent. The time
variable preserves the observed measurement occasions and skips from
time 1 to time 3 for that person. dyadMLM accepts this
structure without requiring a placeholder row for the missing
occasion.
Data preparation for distinguishable dyads
dyads_cross contains three dyad compositions. Each dyad
has two rows: one for each member. The closeness and provided-support
scores are member-level averages across the 14 days in
dyads_ild.
Because these example data contain multiple compositions,
keep_compositions selects the composition modeled below. It
can be omitted when the supplied data already contain only the intended
composition.
#> personID coupleID gender dyad_composition closeness provided_support
#> 1 1 1 female female_x_male 4.767889 4.494570
#> 2 2 1 male female_x_male 4.463017 4.757241
#> 3 3 2 female female_x_male 6.437603 4.092390
#> 4 4 2 male female_x_male 5.993620 6.199226
#> 5 5 3 female female_x_male 4.756118 4.223651
#> 6 6 3 male female_x_male 4.483926 5.029079
We validate and prepare the data with the function
dyadMLM::prepare_dyad_data().
cross_distinguishable_data <- dyadMLM::prepare_dyad_data(
data = dyads_cross,
dyad = coupleID,
member = personID,
role = gender,
# In this example, we optionally specify a predictor variable
# and a model type to generate the columns needed for that model type.
predictors = provided_support,
model_types = "apim",
# All three observed compositions in `dyads_cross` are detected and retained by
# default. This example focuses on `female-male` dyads, so we restrict the
# analysis here.
keep_compositions = "female-male"
)
print(cross_distinguishable_data, n = 4)
#> # dyadMLM data
#> # Rows: 240 | Dyads: 120 | Intensive longitudinal: no
#> # Structure: dyad = coupleID, member = personID, role = gender
#> #
#> # Dyad compositions:
#> # female_x_male distinguishable 120 dyads
#> #
#> # Added columns:
#> # .dy_composition inferred dyad composition
#> # .dy_composition_role composition-specific member role
#> # .dy_is_{comp-role} composition-role indicator columns
#> # .dy_{pred}_actor APIM actor predictor: actor's original predictor
#> # values
#> # .dy_{pred}_partner APIM partner predictor: partner's original predictor
#> # values
#> #
#> # A tibble: 240 × 12
#> personID coupleID gender dyad_composition closeness provided_support
#> <int> <int> <fct> <fct> <dbl> <dbl>
#> 1 1 1 female female_x_male 4.77 4.49
#> 2 2 1 male female_x_male 4.46 4.76
#> 3 3 2 female female_x_male 6.44 4.09
#> 4 4 2 male female_x_male 5.99 6.20
#> # ℹ 236 more rows
#> # ℹ 6 more variables: .dy_composition <fct>, .dy_composition_role <fct>,
#> # .dy_is_female_x_male_female <dbl>, .dy_is_female_x_male_male <dbl>,
#> # .dy_provided_support_actor <dbl>, .dy_provided_support_partner <dbl>The function retained and recognized 120 female-male dyads and
created APIM-relevant variables (Kenny and Cook
1999). These generated .dy_* columns can be used
directly in model formulas.
For fitted APIM examples using these columns, see the Actor-Partner Interdependence Model vignette.
Data preparation for exchangeable dyads
To work with one exchangeable dyad composition, use
keep_compositions to retain it during preparation:
cross_exchangeable_data <- dyadMLM::prepare_dyad_data(
data = dyads_cross,
dyad = coupleID,
member = personID,
role = gender,
keep_compositions = "female-female",
seed = 123
)
print(cross_exchangeable_data, n = 4)
#> # dyadMLM data
#> # Rows: 240 | Dyads: 120 | Intensive longitudinal: no
#> # Structure: dyad = coupleID, member = personID, role = gender
#> #
#> # Dyad compositions:
#> # female_x_female exchangeable 120 dyads
#> #
#> # Added columns:
#> # .dy_composition inferred dyad composition
#> # .dy_composition_role composition-specific member role
#> # .dy_is_{comp-role} composition-role indicator columns
#> # .dy_member_contrast_{comp}_arbitrary composition-specific member contrasts
#> # with arbitrary direction; 0 for
#> # distinguishable dyads or other
#> # exchangeable compositions
#> #
#> # A tibble: 240 × 10
#> personID coupleID gender dyad_composition closeness provided_support
#> <int> <int> <fct> <fct> <dbl> <dbl>
#> 1 241 121 female female_x_female 7.58 5.41
#> 2 242 121 female female_x_female 6.15 5.19
#> 3 243 122 female female_x_female 8.28 5.89
#> 4 244 122 female female_x_female 8.00 5.57
#> # ℹ 236 more rows
#> # ℹ 4 more variables: .dy_composition <fct>, .dy_composition_role <fct>,
#> # .dy_is_female_x_female <dbl>,
#> # .dy_member_contrast_female_x_female_arbitrary <dbl>The generated
.dy_member_contrast_female_x_female_arbitrary contrast
assigns -1 and 1 to the two members of each
exchangeable dyad (del Rosario and West
2025). Its direction is arbitrary, and seed makes
the assignment reproducible.
Refer to the exchangeable APIM
section for how to use these columns to specify an exchangeable
dyadic APIM and recover the constrained actor-partner
variance-covariance structure with dyadMLM::recover_exchangeable_covariance().
Alternatively, we can explicitly set a dyad composition to exchangeable:
cross_exchangeable_data <- dyadMLM::prepare_dyad_data(
data = dyads_cross,
dyad = coupleID,
member = personID,
role = gender,
keep_compositions = "female-male",
set_exchangeable_compositions = "male-female",
seed = 123
)
print(cross_exchangeable_data, n = 4)
#> # dyadMLM data
#> # Rows: 240 | Dyads: 120 | Intensive longitudinal: no
#> # Structure: dyad = coupleID, member = personID, role = gender
#> #
#> # Dyad compositions:
#> # female_x_male exchangeable (set by user) 120 dyads
#> #
#> # Added columns:
#> # .dy_composition inferred dyad composition
#> # .dy_composition_role composition-specific member role
#> # .dy_is_{comp-role} composition-role indicator columns
#> # .dy_member_contrast_{comp}_arbitrary composition-specific member contrasts
#> # with arbitrary direction; 0 for
#> # distinguishable dyads or other
#> # exchangeable compositions
#> #
#> # A tibble: 240 × 10
#> personID coupleID gender dyad_composition closeness provided_support
#> <int> <int> <fct> <fct> <dbl> <dbl>
#> 1 1 1 female female_x_male 4.77 4.49
#> 2 2 1 male female_x_male 4.46 4.76
#> 3 3 2 female female_x_male 6.44 4.09
#> 4 4 2 male female_x_male 5.99 6.20
#> # ℹ 236 more rows
#> # ℹ 4 more variables: .dy_composition <fct>, .dy_composition_role <fct>,
#> # .dy_is_female_x_male <dbl>,
#> # .dy_member_contrast_female_x_male_arbitrary <dbl>Note that whenever you need to refer to a dyad type, the
order of members does not matter (e.g., male-female and
female-male will both work), and you can use different
separators like male_female, male_x_female, or
male female.
Generating DIM and DSM columns
For exchangeable dyads, we can request DIM predictor columns. DIM
preparation requires exactly one exchangeable composition, which we
retain here with keep_compositions.
cross_dim_data <- dyadMLM::prepare_dyad_data(
data = dyads_cross,
dyad = coupleID,
member = personID,
role = gender,
predictors = provided_support,
model_types = "dim",
keep_compositions = "female-female",
seed = 123
)
print(cross_dim_data, n = 4)
#> # dyadMLM data
#> # Rows: 240 | Dyads: 120 | Intensive longitudinal: no
#> # Structure: dyad = coupleID, member = personID, role = gender
#> #
#> # Dyad compositions:
#> # female_x_female exchangeable 120 dyads
#> #
#> # Added columns:
#> # .dy_composition inferred dyad composition
#> # .dy_composition_role composition-specific member role
#> # .dy_is_{comp-role} composition-role indicator columns
#> # .dy_member_contrast_{comp}_arbitrary composition-specific member contrasts
#> # with arbitrary direction; 0 for
#> # distinguishable dyads or other
#> # exchangeable compositions
#> # .dy_{pred}_dyad_mean_gmc dyad-mean predictor: dyad's average
#> # predictor level, grand-mean centered
#> # .dy_{pred}_within_dyad_dev DIM within-dyad member-deviation
#> # predictor: member's difference from
#> # the dyad mean
#> #
#> # A tibble: 240 × 12
#> personID coupleID gender dyad_composition closeness provided_support
#> <int> <int> <fct> <fct> <dbl> <dbl>
#> 1 241 121 female female_x_female 7.58 5.41
#> 2 242 121 female female_x_female 6.15 5.19
#> 3 243 122 female female_x_female 8.28 5.89
#> 4 244 122 female female_x_female 8.00 5.57
#> # ℹ 236 more rows
#> # ℹ 6 more variables: .dy_composition <fct>, .dy_composition_role <fct>,
#> # .dy_is_female_x_female <dbl>,
#> # .dy_member_contrast_female_x_female_arbitrary <dbl>,
#> # .dy_provided_support_dyad_mean_gmc <dbl>,
#> # .dy_provided_support_within_dyad_dev <dbl>Generating DSM columns for distinguishable dyads additionally requires an explicit role order. The role order defines the direction of all DSM predictor differences and the DSM role contrast (Iida et al. 2018).
cross_dsm_data <- dyadMLM::prepare_dyad_data(
data = dyads_cross,
dyad = coupleID,
member = personID,
role = gender,
predictors = provided_support,
model_types = "dsm",
dsm_role_order = c("female", "male"),
keep_compositions = "female-male"
)
print(cross_dsm_data, n = 4)
#> # dyadMLM data
#> # Rows: 240 | Dyads: 120 | Intensive longitudinal: no
#> # Structure: dyad = coupleID, member = personID, role = gender
#> # DSM direction: female - male
#> #
#> # Dyad compositions:
#> # female_x_male distinguishable 120 dyads
#> #
#> # Added columns:
#> # .dy_composition inferred dyad composition
#> # .dy_composition_role composition-specific member role
#> # .dy_is_{comp-role} composition-role indicator columns
#> # .dy_dsm_role_contrast DSM role contrast: +0.5 for the first declared
#> # role and -0.5 for the second declared role
#> # .dy_{pred}_dyad_mean_gmc dyad-mean predictor: dyad's average predictor
#> # level, grand-mean centered
#> # .dy_{pred}_within_dyad_diff DSM signed predictor difference: first
#> # declared role minus second declared role
#> #
#> # A tibble: 240 × 13
#> personID coupleID gender dyad_composition closeness provided_support
#> <int> <int> <fct> <fct> <dbl> <dbl>
#> 1 1 1 female female_x_male 4.77 4.49
#> 2 2 1 male female_x_male 4.46 4.76
#> 3 3 2 female female_x_male 6.44 4.09
#> 4 4 2 male female_x_male 5.99 6.20
#> # ℹ 236 more rows
#> # ℹ 7 more variables: .dy_composition <fct>, .dy_composition_role <fct>,
#> # .dy_is_female_x_male_female <dbl>, .dy_is_female_x_male_male <dbl>,
#> # .dy_dsm_role_contrast <dbl>, .dy_provided_support_dyad_mean_gmc <dbl>,
#> # .dy_provided_support_within_dyad_diff <dbl>Intensive longitudinal dyadic data
dyads_ild is an intensive longitudinal dyadic dataset.
Each dyad has repeated observations over diaryday, with one
row per person-day.
#> # A tibble: 6 × 7
#> personID coupleID diaryday gender dyad_composition closeness provided_support
#> <int> <int> <int> <fct> <fct> <dbl> <dbl>
#> 1 1 1 0 female female_x_male 4.40 4.93
#> 2 2 1 0 male female_x_male 5.14 5.59
#> 3 1 1 1 female female_x_male 5.16 4.89
#> 4 2 1 1 male female_x_male 5.70 5.18
#> 5 1 1 2 female female_x_male 3.28 4.38
#> 6 2 1 2 male female_x_male 2.82 4.99
To prepare intensive longitudinal data, pass the time
variable to dyadMLM::prepare_dyad_data().
ild_apim_data <- dyadMLM::prepare_dyad_data(
dyads_ild,
dyad = coupleID,
member = personID,
role = gender,
time = diaryday,
predictors = provided_support,
model_types = "apim",
keep_compositions = "female-male",
seed = 123
)
print(ild_apim_data, n = 6)
#> # dyadMLM data
#> # Rows: 3360 | Dyads: 120 | Intensive longitudinal: yes
#> # Structure: dyad = coupleID, member = personID, role = gender, time = diaryday
#> #
#> # Dyad compositions:
#> # female_x_male distinguishable 120 dyads
#> #
#> # Added columns:
#> # .dy_composition inferred dyad composition
#> # .dy_composition_role composition-specific member role
#> # .dy_is_{comp-role} composition-role indicator columns
#> # .dy_{pred}_cwp within-person predictor: momentary deviations from
#> # each person's usual level
#> # .dy_{pred}_cbp between-person predictor: stable differences from
#> # the average person's usual level
#> # .dy_{pred}_actor APIM actor predictor: actor's original predictor
#> # values
#> # .dy_{pred}_partner APIM partner predictor: partner's original
#> # predictor values
#> # .dy_{pred}_cwp_actor APIM within-person actor predictor: actor's
#> # momentary deviations from their usual level
#> # .dy_{pred}_cwp_partner APIM within-person partner predictor: partner's
#> # momentary deviations from their usual level
#> # .dy_{pred}_cbp_actor APIM between-person actor predictor: actor's stable
#> # difference from the average person's usual level
#> # .dy_{pred}_cbp_partner APIM between-person partner predictor: partner's
#> # stable difference from the average person's usual
#> # level
#> #
#> # A tibble: 3,360 × 19
#> personID coupleID diaryday gender dyad_composition closeness provided_support
#> <int> <int> <int> <fct> <fct> <dbl> <dbl>
#> 1 1 1 0 female female_x_male 4.40 4.93
#> 2 2 1 0 male female_x_male 5.14 5.59
#> 3 1 1 1 female female_x_male 5.16 4.89
#> 4 2 1 1 male female_x_male 5.70 5.18
#> 5 1 1 2 female female_x_male 3.28 4.38
#> 6 2 1 2 male female_x_male 2.82 4.99
#> # ℹ 3,354 more rows
#> # ℹ 12 more variables: .dy_composition <fct>, .dy_composition_role <fct>,
#> # .dy_is_female_x_male_female <dbl>, .dy_is_female_x_male_male <dbl>,
#> # .dy_provided_support_cwp <dbl>, .dy_provided_support_cbp <dbl>,
#> # .dy_provided_support_actor <dbl>, .dy_provided_support_partner <dbl>,
#> # .dy_provided_support_cwp_actor <dbl>,
#> # .dy_provided_support_cwp_partner <dbl>, …By default, numeric predictors in longitudinal APIM preparation are
decomposed into within-person and between-person components (Bolger and Laurenceau 2013). This temporal
predictor decomposition is controlled by
temporal_decomposition. The default "auto"
setting selects "2l" for this longitudinal setup and
retains raw actor and partner columns alongside both components.
Note that observed person means used to construct the between-person
(cbp) predictors can be unreliable when each member
contributes few occasions, which can bias between-person estimates (Gottfredson 2019).
Preparing lagged predictors
Lagged versions of variables, including an outcome that is also
passed to predictors, can be obtained through the
lag1_predictors argument.
dyadMLM::prepare_dyad_data() then returns lag-1 raw and
within-person-centered actor and partner columns alongside their
contemporaneous versions. Lagging respects the dyad and member
structure, matches observations at exactly time - 1, and
does not bridge missing occasions.
For a simpler dynamic model, this example retains the exchangeable female-female composition:
ild_apim_data_dynamic <- dyadMLM::prepare_dyad_data(
dyads_ild,
dyad = coupleID,
member = personID,
role = gender,
time = diaryday,
predictors = closeness,
lag1_predictors = closeness,
model_types = "apim",
keep_compositions = "female-female",
seed = 123
)
print(ild_apim_data_dynamic, n = 6)
#> # dyadMLM data
#> # Rows: 3360 | Dyads: 120 | Intensive longitudinal: yes
#> # Structure: dyad = coupleID, member = personID, role = gender, time = diaryday
#> #
#> # Dyad compositions:
#> # female_x_female exchangeable 120 dyads
#> #
#> # Added columns:
#> # .dy_composition inferred dyad composition
#> # .dy_composition_role composition-specific member role
#> # .dy_is_{comp-role} composition-role indicator columns
#> # .dy_member_contrast_{comp}_arbitrary composition-specific member contrasts
#> # with arbitrary direction; 0 for
#> # distinguishable dyads or other
#> # exchangeable compositions
#> # .dy_{pred}_lag1 lag-1 raw predictor values
#> # .dy_{pred}_cwp within-person predictor: momentary
#> # deviations from each person's usual
#> # level
#> # .dy_{pred}_cwp_lag1 lag-1 within-person predictor:
#> # momentary deviations from each
#> # person's usual level
#> # .dy_{pred}_cbp between-person predictor: stable
#> # differences from the average person's
#> # usual level
#> # .dy_{pred}_actor APIM actor predictor: actor's
#> # original predictor values
#> # .dy_{pred}_actor_lag1 lag-1 APIM actor predictor: actor's
#> # original predictor values
#> # .dy_{pred}_partner APIM partner predictor: partner's
#> # original predictor values
#> # .dy_{pred}_partner_lag1 lag-1 APIM partner predictor:
#> # partner's original predictor values
#> # .dy_{pred}_cwp_actor APIM within-person actor predictor:
#> # actor's momentary deviations from
#> # their usual level
#> # .dy_{pred}_cwp_actor_lag1 lag-1 APIM within-person actor
#> # predictor: actor's momentary
#> # deviations from their usual level
#> # .dy_{pred}_cwp_partner APIM within-person partner predictor:
#> # partner's momentary deviations from
#> # their usual level
#> # .dy_{pred}_cwp_partner_lag1 lag-1 APIM within-person partner
#> # predictor: partner's momentary
#> # deviations from their usual level
#> # .dy_{pred}_cbp_actor APIM between-person actor predictor:
#> # actor's stable difference from the
#> # average person's usual level
#> # .dy_{pred}_cbp_partner APIM between-person partner
#> # predictor: partner's stable
#> # difference from the average person's
#> # usual level
#> #
#> # A tibble: 3,360 × 25
#> personID coupleID diaryday gender dyad_composition closeness provided_support
#> <int> <int> <int> <fct> <fct> <dbl> <dbl>
#> 1 241 121 0 female female_x_female 6.59 6.18
#> 2 242 121 0 female female_x_female 5.73 5.70
#> 3 241 121 1 female female_x_female 8.70 4.57
#> 4 242 121 1 female female_x_female 5.61 5.30
#> 5 241 121 2 female female_x_female 7.06 5.19
#> 6 242 121 2 female female_x_female 6.72 3.89
#> # ℹ 3,354 more rows
#> # ℹ 18 more variables: .dy_composition <fct>, .dy_composition_role <fct>,
#> # .dy_is_female_x_female <dbl>,
#> # .dy_member_contrast_female_x_female_arbitrary <dbl>,
#> # .dy_closeness_cwp <dbl>, .dy_closeness_cbp <dbl>, .dy_closeness_lag1 <dbl>,
#> # .dy_closeness_cwp_lag1 <dbl>, .dy_closeness_actor <dbl>,
#> # .dy_closeness_partner <dbl>, .dy_closeness_cwp_actor <dbl>, …Note: Whether to use the raw or within-person-centered lagged outcome depends on the research question and the data. Including a lagged outcome in dynamic models can introduce bias, especially in shorter time series (Hamaker and Grasman 2015; Nickell 1981; Gistelinck et al. 2021). See the dynamic ILD APIM example for a more detailed discussion and guidance.
Working with multiple dyad compositions
dyads_cross contains three dyad compositions:
distinguishable female-male dyads and exchangeable female-female and
male-male dyads (Bolger et al. 2025).
Let’s have dyadMLM infer the compositions
automatically:
mixed_cross_data <- dyadMLM::prepare_dyad_data(
dyads_cross,
dyad = coupleID,
member = personID,
role = gender,
seed = 123
)
print(mixed_cross_data, n = 4)
#> # dyadMLM data
#> # Rows: 720 | Dyads: 360 | Intensive longitudinal: no
#> # Structure: dyad = coupleID, member = personID, role = gender
#> #
#> # Dyad compositions:
#> # female_x_female exchangeable 120 dyads
#> # female_x_male distinguishable 120 dyads
#> # male_x_male exchangeable 120 dyads
#> #
#> # Added columns:
#> # .dy_composition inferred dyad composition
#> # .dy_composition_role composition-specific member role
#> # .dy_is_{comp-role} composition-role indicator columns
#> # .dy_member_contrast_{comp}_arbitrary composition-specific member contrasts
#> # with arbitrary direction; 0 for
#> # distinguishable dyads or other
#> # exchangeable compositions
#> #
#> # A tibble: 720 × 14
#> personID coupleID gender dyad_composition closeness provided_support
#> <int> <int> <fct> <fct> <dbl> <dbl>
#> 1 1 1 female female_x_male 4.77 4.49
#> 2 2 1 male female_x_male 4.46 4.76
#> 3 3 2 female female_x_male 6.44 4.09
#> 4 4 2 male female_x_male 5.99 6.20
#> # ℹ 716 more rows
#> # ℹ 8 more variables: .dy_composition <fct>, .dy_composition_role <fct>,
#> # .dy_is_female_x_female <dbl>, .dy_is_female_x_male_female <dbl>,
#> # .dy_is_female_x_male_male <dbl>, .dy_is_male_x_male <dbl>,
#> # .dy_member_contrast_female_x_female_arbitrary <dbl>,
#> # .dy_member_contrast_male_x_male_arbitrary <dbl>Note that when role compositions are available, each exchangeable
composition receives its own difference contrast, such as
.dy_member_contrast_female_x_female_arbitrary, which is
0 for all other compositions (del
Rosario and West 2025).
We can use this data to model these dyad types as separate or in the same model.
Keeping only selected dyad compositions (filtering)
Sometimes a mixed dataset contains dyad compositions that should not
be part of a given analysis. Use keep_compositions to keep
only dyads whose observed composition matches the requested
labels. The filtering happens before exchangeability constraints and
pooling, so set_exchangeable_compositions and
pool_compositions can only refer to retained dyad
compositions.
mixed_cross_data_included <- dyadMLM::prepare_dyad_data(
dyads_cross,
dyad = coupleID,
member = personID,
role = gender,
keep_compositions = c("female-female", "male-male"),
seed = 123
)
print(mixed_cross_data_included, n = 4)
#> # dyadMLM data
#> # Rows: 480 | Dyads: 240 | Intensive longitudinal: no
#> # Structure: dyad = coupleID, member = personID, role = gender
#> #
#> # Dyad compositions:
#> # female_x_female exchangeable 120 dyads
#> # male_x_male exchangeable 120 dyads
#> #
#> # Added columns:
#> # .dy_composition inferred dyad composition
#> # .dy_composition_role composition-specific member role
#> # .dy_is_{comp-role} composition-role indicator columns
#> # .dy_member_contrast_{comp}_arbitrary composition-specific member contrasts
#> # with arbitrary direction; 0 for
#> # distinguishable dyads or other
#> # exchangeable compositions
#> #
#> # A tibble: 480 × 12
#> personID coupleID gender dyad_composition closeness provided_support
#> <int> <int> <fct> <fct> <dbl> <dbl>
#> 1 241 121 female female_x_female 7.58 5.41
#> 2 242 121 female female_x_female 6.15 5.19
#> 3 243 122 female female_x_female 8.28 5.89
#> 4 244 122 female female_x_female 8.00 5.57
#> # ℹ 476 more rows
#> # ℹ 6 more variables: .dy_composition <fct>, .dy_composition_role <fct>,
#> # .dy_is_female_x_female <dbl>, .dy_is_male_x_male <dbl>,
#> # .dy_member_contrast_female_x_female_arbitrary <dbl>,
#> # .dy_member_contrast_male_x_male_arbitrary <dbl>Setting distinguishable dyads to be treated as exchangeable
As mentioned earlier, a distinguishable dyad composition can be
treated as exchangeable. In a mixed dyad composition dataset, this
specification keeps the differentiation between the kinds of dyads
(e.g., male-male, female-female, and
male-female), as opposed to omitting role, which would pool
all dyad compositions into one exchangeable composition.
mixed_cross_exchangeable_data <- dyadMLM::prepare_dyad_data(
dyads_cross,
dyad = coupleID,
member = personID,
role = gender,
set_exchangeable_compositions = c("male-female"),
seed = 123
)
print(mixed_cross_exchangeable_data, n = 4)
#> # dyadMLM data
#> # Rows: 720 | Dyads: 360 | Intensive longitudinal: no
#> # Structure: dyad = coupleID, member = personID, role = gender
#> #
#> # Dyad compositions:
#> # female_x_female exchangeable 120 dyads
#> # female_x_male exchangeable (set by user) 120 dyads
#> # male_x_male exchangeable 120 dyads
#> #
#> # Added columns:
#> # .dy_composition inferred dyad composition
#> # .dy_composition_role composition-specific member role
#> # .dy_is_{comp-role} composition-role indicator columns
#> # .dy_member_contrast_{comp}_arbitrary composition-specific member contrasts
#> # with arbitrary direction; 0 for
#> # distinguishable dyads or other
#> # exchangeable compositions
#> #
#> # A tibble: 720 × 14
#> personID coupleID gender dyad_composition closeness provided_support
#> <int> <int> <fct> <fct> <dbl> <dbl>
#> 1 1 1 female female_x_male 4.77 4.49
#> 2 2 1 male female_x_male 4.46 4.76
#> 3 3 2 female female_x_male 6.44 4.09
#> 4 4 2 male female_x_male 5.99 6.20
#> # ℹ 716 more rows
#> # ℹ 8 more variables: .dy_composition <fct>, .dy_composition_role <fct>,
#> # .dy_is_female_x_female <dbl>, .dy_is_female_x_male <dbl>,
#> # .dy_is_male_x_male <dbl>,
#> # .dy_member_contrast_female_x_female_arbitrary <dbl>,
#> # .dy_member_contrast_female_x_male_arbitrary <dbl>,
#> # .dy_member_contrast_male_x_male_arbitrary <dbl>Pooling different dyad compositions
Sometimes for theoretical or practical reasons, we may want to pool
selected exchangeable dyad compositions and analyze them as if they were
one. Pooling can impose equality constraints among compositions. After
fitting nested pooled and unpooled models to the same observations,
these constraints can be tested with dyadMLM::compare_nested_glmmTMB_models();
see Testing
distinguishability in the APIM vignette for the model-comparison
workflow.
For instance, let’s pool male-male and
female-female dyads and name them same-sex
dyads:
mixed_cross_data_pooled <- dyadMLM::prepare_dyad_data(
dyads_cross,
dyad = coupleID,
member = personID,
role = gender,
pool_compositions = list(
"same-sex" = c("male-male", "female_female")
),
seed = 123
)
print(mixed_cross_data_pooled)
#> # dyadMLM data
#> # Rows: 720 | Dyads: 360 | Intensive longitudinal: no
#> # Structure: dyad = coupleID, member = personID, role = gender
#> #
#> # Dyad compositions:
#> # female_x_male distinguishable 120 dyads
#> # same-sex (pooled) exchangeable 240 dyads
#> # female_x_female
#> # male_x_male
#> #
#> # Added columns:
#> # .dy_composition inferred dyad composition
#> # .dy_composition_role composition-specific member role
#> # .dy_is_{comp-role} composition-role indicator columns
#> # .dy_member_contrast_{comp}_arbitrary composition-specific member contrasts
#> # with arbitrary direction; 0 for
#> # distinguishable dyads or other
#> # exchangeable compositions
#> #
#> # A tibble: 720 × 12
#> personID coupleID gender dyad_composition closeness provided_support
#> <int> <int> <fct> <fct> <dbl> <dbl>
#> 1 1 1 female female_x_male 4.77 4.49
#> 2 2 1 male female_x_male 4.46 4.76
#> 3 3 2 female female_x_male 6.44 4.09
#> 4 4 2 male female_x_male 5.99 6.20
#> 5 5 3 female female_x_male 4.76 4.22
#> 6 6 3 male female_x_male 4.48 5.03
#> 7 7 4 female female_x_male 7.76 5.36
#> 8 8 4 male female_x_male 5.59 5.25
#> 9 9 5 female female_x_male 7.28 5.78
#> 10 10 5 male female_x_male 5.42 4.98
#> # ℹ 710 more rows
#> # ℹ 6 more variables: .dy_composition <fct>, .dy_composition_role <fct>,
#> # .dy_is_female_x_male_female <dbl>, .dy_is_female_x_male_male <dbl>,
#> # .dy_is_same_sex <dbl>, .dy_member_contrast_same_sex_arbitrary <dbl>Note that you cannot pool distinguishable dyads. If we wanted to pool
female-male with male-male, we would first
have to treat female-male as exchangeable:
mixed_cross_data_pooled_constrained <- dyadMLM::prepare_dyad_data(
dyads_cross,
dyad = coupleID,
member = personID,
role = gender,
set_exchangeable_compositions = "male female",
pool_compositions = list(
"pooled_exchangeable" = c("male-male", "male_female")
),
seed = 123
)
print(mixed_cross_data_pooled_constrained)
#> # dyadMLM data
#> # Rows: 720 | Dyads: 360 | Intensive longitudinal: no
#> # Structure: dyad = coupleID, member = personID, role = gender
#> #
#> # Dyad compositions:
#> # female_x_female exchangeable 120 dyads
#> # pooled_exchangeable (pooled) exchangeable 240 dyads
#> # female_x_male
#> # male_x_male
#> #
#> # Added columns:
#> # .dy_composition inferred dyad composition
#> # .dy_composition_role composition-specific member role
#> # .dy_is_{comp-role} composition-role indicator columns
#> # .dy_member_contrast_{comp}_arbitrary composition-specific member contrasts
#> # with arbitrary direction; 0 for
#> # distinguishable dyads or other
#> # exchangeable compositions
#> #
#> # A tibble: 720 × 12
#> personID coupleID gender dyad_composition closeness provided_support
#> <int> <int> <fct> <fct> <dbl> <dbl>
#> 1 1 1 female female_x_male 4.77 4.49
#> 2 2 1 male female_x_male 4.46 4.76
#> 3 3 2 female female_x_male 6.44 4.09
#> 4 4 2 male female_x_male 5.99 6.20
#> 5 5 3 female female_x_male 4.76 4.22
#> 6 6 3 male female_x_male 4.48 5.03
#> 7 7 4 female female_x_male 7.76 5.36
#> 8 8 4 male female_x_male 5.59 5.25
#> 9 9 5 female female_x_male 7.28 5.78
#> 10 10 5 male female_x_male 5.42 4.98
#> # ℹ 710 more rows
#> # ℹ 6 more variables: .dy_composition <fct>, .dy_composition_role <fct>,
#> # .dy_is_female_x_female <dbl>, .dy_is_pooled_exchangeable <dbl>,
#> # .dy_member_contrast_female_x_female_arbitrary <dbl>,
#> # .dy_member_contrast_pooled_exchangeable_arbitrary <dbl>Continue with the Actor-Partner Interdependence Model (APIM) vignette.
Related model-specific vignettes:
or return to About this vignette.