## ----setup, include = FALSE--------------------------------------------------- knitr::opts_chunk$set( collapse = TRUE, comment = "#>", fig.width = 7, fig.height = 5 ) ## ----simulate-data------------------------------------------------------------ library(causaldef) set.seed(42) n <- 500 # Unmeasured confounder U <- rnorm(n) # Observed covariate (partially captures U) W <- 0.7 * U + rnorm(n, sd = 0.5) # Treatment assignment (confounded by U via W) ps_true <- plogis(0.3 + 0.8 * U) A <- rbinom(n, 1, ps_true) # True causal effect beta_true <- 2.0 # Outcome (affected by A and U) Y <- 1 + beta_true * A + 1.5 * U + rnorm(n) # Negative control outcome (affected by U only, NOT by A) Y_nc <- 0.5 + 1.2 * U + rnorm(n, sd = 0.8) # Create data frame df <- data.frame(W = W, A = A, Y = Y, Y_nc = Y_nc) ## ----create-spec-------------------------------------------------------------- spec <- causal_spec( data = df, treatment = "A", outcome = "Y", covariates = "W", negative_control = "Y_nc" ) print(spec) ## ----nc-diagnostic, eval=FALSE------------------------------------------------ # nc_result <- nc_diagnostic( # spec, # method = "iptw", # alpha = 0.05, # n_boot = 200 # ) # # print(nc_result) ## ----scenario-success, eval=FALSE--------------------------------------------- # # When W = U (no unmeasured confounding) # df_full <- df # df_full$W <- U # Perfect proxy # # spec_full <- causal_spec( # df_full, "A", "Y", "W", negative_control = "Y_nc" # ) # # nc_full <- nc_diagnostic(spec_full, method = "iptw", n_boot = 100) # print(nc_full) # # Expect: falsified = FALSE ## ----scenario-fail, eval=FALSE------------------------------------------------ # # When W is noise (no information about U) # df_bad <- df # df_bad$W <- rnorm(n) # Useless proxy # # spec_bad <- causal_spec( # df_bad, "A", "Y", "W", negative_control = "Y_nc" # ) # # nc_bad <- nc_diagnostic(spec_bad, method = "iptw", n_boot = 100) # print(nc_bad) # # Expect: falsified = TRUE ## ----combined-workflow, eval=FALSE-------------------------------------------- # # Step 1: Estimate deficiency # def_results <- estimate_deficiency( # spec, # methods = c("unadjusted", "iptw", "aipw"), # n_boot = 100 # ) # # print(def_results) # # # Step 2: Run negative control diagnostic on best method # best_method <- names(which.min(def_results$estimates)) # nc_check <- nc_diagnostic(spec, method = best_method, n_boot = 100) # # # Step 3: Compute policy bounds if assumptions not falsified # if (!nc_check$falsified) { # bounds <- policy_regret_bound( # def_results, # utility_range = c(-5, 10), # method = best_method # ) # print(bounds) # } else { # warning("Causal assumptions falsified. Consider additional covariates.") # } ## ----kappa-estimation, eval=FALSE--------------------------------------------- # # If you believe Y' has 80% of Y's confounding structure: # nc_tight <- nc_diagnostic( # spec, # method = "iptw", # kappa = 0.8, # n_boot = 100 # ) # # print(nc_tight)