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) [0.9s]
#> NC capture null: 51% (50/99) [1.2s]
#> NC capture null: 61% (60/99) [1.4s]
#> NC capture null: 71% (70/99) [1.6s]
#> NC capture null: 81% (80/99) [1.8s]
#> NC capture null: 91% (90/99) [2.1s]
#> NC capture null: 100% (99/99) [2.3s]
#> $capture_R2
#> [1] 0.616692
#>
#> $capture_pvalue
#> [1] 0
#>
#> $capture_verdict
#> [1] "strong"
#>
#> $null_distribution
#> [1] 0.023811221 0.010631048 0.010743923 0.012655256 0.017335406 0.021323739
#> [7] 0.019705726 0.007496139 0.014059617 0.023486492 0.017275701 0.032740432
#> [13] 0.009844975 0.036229150 0.020553291 0.028758753 0.011437690 0.024856088
#> [19] 0.026455246 0.031542595 0.018638829 0.037088108 0.021689140 0.015296955
#> [25] 0.025209603 0.011135585 0.021571259 0.013427914 0.010231789 0.020427127
#> [31] 0.012818920 0.010615558 0.027752575 0.009953221 0.012910560 0.013654321
#> [37] 0.025559130 0.012157132 0.011736521 0.012591878 0.023153163 0.013070338
#> [43] 0.020114944 0.036173131 0.021618213 0.045410778 0.024944078 0.016637092
#> [49] 0.015602336 0.012542551 0.008437784 0.018127338 0.013196752 0.028421198
#> [55] 0.019143591 0.024692230 0.020443707 0.028283345 0.020310990 0.011208830
#> [61] 0.033341281 0.020795356 0.047075391 0.022070932 0.029307123 0.025713386
#> [67] 0.015758224 0.024023905 0.010762807 0.011960494 0.020773284 0.024551014
#> [73] 0.033713755 0.018759640 0.020459374 0.036386361 0.024725866 0.026594438
#> [79] 0.017608485 0.020512963 0.031217196 0.013761487 0.017590866 0.009599733
#> [85] 0.041777457 0.009716157 0.011334993 0.020738306 0.019375374 0.021590861
#> [91] 0.017783899 0.025111684 0.018242955 0.006558237 0.009532424 0.023175137
#> [97] 0.010620384 0.028225261 0.023452844
#>
#> $n_features
#> [1] 10
#>
