Bivariate dyadic workflow

Overview

This vignette shows the bivariate workflow implemented in dyadicMarkov. In the bivariate setting, two categorical variables are observed repeatedly for the two members of a dyad. The bivariate method follows the global-and-local procedure described in Böllenrücher, Darwiche, and Antonietti (in press).

The current bivariate functions support states = 2. With two binary variables observed for two members, the previous state is described by four binary components. The empirical bivariate count matrix therefore has 16 rows and 2 columns.

Data

The example data set dyadic_bivariate_example contains two categorical variables for the first member and the second member of a dyad. Each row corresponds to one measurement occasion.

utils::data("dyadic_bivariate_example", package = "dyadicMarkov")

head(dyadic_bivariate_example)
#>   time FM_V1 SM_V1 FM_V2 SM_V2
#> 1    1     2     1     1     2
#> 2    2     2     1     2     1
#> 3    3     2     2     2     1
#> 4    4     2     2     2     2
#> 5    5     2     2     1     2
#> 6    6     2     2     1     1
dim(dyadic_bivariate_example)
#> [1] 90  5

The four chains are first-member and second-member sequences for the main variable (V1) and the second variable (V2).

table(dyadic_bivariate_example$FM_V1)
#> 
#>  1  2 
#> 16 74
table(dyadic_bivariate_example$SM_V1)
#> 
#>  1  2 
#> 18 72

Empirical bivariate transition counts

The first step is to construct the empirical bivariate transition count matrix with countEmpBivariate(). Rows represent the 16 possible previous-state combinations of the two dyadic variables. Columns represent the next state of the first member on the main variable.

emp_bi <- dyadicMarkov::countEmpBivariate(
  chainFM_V1 = dyadic_bivariate_example$FM_V1,
  chainSM_V1 = dyadic_bivariate_example$SM_V1,
  chainFM_V2 = dyadic_bivariate_example$FM_V2,
  chainSM_V2 = dyadic_bivariate_example$SM_V2,
  states = 2L
)

emp_bi
#>                                     next_1 next_2
#> mainFM1_mainSM1_secondFM1_secondSM1 7      0     
#> mainFM1_mainSM1_secondFM1_secondSM2 0      2     
#> mainFM1_mainSM1_secondFM2_secondSM1 0      0     
#> mainFM1_mainSM1_secondFM2_secondSM2 1      0     
#> mainFM1_mainSM2_secondFM1_secondSM1 0      1     
#> mainFM1_mainSM2_secondFM1_secondSM2 0      1     
#> mainFM1_mainSM2_secondFM2_secondSM1 2      0     
#> mainFM1_mainSM2_secondFM2_secondSM2 0      2     
#> mainFM2_mainSM1_secondFM1_secondSM1 0      0     
#> mainFM2_mainSM1_secondFM1_secondSM2 2      1     
#> mainFM2_mainSM1_secondFM2_secondSM1 1      1     
#> mainFM2_mainSM1_secondFM2_secondSM2 0      3     
#> mainFM2_mainSM2_secondFM1_secondSM1 1      1     
#> mainFM2_mainSM2_secondFM1_secondSM2 1      4     
#> mainFM2_mainSM2_secondFM2_secondSM1 1      5     
#> mainFM2_mainSM2_secondFM2_secondSM2 0      52
class(emp_bi)
#> [1] "dyadic_counts" "matrix"        "array"
dim(emp_bi)
#> [1] 16  2

Global bivariate case

The function bivariateCase() performs the global step of the bivariate method. It applies the package chi-squared comparisons to classify the dependence structure of the member sequence analyzed as a trivial, univariate, partial bivariate or complete bivariate case.

case_bi <- dyadicMarkov::bivariateCase(emp_bi, alpha = 0.05)

case_bi
#> Bivariate dyadic case
#> Case: complete
#> Alpha: 0.05
case_bi$case
#> [1] "complete"
summary(case_bi)
#> $case
#> [1] "complete"
#> 
#> $alpha
#> [1] 0.05
#> 
#> $call
#> dyadicMarkov::bivariateCase(empirical = emp_bi, alpha = 0.05)
#> 
#> attr(,"class")
#> [1] "summary_dyadic_case" "list"

This example is identified as a complete bivariate case. The appropriate local step is therefore to compare complete bivariate candidate patterns.

Local pattern identification for a complete case

For a complete bivariate case, completePattern() compares the complete bivariate candidate structures by AIC and returns the selected pattern.

complete_bi <- dyadicMarkov::completePattern(emp_bi)

complete_bi
#> Dyadic interaction pattern
#> Pattern: complete actor on the main, actor partner on the second (D2)
complete_bi$pattern
#> [1] "complete actor on the main, actor partner on the second (D2)"
complete_bi$aic
#>                                                          pattern matrix
#> 1                             complete actor partner on both (C)      C
#> 2 complete partner on the main, actor partner on the second (D1)     D1
#> 3   complete actor on the main, actor partner on the second (D2)     D2
#> 4 complete actor partner on the main, partner on the second (D3)     D3
#> 5   complete actor partner on the main, actor on the second (D4)     D4
#> 6                                  complete partner on both (E1)     E1
#> 7         complete partner on the main, actor on the second (E2)     E2
#> 8         complete actor on the main, partner on the second (E3)     E3
#> 9                                    complete actor on both (E4)     E4
#>        aic
#> 1 32.00000
#> 2 30.03720
#> 3 28.42735
#> 4 33.33973
#> 5 38.60730
#> 6 30.55374
#> 7 42.91748
#> 8 36.47261
#> 9 40.57170

In this example, the selected complete bivariate pattern is D2, labelled by the package as complete actor on the main, actor-partner on the second.

Reassigning member and main-variable roles

The previous analysis used FM_V1 as the member-variable sequence analyzed, V1 as the main variable and V2 as the second variable. In the bivariate method, these are analysis roles rather than fixed identities. To describe the dyad more completely, the roles can be reassigned so that each member-variable sequence is analyzed in turn.

The same data set gives different branches of the global-and-local procedure depending on the member-variable sequence analyzed and the main variable.

analyze_bivariate <- function(label, fm_v1, sm_v1, fm_v2, sm_v2) {
  emp <- dyadicMarkov::countEmpBivariate(
    chainFM_V1 = fm_v1,
    chainSM_V1 = sm_v1,
    chainFM_V2 = fm_v2,
    chainSM_V2 = sm_v2,
    states = 2L
  )

  case <- dyadicMarkov::bivariateCase(emp, alpha = 0.05)

  cat("\n", label, "\n", sep = "")
  print(case)

  if (identical(case$case, "complete")) {
    print(dyadicMarkov::completePattern(emp))
  }

  if (identical(case$case, "partial")) {
    print(dyadicMarkov::partialPattern(emp))
  }

  if (identical(case$case, "univariate")) {
    print(dyadicMarkov::univariatePattern(fm_v1, sm_v1, states = 2L, alpha = 0.05))
  }
}

d <- dyadic_bivariate_example

analyze_bivariate(
  "FM_V1 as analyzed sequence, V1 as main variable",
  d$FM_V1, d$SM_V1, d$FM_V2, d$SM_V2
)
#> 
#> FM_V1 as analyzed sequence, V1 as main variable
#> Bivariate dyadic case
#> Case: complete
#> Alpha: 0.05
#> Dyadic interaction pattern
#> Pattern: complete actor on the main, actor partner on the second (D2)

analyze_bivariate(
  "SM_V1 as analyzed sequence, V1 as main variable",
  d$SM_V1, d$FM_V1, d$SM_V2, d$FM_V2
)
#> 
#> SM_V1 as analyzed sequence, V1 as main variable
#> Bivariate dyadic case
#> Case: complete
#> Alpha: 0.05
#> Dyadic interaction pattern
#> Pattern: complete actor partner on the main, partner on the second (D3)

analyze_bivariate(
  "FM_V2 as analyzed sequence, V2 as main variable",
  d$FM_V2, d$SM_V2, d$FM_V1, d$SM_V1
)
#> 
#> FM_V2 as analyzed sequence, V2 as main variable
#> Bivariate dyadic case
#> Case: partial
#> Alpha: 0.05
#> Dyadic interaction pattern
#> Pattern: partial actor (B2)

analyze_bivariate(
  "SM_V2 as analyzed sequence, V2 as main variable",
  d$SM_V2, d$FM_V2, d$SM_V1, d$FM_V1
)
#> 
#> SM_V2 as analyzed sequence, V2 as main variable
#> Bivariate dyadic case
#> Case: univariate
#> Alpha: 0.05
#> Dyadic interaction pattern
#> Pattern: APM (A1)
#> Alpha: 0.05
#> States: 2

For this example, the four role assignments illustrate three branches of the procedure: complete bivariate cases for the two V1 member-variable sequences, a partial bivariate case for FM_V2, and a univariate case for SM_V2. The partial branch is therefore demonstrated with the same bivariate example data rather than with an artificial seeded example.

Reading the global and local steps together

The global and local steps should be read together. If bivariateCase() returns trivial, no subsequent local pattern is selected. If it returns univariate, the bivariate workflow returns to univariatePattern() using the first- and second-member sequences of the current main variable. If it returns partial, the local step is partialPattern(). If it returns complete, the local step is completePattern().

References

Böllenrücher, Mégane, Joëlle Darwiche, and Jean-Philippe Antonietti. in press. “Bivariate Dyadic Patterns Analysis Using Longitudinal Actor-Partner Interdependence Model and Markov Chains for Single-Case.” Quantitative and Computational Methods in Behavioral Sciences, in press. https://doi.org/10.23668/psycharchives.22174.