--- title: "Getting started with spliv" author: "Ore Koren" output: rmarkdown::html_vignette: toc: true vignette: > %\VignetteIndexEntry{Getting started with spliv} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include=FALSE} knitr::opts_chunk$set(collapse = TRUE, comment = "#>") library(spliv) set.seed(42) n <- 240 z <- rnorm(n) w <- rnorm(n) exposure <- pnorm(w) inactive <- seq_len(n) <= n / 2 x <- ifelse(inactive, 0, 1) * z + 0.4 * w + rnorm(n) y <- 1.2 * x + 0.25 * w + 0.15 * exposure * z + rnorm(n) d <- data.frame(y, x, z, w, exposure, inactive) f <- y ~ x + w | z + w ``` ## Baseline IV and uniform sensitivity The `spliv()` estimator accepts the usual IV formula `y ~ X | Z`. Ordinary exogenous controls belong on both sides, as in `y ~ x + w | z + w`. With no method or bound supplied, the baseline is UCI at `delta = 0`; a positive `delta` allows a bounded uniform direct effect. On the default scale, `delta` is an outcome-unit direct effect for a one-residual-SD instrument shift. ```{r baseline} baseline <- spliv(f, d, vcov = "hc1") baseline$estimates uniform <- spliv(f, d, method = "uci", delta = 0.20, vcov = "hc1", grid = list(steps = 9)) uniform$estimates ``` ## A patterned UCI/LTZ analysis Patterns are explicit objects with a substantive rationale. Here the direct effect is allowed to be larger where the synthetic exposure is larger. ```{r pattern} pattern <- spliv_pattern( name = "Exposure pattern", pattern = ~ exposure, rationale = "The alternative channel is stronger at higher exposure.", variables_used = "exposure", pattern_type = "theory_defined", normalize = "max_abs" ) spliv_eval_pattern(pattern, d)[1:5] patterned_uci <- spliv(f, d, method = "uci", delta = 0.20, vcov = "hc1", violation_pattern = pattern, grid = list(steps = 9)) patterned_ltz <- spliv(f, d, method = "ltz", delta = 0.20, vcov = "hc1", violation_pattern = pattern) patterned_uci$estimates patterned_ltz$estimates ``` ## Sensitivity paths and tipping points Paths make the sensitivity grid explicit. A tipping point is reported only when the supplied interval contains zero at a grid value. ```{r paths} path <- spliv_sensitivity_path( f, d, method = "uci", delta_grid = seq(0, 0.30, by = 0.05), vcov = "hc1", violation_pattern = pattern ) head(path) spliv_tipping_point(path) ``` ## Confirmatory BPE design and validation BPE uses an outcome-independent subset specified before examining the outcome analysis and requires a non-empty transportability rationale. Validation reports eligibility diagnostics; it does not search across candidate subgroups. The default `sampling` transport uses the estimated reduced-form sampling covariance; `conservative` adds a pre-specified covariance inflation. ```{r bpe} design <- bpe_design( name = "Theory-defined inactive subset", subset = ~ inactive, rationale = "The treatment channel is absent in the inactive subset.", variables_used = "inactive", subset_type = "theory_defined", pre_specified = TRUE, transportability_rationale = "The subset direct effect is informative for the target sample." ) # Illustrative synthetic margin: 0.25 residual treatment SD per # one-residual-SD instrument shift. In substantive work, pre-specify the # margin rather than tuning it to obtain BPE eligibility. bpe_margin <- 0.25 validation <- bpe_validate_design( f, d, design = design, vcov = "hc1", bpe_min_n_S = 40, bpe_equiv_margin = bpe_margin ) validation[c("n_S", "equivalence_passed", "eligibility_passed")] bpe_fit <- spliv(f, d, method = "bpe", bpe_design = design, vcov = "hc1", bpe_min_n_S = 40, bpe_equiv_margin = bpe_margin) bpe_fit$estimates ``` `bpe_explore_subsets()` is available for transparent exploratory diagnostics, but exploratory subgroup search and selecting the first passing rule are not confirmatory BPE. Confirmatory claims require a pre-specified design and a reported validation record.