tests/testthat/test-18-bounds-fixest.R

context("Testing Bounds fixest")

test_that("Significance level of bounds",
          {
            data("darfur")
            # runs regression model
            model <- fixest::feols(peacefactor ~ directlyharmed + age + farmer_dar + herder_dar +
                          pastvoted + hhsize_darfur + female + village, data = darfur)

            out <- ovb_bounds(model, treatment = "directlyharmed", benchmark_covariates = "female")
            plot.env$treatment <- NULL
            expect_error(add_bound_to_contour(out))
            expect_error(add_bound_to_contour(model = model, benchmark_covariates = "female"))

            out.g <- ovb_bounds(model, treatment = "directlyharmed", benchmark_covariates = list(female = "female"))

            out2 <- structure(list(bound_label = "1x female", r2dz.x = 0.00916428667504862,
                                   r2yz.dx = 0.12464092303637, treatment = "directlyharmed",
                                   adjusted_estimate = 0.0752202712144491,
                                   adjusted_se = 0.0218733277437572, adjusted_t = 3.43890386024675,
                                   adjusted_lower_CI = 0.0322829657274445, adjusted_upper_CI = 0.118157576701454),
                              row.names = c(NA, -1L), class = c("ovb_bounds","data.frame"))
            expect_equivalent(out, out2)
            expect_equivalent(out2, out.g)

            out <- ovb_bounds(model, treatment = "directlyharmed", benchmark_covariates = "female", alpha = 0.2)
            out2 <- structure(list(bound_label = "1x female", r2dz.x = 0.00916428667504862,
                                   r2yz.dx = 0.12464092303637, treatment = "directlyharmed",
                                   adjusted_estimate = 0.0752202712144491,
                                   adjusted_se = 0.0218733277437572, adjusted_t = 3.43890386024675,
                                   adjusted_lower_CI = 0.0471648038348768, adjusted_upper_CI = 0.103275738594021),
                              row.names = c(NA, -1L),
                              class = c("ovb_bounds", "data.frame"))
            expect_equivalent(out, out2)

            out <- ovb_bounds(model, treatment = "directlyharmed", benchmark_covariates = "female", alpha = 1)
            expect_equal(out$adjusted_estimate, out$adjusted_lower_CI)
            expect_equal(out$adjusted_estimate, out$adjusted_upper_CI)
          })

test_that("Bounds error",
          {

            expect_error(ovb_partial_r2_bound.numeric(r2dxj.x = "a", r2yxj.dx = .2))
            expect_error(ovb_partial_r2_bound.numeric(r2dxj.x = .1, r2yxj.dx = 2))
            expect_warning(ovb_partial_r2_bound.numeric(r2dxj.x = .1, r2yxj.dx = 1))
            expect_error(ovb_partial_r2_bound.numeric(r2dxj.x = 1, r2yxj.dx = .1))
            data("darfur")
            # runs regression model
            model <- fixest::feols(peacefactor ~ directlyharmed + age + farmer_dar + herder_dar +
                          pastvoted + hhsize_darfur + female + village, data = darfur)
            expect_error(ovb_partial_r2_bound.fixest(model = model, treatment = 2, benchmark_covariates = "female"))
            expect_error(ovb_partial_r2_bound.fixest(model = model, treatment = "directlyharmed", benchmark_covariates = 2))
            expect_error(ovb_partial_r2_bound.fixest(model = model, treatment = c("a","b"),
                                                 benchmark_covariates = 2))

            expect_error(ovb_partial_r2_bound.fixest(model = model, treatment = "directlyharmed",
                                                 benchmark_covariates = list(1)))

            expect_error(ovb_partial_r2_bound.fixest(model = model, treatment = "directlyharmed",
                                                 benchmark_covariates = list(a  = 1, c= "a")))

          })


test_that("Bounds warning",
          {
            model <- fixest::feols(peacefactor ~ directlyharmed + age + farmer_dar + herder_dar +
                          pastvoted + hhsize_darfur + female + village, data = darfur)

            b1 <- ovb_bounds(model, treatment = "directlyharmed", benchmark_covariates = "female")
            ovb_contour_plot(model, treatment = "female")
            expect_warning(add_bound_to_contour(b1))
            expect_warning(add_bound_to_contour(model = model,
                                                treatment = "directlyharmed",
                                                benchmark_covariates = "female"))


            b1 <- ovb_bounds(model, treatment = "directlyharmed", benchmark_covariates = "female")
            ovb_contour_plot(model, treatment = "female", sensitivity.of = "t-value")
            expect_warning(add_bound_to_contour(b1))

            b2 <- ovb_partial_r2_bound(.1, .1)
            add_bound_to_contour(b2)


          })


test_that("Group benchmarks",
          {
            model <- fixest::feols(peacefactor ~ directlyharmed + age + farmer_dar + herder_dar +
                          pastvoted + hhsize_darfur + female + village, data = darfur)

            check1 <- ovb_contour_plot(model = model,
                                       treatment = "directlyharmed",
                                       benchmark_covariates = list(`fem+past` = c("female", "pastvoted")))

            out <- sensemakr(model = model,
                             treatment = "directlyharmed",
                             benchmark_covariates = list(`fem+past` = c("female", "pastvoted")))
            check2 <- plot(out)
            expect_equal(check1, check2)

          })


test_that("Group benchmarks - simulations",
          {

            # exact
            rm(list = ls())
            set.seed(10)
            n <- 1e3
            z1 <- resid_maker(n, rep(1, n))
            z2 <- resid_maker(n, z1)
            x1 <- resid_maker(n, cbind(z1, z2))
            x2 <- resid_maker(n, cbind(z1, z2, x1))
            d  <- 2*x1 + 1*x2 + 2*z1 + 1*z2 + resid_maker(n, cbind(z1, z2, x1, x2))*5
            y  <- 2*x1 + 1*x2 + 2*z1 + 1*z2 + resid_maker(n, cbind(z1, z2, x1, x2, d))*5

            data <- data.frame(y, d, x1, x2, z1, z2)

            model <- fixest::feols(y ~ d + x1 + x2, data = data)
            model_z <- fixest::feols(y ~ d + z1 + z2, data = data)
            r2yx <- group_partial_r2(model, covariates = c("x1", "x2"))
            r2yz <- group_partial_r2(model_z, covariates = c("z1", "z2"))
            ky <- r2yz/r2yx

            model.d <- fixest::feols(y ~ d + x1 + x2, data = data)
            model.d_z <- fixest::feols(y ~ d + z1 + z2, data = data)
            r2dz <- group_partial_r2(model.d_z, covariates = c("z1", "z2"))
            r2dx <- group_partial_r2(model.d, covariates = c("x1", "x2"))
            kd <- r2dz/r2dx

            out   <- sensemakr(model = model, treatment = "d", benchmark_covariates = list(X = c("x1", "x2")), kd =kd, ky= ky)
            expect_equivalent(out$bounds$adjusted_estimate, 0)

            # conservative
            rm(list = ls())
            rcoef <- function() runif(1, -2, 2)
            n <- 1e3
            z1 <- resid_maker(n, rep(1, n))
            z2 <- resid_maker(n, z1)
            x1 <- resid_maker(n, cbind(z1, z2))
            x2 <- resid_maker(n, cbind(z1, z2, x1))
            d  <- rcoef()*x1 + rcoef()*x2 + rcoef()*z1 + rcoef()*z2 + resid_maker(n, cbind(z1, z2, x1, x2))*5
            y  <- rcoef()*x1 + rcoef()*x2 + rcoef()*z1 + rcoef()*z2 + resid_maker(n, cbind(z1, z2, x1, x2, d))*5

            data <- data.frame(y, d, x1, x2, z1, z2)

            model <- fixest::feols(y ~ d + x1 + x2, data = data)
            model_z <- fixest::feols(y ~ d + z1 + z2, data = data)
            r2yx <- group_partial_r2(model, covariates = c("x1", "x2"))
            r2yz <- group_partial_r2(model_z, covariates = c("z1", "z2"))
            ky <- r2yz/r2yx

            model.d_z <- fixest::feols(d ~ z1 + z2, data = data)
            model.d <- fixest::feols(d ~ x1 + x2, data = data)
            r2dz <- group_partial_r2(model.d_z, covariates = c("z1", "z2"))
            r2dx <- group_partial_r2(model.d, covariates = c("x1", "x2"))
            kd <- r2dz/r2dx

            out   <- sensemakr(model = model, treatment = "d", benchmark_covariates = list(X = c("x1", "x2")), kd =kd, ky= ky)
            full.model <- fixest::feols(y ~ d + x1 + x2 + z1 + z2, data = data)
            true_r2yz.dx <- group_partial_r2(full.model, covariates = c("z1", "z2"))

            full.model.d <-fixest::feols(d ~ x1 + x2 + z1 + z2, data = data)
            true_r2dz.x <- group_partial_r2(full.model.d, covariates = c("z1", "z2"))

            expect_equal(out$bounds$r2dz.x, true_r2dz.x)
            expect_true(out$bounds$r2yz.dx > true_r2yz.dx)
          })


test_that("Factor treatment and factor benchmarks",{

  data(mtcars)
  mtcars$cyl <- as.factor(mtcars$cyl)
  mtcars$gear <- as.factor(mtcars$gear)

  model <- fixest::feols(mpg ~ cyl + gear, data = mtcars)
  sens <- sensemakr(model, treatment = "cyl6", benchmark_covariates = list(gear = c("gear4", "gear5")))

  t.value <- model$coeftable["cyl6","t value"]
  rv <- robustness_value(t.value, model$nobs - model$nparams, alpha = 1)
  rv.check <- sens$sensitivity_stats$rv_q
  expect_equal(rv, rv.check)

  # benchmarks
  r2y <- group_partial_r2(model, covariates = c("gear4", "gear5"))
  mtcars <- cbind(mtcars, model.matrix(~cyl + gear + 0, data = mtcars))
  treat.model <- fixest::feols(cyl6 ~ cyl8 + gear4 + gear5, data= mtcars)
  r2d <- group_partial_r2(treat.model, covariates = c("gear4", "gear5"))
  bounds <- sensemakr:::ovb_partial_r2_bound.numeric(r2dxj.x = r2d, r2yxj.dx = r2y)
  bounds.check <- sens$bounds
  expect_equal(bounds$r2dz.x, bounds.check$r2dz.x)
  expect_equal(bounds$r2yz.dx, bounds.check$r2yz.dx)
  adj.est<- adjusted_estimate(model, treatment = "cyl6", r2dz.x = bounds$r2dz.x, r2yz.dx = bounds$r2yz.dx)
  expect_equivalent(adj.est, bounds.check$adjusted_estimate)

})
chadhazlett/sensemakr documentation built on Dec. 12, 2023, 11:20 a.m.