Skip to contents

Applies the d-separation conditions derived in Yu (2026) to a declared dm-graph and reports, estimand by estimand, whether the estimand is structurally recoverable and by which estimator, and whether the silence test and the sensor-gap test are valid tests of the recoverable class under the declared mechanism. Recoverability is used in the sense of Mohan and Pearl (2021): a consistent estimator exists that uses only the observed part of the data.

Usage

recoverability(g, t = 3L)

Arguments

g

A dm_graph.

t

Index of the focal prompt inside the window (default: the third; it must satisfy 3 <= t <= window - 1, so that the prompts \(t-2\) to \(t+1\) exist).

Value

A data frame of class "recoverability" with one row per estimand and the columns estimand, recoverable (logical;

NA for the two test rows, which report expected behavior rather than recoverability), estimator (the estimator that recovers the estimand, or the reason it is not recoverable), condition (the d-separation statement that was checked), and the attributes

motifs and silence_null (logical: whether the null hypothesis of the silence test is implied by the graph).

Details

The within-person conditioning set always contains every person-level latent node (eta, and zeta when declared), which is what person-specific intercepts (fixed effects) realize in estimation. Observed context nodes are added to the conditioning set for the context-conditional transition kernel. The probe rule (Z_t = 1 forces R_t = 1) is a deterministic relation that d-separation cannot express; it is applied as a separate rule.

References

Mohan, K., & Pearl, J. (2021). Graphical models for processing missing data. Journal of the American Statistical Association, 116, 1023-1037. doi:10.1080/01621459.2021.1874961

Yu, H.-T. (2026). What skipped prompts hide: Detecting, diagnosing, and correcting informative nonresponse in ecological momentary assessment. Manuscript under review.

Examples

recoverability(dm_graph("M1"))
#> Recoverability report for motifs: M1 
#> 
#> * transition kernel (Phi, Psi, contemporaneous network)
#>     [recoverable] complete adjacent pairs, within-person (person intercepts)
#>     condition: R_t _||_ X_t | {X_{t-1},eta} and R_{t-1} _||_ X_t | {X_{t-1},eta, R_t}
#> * person mean via observed within-person mean
#>     [NOT recoverable] biased
#>     condition: R_t _||_ X_t | {eta}
#> * person mean via recovered dynamics
#>     [recoverable] mu_i = (I - Phi)^{-1} c_i from the recovered kernel
#>     condition: transition kernel recoverable
#> * between-person law (mu, Sigma_mu), person-weighted
#>     [recoverable] one recovered mean per person (dynamics-recovered means), persons weighted equally; positivity assumed
#>     condition: a person-mean estimator is available and P(R_t = 1 | eta) > 0
#> * between-person law, prompt-weighted (pooling answered prompts)
#>     [NOT recoverable] biased: response rate depends on the person's states
#>     condition: R_t _||_ X_t | {empty set}
#> * silence test (coefficient of R_t in X_{t+1} ~ X_{t-1} + R_t, within person)
#>     null expected (test valid as a test of the recoverable class)
#>     condition: R_t _||_ X_{t+1} | {X_{t-1},eta,R_{t-1},R_{t+1}}
recoverability(dm_graph(c("M1", "M3")))
#> Recoverability report for motifs: M1 + M3 
#> 
#> * transition kernel (Phi, Psi, contemporaneous network)
#>     [recoverable] complete adjacent pairs, within-person (person intercepts)
#>     condition: R_t _||_ X_t | {X_{t-1},eta} and R_{t-1} _||_ X_t | {X_{t-1},eta, R_t}
#> * person mean via observed within-person mean
#>     [NOT recoverable] biased
#>     condition: R_t _||_ X_t | {eta}
#> * person mean via recovered dynamics
#>     [recoverable] mu_i = (I - Phi)^{-1} c_i from the recovered kernel
#>     condition: transition kernel recoverable
#> * between-person law (mu, Sigma_mu), person-weighted
#>     [recoverable] one recovered mean per person (dynamics-recovered means), persons weighted equally; positivity assumed
#>     condition: a person-mean estimator is available and P(R_t = 1 | eta) > 0
#> * between-person law, prompt-weighted (pooling answered prompts)
#>     [NOT recoverable] biased: response rate depends on the person's states
#>     condition: R_t _||_ X_t | {empty set}
#> * silence test (coefficient of R_t in X_{t+1} ~ X_{t-1} + R_t, within person)
#>     null violated although the kernel is recoverable (collider at R_{t+1}); use the sensor-gap test or check for fatigue first
#>     condition: R_t _||_ X_{t+1} | {X_{t-1},eta,R_{t-1},R_{t+1}}
recoverability(dm_graph("M6"))
#> Recoverability report for motifs: M6 
#> 
#> * transition kernel (Phi, Psi, contemporaneous network)
#>     [recoverable] complete adjacent pairs recover the assessment-conditioned kernel p(X_t | X_{t-1}, eta, R_{t-1} = 1): Phi and Psi are unaffected when reactivity shifts the level (additive), but the person intercept absorbs the shift
#>     condition: reactivity edge R_{t-1} -> X_t declared; all complete pairs have R_{t-1} = 1
#> * person mean via observed within-person mean
#>     [recoverable] mean of answered prompts, per person
#>     condition: R_t _||_ X_t | {eta}
#> * person mean via recovered dynamics
#>     [NOT recoverable] biased: the answered-pair intercept is the intercept of the assessed process (it absorbs the reactivity shift)
#>     condition: transition kernel recoverable and no reactivity
#> * between-person law (mu, Sigma_mu), person-weighted
#>     [recoverable] one recovered mean per person (observed means), persons weighted equally; positivity assumed
#>     condition: a person-mean estimator is available and P(R_t = 1 | eta) > 0
#> * between-person law, prompt-weighted (pooling answered prompts)
#>     [recoverable] pooled answered prompts
#>     condition: R_t _||_ X_t | {empty set}
#> * silence test (coefficient of R_t in X_{t+1} ~ X_{t-1} + R_t, within person)
#>     non-null expected: silence is informative
#>     condition: R_t _||_ X_{t+1} | {X_{t-1},eta,R_{t-1},R_{t+1}}
r <- recoverability(dm_graph("M2", sensor = TRUE))
r$recoverable
#> [1] FALSE FALSE FALSE FALSE FALSE    NA    NA
attr(r, "silence_null")
#> [1] FALSE