This vignette shows how iconic stress-tests a causal
estimate by replaying the analysis on synthetic data that preserve the
observed feature texture while sweeping the strength of unmeasured
confounding and instrument exogeneity violations.
iconic is being submitted to Bioconductor. Once
accepted, install the release version with:
if (!requireNamespace("BiocManager", quietly = TRUE))
install.packages("BiocManager")
BiocManager::install("iconic")The development version is available from GitHub:
Even after diagnosis declares an estimator eligible, its validity
rests on the assumption that the genetic instrument is exogenous — that
the instrument-confounder correlations \(\rho_{G1}\) and \(\rho_{G2}\) are zero. These correlations
cannot be estimated from data (the confounders are unobserved), so
iconic_sensitivity() sweeps them over a plausible grid and
reports how each estimator’s bias degrades.
The output reports, for each estimator:
We simulate a small mediation panel, train a texture model briefly, and run the sensitivity sweep.
dat <- generate_toy_data(
n = 200, n_features = 10, seed = 1,
phi = 0.8, omega_1 = 0.7, omega_2 = 0.7
)
idat <- iconic_data(
X = dat$X, Y = dat$Y, M = dat$M,
G = dat$G, Gm = dat$Gm,
W1 = dat$W1, W2 = dat$W2,
covariates = dat$synthetic_data
)# Train a texture model briefly and attach it to the iconic_data object.
input <- load_real_input_data(
X_matrix = matrix(dat$X, nrow = 1),
Y_matrix = t(dat$Y), M_matrix = t(dat$M),
W_matrix = t(dat$W), covariates_df = dat$synthetic_data
)
idat$trained_gan <- train_gan_on_real_data(
input$gan_training_data,
feature_correlations = input$feature_correlations,
feature_texture = input$feature_texture,
epochs = 5, seed = 1, verbose = FALSE
)The sensitivity-sweep chunks in this vignette are skipped because
torch is not available. Install torch with
install.packages("torch") and run
torch::install_torch() to run them.
infer_confounding() estimates the held-fixed confounding
parameters from your data, supplying a
confounding = "inferred" mode for
iconic_sensitivity() and
iconic_prospect().
diag <- iconic_diagnose(idat)
est <- iconic_estimate(idat, diagnosis = diag)
conf <- infer_confounding(idat, diag, est)
conf#> <iconic_confounding>
#> conf_strength 0.409 (UNADJ-IV2SLS gap (NDE))
#> mo_confounding 0.025 (IV2SLS-IV2SLS2 NIE gap)
#> omega_1 0.485 (sqrt(R^2) of W on Y residualized on X+C)
#> warning: composite: coverage x confounder strength, not pure coverage
#> omega_2 0.484 (sqrt(R^2) of W on Y residualized on X+C)
#> warning: composite: coverage x confounder strength, not pure coverage
#> k 1 [CI: 1, 2] (parallel analysis (Horn, 1965))
#>
#> Unavailable: rho_G1, rho_G2
The inferred parameters include:
Parameters that cannot be inferred (the instrument-confounder correlations \(\rho_{G1}\), \(\rho_{G2}\)) fall back to defaults with a warning and are always swept.
The confounding = "default" mode uses fixed defaults
(\(\delta_{mo} = 0.8\), \(\omega_1 = \omega_2 = 0.7\), \(\phi = 0.8\)) and is the recommended
starting point. The confounding = "inferred" mode
calibrates to your data but uses estimator validity (e.g., that IV2SLS
is unbiased) to set up a benchmark whose purpose is to test estimator
validity — so inferred values should be read as best-case calibrations
under the stated assumptions.
vignette("iconic-texture-model") — how the GAN + copula
texture model is trained and why it matters for sensitivity.?iconic_sensitivity for the full argument list, including
the \(\rho_{G1} \times \rho_{G2}\) grid
and the n_iter control.#> R version 4.6.1 (2026-06-24)
#> Platform: x86_64-pc-linux-gnu
#> Running under: Ubuntu 26.04.1 LTS
#>
#> Matrix products: default
#> BLAS: /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3
#> LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.32.so; LAPACK version 3.12.0
#>
#> locale:
#> [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
#> [3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8
#> [5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
#> [7] LC_PAPER=en_US.UTF-8 LC_NAME=C
#> [9] LC_ADDRESS=C LC_TELEPHONE=C
#> [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
#>
#> time zone: Etc/UTC
#> tzcode source: system (glibc)
#>
#> attached base packages:
#> [1] stats graphics grDevices utils datasets methods base
#>
#> other attached packages:
#> [1] doRNG_1.8.6.3 rngtools_1.5.2 foreach_1.5.2 iconic_0.99.3
#> [5] BiocStyle_2.41.0
#>
#> loaded via a namespace (and not attached):
#> [1] SummarizedExperiment_1.43.0 gtable_0.3.6
#> [3] shape_1.4.6.1 xfun_0.61
#> [5] bslib_0.12.0 ggplot2_4.0.3
#> [7] processx_3.9.0 Biobase_2.73.2
#> [9] lattice_0.23-1 callr_3.8.0
#> [11] bigassertr_0.2.0 vctrs_0.7.3
#> [13] tools_4.6.1 ps_1.9.3
#> [15] generics_0.1.4 stats4_4.6.1
#> [17] parallel_4.6.1 tibble_3.3.1
#> [19] pkgconfig_2.0.3 torch_0.17.0
#> [21] Matrix_1.7-6 data.table_1.18.6.1
#> [23] RColorBrewer_1.1-3 bigstatsr_1.6.2
#> [25] S7_0.2.2 S4Vectors_0.51.10
#> [27] lifecycle_1.0.5 compiler_4.6.1
#> [29] farver_2.1.2 bigparallelr_0.3.2
#> [31] Seqinfo_1.3.2 codetools_0.2-20
#> [33] htmltools_0.5.9 sys_3.4.3
#> [35] buildtools_1.0.0 sass_0.4.10
#> [37] yaml_2.3.12 glmnet_5.0
#> [39] pillar_1.11.1 jquerylib_0.1.4
#> [41] DelayedArray_0.39.6 cachem_1.1.0
#> [43] iterators_1.0.14 abind_1.4-8
#> [45] tidyselect_1.2.1 digest_0.6.39
#> [47] dplyr_1.2.1 maketools_1.3.2
#> [49] splines_4.6.1 cowplot_1.2.0
#> [51] fastmap_1.2.0 grid_4.6.1
#> [53] SparseArray_1.13.2 cli_3.6.6
#> [55] magrittr_2.0.5 S4Arrays_1.13.0
#> [57] survival_3.8-12 withr_3.0.3
#> [59] scales_1.4.0 bit64_4.8.6
#> [61] XVector_0.53.0 rmarkdown_2.32
#> [63] bigsparser_0.7.3 matrixStats_1.5.0
#> [65] rmio_0.4.0 bit_4.6.0
#> [67] otel_0.2.0 evaluate_1.0.5
#> [69] knitr_1.52 ff_4.5.3
#> [71] GenomicRanges_1.65.4 IRanges_2.47.5
#> [73] doParallel_1.0.17 irlba_2.3.7
#> [75] rlang_1.3.0 Rcpp_1.1.2
#> [77] glue_1.8.1 BiocManager_1.30.27
#> [79] coro_1.1.0 BiocGenerics_0.59.12
#> [81] jsonlite_2.0.0 R6_2.6.1
#> [83] bigsnpr_1.12.21 MatrixGenerics_1.25.0
#> [85] flock_0.7