context("Noncompliance") test_that("Noncompliance", { skip_if_not_installed("AER") my_population <- declare_model(N = 100, noise = rnorm(N)) POS_Y <- declare_model(Y_D_0 = noise, Y_D_1 = Y_D_0 + 2) POS_Z <- declare_model( D_Z_0 = rbinom(n = N, size = 1, prob = pnorm(noise - 1)), D_Z_1 = rbinom(n = N, size = 1, prob = pnorm(noise + 1)) ) my_assignment <- declare_assignment(Z = complete_ra(N, m = 50)) CACE <- declare_inquiry(CACE = mean(Y_D_1[complier == 1] - Y_D_0[complier == 1])) ITT_d <- declare_inquiry(ITT_d = mean(complier)) cace_estimator <- function(data, alpha = 0.05) { fit <- AER::ivreg(Y ~ D | Z, data = data) N <- nrow(data) k <- 2 df <- N - k coef <- coef(fit) std.error <- sqrt(diag(vcov(fit))) p.value <- 2 * pt(abs(coef), df = df, lower.tail = FALSE) conf.low <- coef - qt(1 - alpha / 2, df = df) * std.error conf.high <- coef + qt(1 - alpha / 2, df = df) * std.error return_frame <- data.frame( variable_names = names(coef), estimate = coef, std.error = std.error, p.value = p.value, conf.low = conf.low, conf.high = conf.high ) return_frame[return_frame$variable_names == "D", ] } cace_hat <- declare_estimator(handler = label_estimator(cace_estimator), inquiry = CACE, label = "CACE_hat") design <- my_population + POS_Y + POS_Z + declare_step(fabricate, complier = as.numeric(D_Z_0 == 0 & D_Z_1 == 1)) + ITT_d + CACE + my_assignment + declare_measurement(D = reveal_outcomes(D ~ Z)) + declare_measurement(Y = reveal_outcomes(Y ~ D)) + cace_hat df <- draw_data(design) expect_true("complier" %in% colnames(df)) diag <- diagnose_design(design, sims = 2, bootstrap_sims = FALSE) expect_equal(diag$diagnosands$mean_estimand[1], 2) expect_equal(diag$diagnosands$estimator[1], "CACE_hat") # ITT_d is not in output - not estimated: AC: NOW IT IS! }) test_that("POs correctly assembled for noncompliance case", { pop <- declare_model( N = 10000, type = sample( c("Complier", "Never-taker", "Always-taker"), size = N, prob = c(0.5, 0.2, 0.3), replace = TRUE ), noise = rnorm(N) ) df <- pop() pos_D <- declare_potential_outcomes(D ~ as.numeric(type == "Always-taker" | type == "Complier" & Z == 1)) expect_equal(colnames(pos_D(df)), c("ID", "type", "noise", "D_Z_0", "D_Z_1")) pos_Y <- declare_potential_outcomes( Y ~ 0.4 * D * (type == "Complier") - 0.2 * (type == "Never-taker") + 0.5 * (type == "Always-taker") + noise, assignment_variables = "D" ) assignment <- declare_assignment(Z = complete_ra(N, prob = 0.5)) noncompliance <- pop + pos_D + assignment + declare_measurement(D = reveal_outcomes(D ~ Z)) + pos_Y + declare_measurement(Y = reveal_outcomes(Y ~ D)) e <- (noncompliance[[4]]) expect_true(inherits(e, "design_step")) expect_equal(attr(e, "step_type"), "measurement") }) test_that("POS don't erase Z", { pop <- declare_model(N = 10, Z = rbinom(N, size = 1, prob = .5)) po <- declare_potential_outcomes(Y ~ Z) df <- pop() expect_equal(df$Z, po(df)$Z) })