---
title: "Getting Started"
author: "Pascal Küng"
description: >
  Core workflow for validating dyadic data, identifying dyad compositions, and
  preparing model-ready columns for dyadic multilevel models.
bibliography: references.bib
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Getting Started}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)
```

```{r setup}
library(dyadMLM)
```

## Installation

You can install the released version of `dyadMLM` from CRAN with:

```{r installation-cran, eval=FALSE}
install.packages("dyadMLM")
```

You can install the development version from GitHub with:

```{r installation, eval=FALSE}
# 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 @ledermannAnalyzingDyadicData2017.

The available model-specific vignettes include the
[Actor-Partner Interdependence Model](apim.html),
[Dyad-Individual Model](dim.html), and
[Dyadic Score Model](dsm.html).

The [online package overview](https://pascal-kueng.github.io/dyadMLM/)
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](https://tidyr.tidyverse.org/articles/pivot.html) or
the [`pivot_longer()` reference](https://tidyr.tidyverse.org/reference/pivot_longer.html).

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.

```{r cross-sectional-raw, echo = FALSE}
head(dyads_cross)
```

We validate and prepare the data with the function `dyadMLM::prepare_dyad_data()`.

```{r prepare-cross-distinguishable}
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)

```

The function retained and recognized 120
female-male dyads and created APIM-relevant variables
[@kennyPartnerEffectsRelationship1999]. 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](apim.html).

## Data preparation for exchangeable dyads

To work with one exchangeable dyad composition, use `keep_compositions` to
retain it during preparation:

```{r prepare-cross-exchangeable-basic}
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)

```

The generated `.dy_member_contrast_female_x_female_arbitrary` contrast assigns `-1`
and `1` to the two members of each exchangeable dyad
[@delrosarioPracticalGuideSpecifying2025]. Its direction is arbitrary, and
`seed` makes the assignment reproducible.

Refer to the [exchangeable APIM section](apim.html#exchangeable-residual-structure)
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()`](https://pascal-kueng.github.io/dyadMLM/reference/recover_exchangeable_covariance.html).

Alternatively, we can explicitly set a dyad composition to exchangeable:

```{r prepare-cross-set-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)

```

*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`.

```{r prepare-cross-dim}
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)
```

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
[@iidaModelsInterdependentIndividuals2018].

```{r prepare-cross-dsm}
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)
```


## 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.

```{r ild-raw, echo=FALSE}
head(dyads_ild)
```

To prepare intensive longitudinal data, pass the `time` variable to
`dyadMLM::prepare_dyad_data()`.

```{r prepare-ild-apim}
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)

```

By default, numeric predictors in longitudinal APIM preparation are
decomposed into within-person and between-person components
[@bolgerIntensiveLongitudinalMethods2013]. 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 [@gottfredsonStraightforwardApproachCoping2019].

### 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:

```{r prepare-ild-apim-dynamic}
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)

```

**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
[@hamakerCenterNotCenter2015; @nickellBiasesDynamicModels1981;
@gistelinckMultilevelAutoregressiveSmall2021]. See the
[dynamic ILD APIM example](apim.html#dynamic-models) 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 [@Bolger2025Unified].

Let's have `dyadMLM` infer the compositions automatically:

```{r prepare-mixed-cross-sectional}
mixed_cross_data <- dyadMLM::prepare_dyad_data(
  dyads_cross,
  dyad = coupleID,
  member = personID,
  role = gender,
  seed = 123
)

print(mixed_cross_data, n = 4)
```

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
[@delrosarioPracticalGuideSpecifying2025].

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.

```{r prepare-mixed-cross-sectional-included}
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)
```

### 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.


```{r prepare-mixed-cross-sectional-exchangeable}
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)
```


### 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()`](https://pascal-kueng.github.io/dyadMLM/reference/compare_nested_glmmTMB_models.html); see
[Testing distinguishability in the APIM vignette](apim.html#testing-distinguishability)
for the model-comparison workflow.

For instance, let's pool `male-male` and `female-female` dyads
and name them `same-sex` dyads:

```{r prepare-mixed-cross-sectional_pooled}
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)
```

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:


```{r prepare-mixed-cross-sectional_pooled_constrained}
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)
```

---

**Continue** with the
[Actor-Partner Interdependence Model (APIM) vignette](apim.html).

Related model-specific vignettes:

- [Dyad-Individual Model vignette](dim.html),
- [Dyadic Score Model vignette](dsm.html),

or return to [About this vignette](#about-this-vignette).

## References

::: {#refs}
:::
