tests/testthat/test-cross_fit.R

df <- dplyr::tibble(
  x = rep(0:5, 2),
  y = c(0:5, 0:-5),
  z = rep(0:-5, 2),
  m = c(rep("a", 6), rep("b", 6)),
  n = c(rep("a", 4), rep("b", 4), rep("c", 4)),
  w = seq(0.4, 2.6, length.out = 12)
)

test_that("one subset, one formula", {
  fit      <- suppressWarnings(cross_fit(df, y ~ x, m))
  fit_lst  <- suppressWarnings(cross_fit(df, list(y ~ x), c(m)))
  fit_tidy <- suppressWarnings(cross_fit(df, y ~ x, m, tidy = TRUE))
  fit_unwt <- suppressWarnings(cross_fit(df, y ~ x, m, NULL))
  fit_nawt <- suppressWarnings(cross_fit(df, y ~ x, m, NA))
  expect_equal(nrow(fit), 4)
  expect_equal(ncol(fit), 19)
  expect_equal(fit$estimate, c(0, 1, 0, -1))
  expect_equal(fit, fit_lst)
  expect_equal(fit, fit_tidy)
  expect_equal(fit, fit_unwt)
  expect_equal(fit, fit_nawt)
})

test_that("no subset, one formula", {
  fit <- suppressWarnings(cross_fit(df, y ~ x))
  expect_equal(nrow(fit), 2)
  expect_equal(ncol(fit), 18)
})

test_that("one subset, two formulas", {
  fit <- suppressWarnings(cross_fit(df, list(y ~ x, y ~ z), m))
  expect_equal(nrow(fit), 8)
  expect_equal(ncol(fit), 19)
  expect_equal(fit$estimate, c(0, 1, 0, -1, 0, -1, 0, 1))
})

test_that("two subsets, one formula", {
  fit <- suppressWarnings(cross_fit(df, y ~ x, c(m, n)))
  expect_equal(nrow(fit), 8)
  expect_equal(ncol(fit), 20)
  expect_equal(fit$estimate, c(0, 1, 0, 1, 0, -1, 0, -1))
})

test_that("two subsets, two formulas", {
  fit <- suppressWarnings(cross_fit(df, c(y ~ x, y ~ z), c(m, n)))
  expect_equal(nrow(fit), 16)
  expect_equal(ncol(fit), 20)
  expect_equal(
    fit$estimate, c(0, 1, 0, 1, 0, -1, 0, -1, 0, -1, 0, -1, 0, 1, 0, 1)
  )
})

test_that("one subset, one formula, one weight", {
  fit <- suppressWarnings(cross_fit(df, y ~ x, m, w))
  expect_equal(nrow(fit), 4)
  expect_equal(ncol(fit), 20)
  expect_true(all(c("model", "m", "weights", "term") %in% names(fit)))
  expect_equal(unique(fit$weights), "w")
  expect_equal(fit$estimate, c(0, 1, 0, -1))
})

test_that("two subsets, one formula, two weights", {
  fit <- suppressWarnings(cross_fit(df, y ~ x, c(m, n), list(w, NULL)))
  expect_equal(nrow(fit), 16)
  expect_equal(ncol(fit), 21)
  expect_true(all(c("model", "m", "n", "weights", "term") %in% names(fit)))
  expect_equal(unique(fit$weights), c("NULL", "w"))
  expect_equal(
    fit$estimate, c(0, 1, 0, 1, 0, -1, 0, -1, 0, 1, 0, 1, 0, -1, 0, -1)
  )

  fit_na <- suppressWarnings(cross_fit(df, y ~ x, c(m, n), c(w, NA)))
  expect_equal(nrow(fit_na), 16)
  expect_equal(ncol(fit_na), 21)
  expect_true(all(c("model", "m", "n", "weights", "term") %in% names(fit_na)))
  expect_equal(unique(fit_na$weights), c("NA", "w"))
  expect_equal(fit_na$estimate, fit$estimate)

  fit_na_real <- suppressWarnings(cross_fit(df, y ~ x, c(m, n), c(w, NA_real_)))
  expect_equal(nrow(fit_na), 16)
  expect_equal(ncol(fit_na), 21)
  expect_true(all(c("model", "m", "n", "weights", "term") %in% names(fit_na)))
  expect_equal(unique(fit_na_real$weights), c("NA_real_", "w"))
  expect_equal(fit_na_real$estimate, fit$estimate)
})

test_that("named formulas", {
  fit <- suppressWarnings(cross_fit(df, list(x = y ~ x, z = y ~ z), m))
  expect_equal(nrow(fit), 8)
  expect_equal(ncol(fit), 19)
  expect_equal(fit$estimate, c(0, 1, 0, -1, 0, -1, 0, 1))
  expect_equal(unique(fit$model), c("x", "z"))
})

test_that("tidiers", {
  fit <- suppressWarnings(cross_fit(df, y ~ x, m, tidy = generics::tidy))
  expect_equal(nrow(fit), 4)
  expect_equal(ncol(fit), 7)

  fit_untidy <- suppressWarnings(cross_fit(df, y ~ x, m, tidy = FALSE))
  expect_equal(nrow(fit_untidy), 2)
  expect_equal(ncol(fit_untidy), 3)
  expect_s3_class(fit_untidy$fit[[1]], "lm")

  expect_equal(fit_untidy, suppressWarnings(cross_fit(df, y ~ x, m, tidy = NA)))
  expect_equal(
    fit_untidy, suppressWarnings(cross_fit(df, y ~ x, m, tidy = NULL))
  )
})

test_that("conf.int", {
  fit <- suppressWarnings(
    cross_fit(df, y ~ x, m, tidy_args = list(conf.int = TRUE))
  )
  expect_equal(nrow(fit), 4)
  expect_equal(ncol(fit), 21)
  expect_equal(
    fit,
    suppressWarnings(
      cross_fit(df, y ~ x, m, tidy = ~ tidy_glance(., conf.int = TRUE))
    )
  )
})

test_that("logit", {
  df <- data.frame(
    x = rep(c(0, 0.5, 1), 2),
    y = c(0, 0.5, 1, 1, 0.5, 0),
    m = c(rep("a", 3), rep("b", 3)),
    stringsAsFactors = FALSE
  )

  fit <- suppressWarnings(
    cross_fit(
      df, y ~ x, m, fn = glm, fn_args = list(family = binomial(link = logit))
    )
  )
  expect_equal(nrow(fit), 4)
  expect_equal(ncol(fit), 15)
  expect_equal(round(fit$estimate), c(-24, 47, 24, -47))
  expect_equal(
    fit,
    suppressWarnings(
      cross_fit(
        df, y ~ x, m, fn = ~ glm(.x, .y, family = binomial(link = logit))
      )
    )
  )
  expect_equal(
    fit,
    suppressWarnings(
      cross_fit(
        df, y ~ x, m, fn = glm,
        fn_args = list(family = binomial(link = logit), na.action = na.omit)
      )
    )
  )
})

test_that("clusters", {
  skip_if_not_installed("estimatr")

  withr::local_package("dplyr")

  fit <- suppressWarnings(
    cross_fit(df, y ~ x, clusters = list(m, n, NULL), fn = estimatr::lm_robust)
  ) %>%
    dplyr::arrange(clusters)

  fit_robust <- suppressWarnings(
    cross_fit_robust(df, y ~ x, clusters = list(m, n, NULL))
  ) %>%
    dplyr::arrange(clusters)

  fit_manual <- suppressWarnings(
    purrr::map_dfr(
      list(rlang::quo(m), rlang::quo(n), NULL),
      ~ estimatr::lm_robust(y ~ x, data = df, clusters = !!.x) %>%
        tidy_glance() %>%
        dplyr::mutate(clusters = rlang::as_label(.x), .before = 1)
    )
  ) %>%
    dplyr::as_tibble() %>%
    dplyr::arrange(clusters)

  expect_equal(fit$se_type, fit_manual$se_type)
  expect_equal(fit[, -1], fit_manual)
  expect_equal(fit, fit_robust)
  expect_equal(names(fit)[1:3], c("model", "clusters", "term"))
  expect_equal(nrow(fit), 6)
  expect_equal(ncol(fit), 18)

  expect_warning(cross_fit(df, y ~ x, clusters = list(m, n)))
})

test_that("no contrasts", {
  expect_error(cross_fit(df, x ~ m, n))
  expect_warning(
    cross_fit(df, x ~ m, n, errors = "warn"), "Invalid model specified in row 1"
  )
  fit <- suppressWarnings(cross_fit(df, x ~ m, n, errors = "warn"))
  expect_equal(ncol(fit), 19)
  expect_true(any(fit$term == "(Invalid model)"))
  expect_false(all(fit$term == "(Invalid model)"))
})

test_that("invalid weights", {
  expect_error(cross_fit(df, y ~ x, m, v))
})

test_that("invalid tidiers", {
  expect_error(cross_fit(df, y ~ x, m, tidy = character(1)))
  expect_error(cross_fit(df, y ~ x, m, tidy = y ~ x))
})

test_that("abort if not formulas", {
  expect_error(cross_fit(df, "x", m), "x.*is of class.*character")
  expect_error(cross_fit(df, list("x"), m), "x.*is of class.*character")
  expect_error(cross_fit(df, as.list(letters), m), "c.*is of class.*character")
  expect_error(cross_fit(df, as.list(letters), m), "... and 21 more")
})

Try the crossmap package in your browser

Any scripts or data that you put into this service are public.

crossmap documentation built on Jan. 13, 2023, 1:13 a.m.