Operationalizes the proximal completeness condition as whether the negative-control panel W captures the confounder covariance — i.e., whether adding W reduces U's contribution to the outcome toward zero.
Usage
nc_completeness_capture(
dat,
outcome = "Y",
n_perm = 1000,
n_cores = 1,
thresholds = list(strong = 0.3, weak = 0.1)
)Arguments
- dat
Dataset list from
run_single_iteration()orgenerate_toy_data(), containingW, an outcome block (YorM), andsynthetic_data(covariates).- outcome
Outcome block to test against:
"Y"(default) or"M".- n_perm
Number of permutations for the null. Default 1000.
- n_cores
Number of parallel workers. Default 1.
- thresholds
Named list with
strongandweakR^2 cutoffs for the verdict. Defaultlist(strong = 0.3, weak = 0.1).
Value
A list with:
capture_R2 (point estimate, averaged across outcome features),
capture_pvalue (permutation p-value),
capture_verdict ("strong", "weak", or "negligible"),
null_distribution (numeric vector of permuted R^2 values),
n_features (number of outcome features tested).
Details
The test computes the incremental R^2 of W for the outcome above
covariates C alone: R^2(W | C) = R^2(Y ~ C + W) - R^2(Y ~ C), averaged
across outcome features. A permutation null is generated by permuting the
W-outcome association (holding the C-outcome association fixed) over
n_perm permutations, yielding a permutation p-value for "W captures
U-signal beyond chance."
This addresses the concern that the count-based completeness check
(dim(W_valid) >= k) is necessary but not sufficient: completeness is
about the covariance the controls capture, not the number of proxies. A
panel can have many controls that each weakly capture U, or few controls
that together capture it well.
Examples
dat <- run_single_iteration(n_features = 10, n_confounders = 1, seed = 1)
nc_completeness_capture(dat, n_perm = 99)
#> NC capture null: 99 tasks (sequential)
#> NC capture null: 10% (10/99) [0.2s]
#> NC capture null: 20% (20/99) [0.5s]
#> NC capture null: 30% (30/99) [0.7s]
#> NC capture null: 40% (40/99) [1.6s]
#> NC capture null: 51% (50/99) [1.8s]
#> NC capture null: 61% (60/99) [2.1s]
#> NC capture null: 71% (70/99) [2.3s]
#> NC capture null: 81% (80/99) [2.5s]
#> NC capture null: 91% (90/99) [2.8s]
#> NC capture null: 100% (99/99) [3s]
#> $capture_R2
#> [1] 0.616692
#>
#> $capture_pvalue
#> [1] 0
#>
#> $capture_verdict
#> [1] "strong"
#>
#> $null_distribution
#> [1] 0.008724099 0.008928810 0.012081948 0.023921185 0.014254757 0.013333922
#> [7] 0.029773923 0.016207649 0.032232805 0.032408672 0.020564075 0.025288176
#> [13] 0.021447251 0.017686638 0.018308490 0.014959142 0.034707614 0.017231756
#> [19] 0.025668071 0.024510220 0.029254301 0.015646657 0.020075614 0.037289204
#> [25] 0.014319553 0.017942267 0.019583425 0.029299869 0.023639253 0.026240893
#> [31] 0.011116603 0.010520650 0.017713280 0.021237523 0.014167138 0.026695385
#> [37] 0.025581615 0.014057918 0.014969354 0.028323007 0.008134256 0.007658334
#> [43] 0.018183770 0.008009030 0.023052488 0.019952585 0.007582754 0.013825606
#> [49] 0.019718216 0.013866528 0.024474821 0.031227315 0.008126219 0.006566353
#> [55] 0.019188921 0.016231317 0.019083737 0.016216128 0.018275726 0.023805869
#> [61] 0.023154481 0.018466259 0.024374756 0.027114979 0.014391975 0.014482670
#> [67] 0.019077723 0.019659838 0.014915116 0.018972154 0.010304153 0.031249417
#> [73] 0.008432791 0.028693459 0.031662725 0.023404222 0.019634002 0.019002577
#> [79] 0.027978437 0.028797877 0.010529774 0.044945821 0.035896621 0.013500541
#> [85] 0.025348244 0.024677247 0.014606582 0.024224230 0.020814065 0.017031917
#> [91] 0.043145251 0.017785751 0.010650629 0.017336114 0.020350415 0.020925617
#> [97] 0.017035801 0.018216804 0.019469662
#>
#> $n_features
#> [1] 10
#>
