--- 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(2026) n <- 240 z <- rnorm(n) w <- rnorm(n) 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 * z + rnorm(n) d <- data.frame(y, x, z, w, inactive) f <- y ~ x + w | z + w ``` ## Baseline IV and uniform sensitivity The `spliv()` estimator accepts the usual IV formula `y ~ X | Z`. A baseline fit with `delta = 0` is an ordinary IV calculation, while a positive `delta` allows a bounded uniform direct effect. ```{r baseline} baseline <- spliv(f, d, method = "uci", delta = 0, 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 `w` is larger. ```{r pattern} pattern <- spliv_pattern( name = "Exposure pattern", pattern = ~ w, rationale = "The alternative channel is stronger at higher exposure.", variables_used = "w", 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. Validation reports eligibility diagnostics; it does not search across candidate subgroups. ```{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." ) validation <- bpe_validate_design( f, d, design = design, vcov = "hc1", bpe_min_n_S = 40, bpe_equiv_margin = 0.25 * sd(resid(lm(x ~ w))) ) validation[c("n_S", "equivalence_passed", "eligibility_passed")] # Illustrative synthetic scale only. In a substantive analysis, pre-specify # the equivalence margin from the scientific design rather than tuning it to # obtain BPE eligibility. bpe_margin <- 0.25 * sd(resid(lm(x ~ w))) 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.