tests/testthat/test-interaction.R

library(dplyr)
interact_data <- data.frame(
  int_col = c(1, 1:3, 1),
  char_col = letters[c(1, 3:1, 1)],
  fct_col = factor(letters[1:5]),
  dbl_col = c(1.1, 2.2, 3.3, 4.4, 5.5),
  ordered_col = ordered(letters[6:10]),
  stringsAsFactors = FALSE
)

data(api, package = "survey")
dstrata <- apistrat %>%
   as_survey_design(strata = stype, weights = pw)

test_that("Can make an interaction", {
  x <- interact(interact_data$int_col, interact_data$char_col)

  expect_s3_class(x, "srvyr_interaction")
  expect_equal(vctrs::vec_data(x), c(1, 2, 3, 4, 1))
  expect_equal(
    attr(x, "crosswalk"),
    tibble::tibble(
      `interact_data$int_col` = c(1, 1, 2, 3),
      `interact_data$char_col` = c("a", "c", "b", "a"),
      `___srvyr_cw_id` = 1:4
    )
  )
})

test_that("Can unmake an interaction column", {
  x <- interact(int_col = interact_data$int_col, char_col = interact_data$char_col)

  orig <- uninteract(x)
  expect_equal(orig, tibble::tibble(interact_data[c("int_col", "char_col")]))
})

test_that("Can unmake all interactions in a data.frame", {
  x <- data.frame(
    a = interact(int_col = interact_data$int_col, char_col = interact_data$char_col),
    b = interact(fct_col = interact_data$fct_col, dbl_col = interact_data$dbl_col)
  )

  orig <- uninteract(x)
  expect_equal(
    orig,
    tibble::tibble(interact_data[c("int_col", "char_col", "fct_col", "dbl_col")])
  )
})

test_that("Can make interactions in a srvyr pipeline", {
  srvyr_interact <- dstrata %>%
    group_by(x = interact(stype, awards)) %>%
    pull(x)

  expect_equal(
    srvyr_interact,
    interact(stype = apistrat$stype, awards = apistrat$awards)
  )
})

test_that("A wide variety of column types are preserved in an interaction roundtrip", {
  x <- interact(!!!as.list(interact_data))

  orig <- uninteract(x)
  expect_equal(orig, tibble::tibble(interact_data))
})

test_that("Can make new columns in interact", {
  x <- interact(int_col = interact_data$int_col + 10, char_col = interact_data$char_col)

  orig <- uninteract(x)
  expected <- interact_data %>% mutate(int_col = int_col + 10) %>% select(int_col, char_col) %>% tibble::tibble()
  expect_equal(orig, expected)
})

test_that("Can combine interactions with identical crosswalks", {
  x <- data.frame(
    a = interact(int_col = interact_data$int_col, char_col = interact_data$char_col)
  )

  combined <- dplyr::bind_rows(x, x)
  expected <- dplyr::bind_rows(interact_data, interact_data) %>%
    select(int_col, char_col) %>%
    tibble::tibble()

  expect_equal(uninteract(combined$a), expected)
})

test_that("Can combine interactions with crosswalks that are superset-able", {
  x <- data.frame(
    a = interact(int_col = interact_data$int_col[1:2], char_col = interact_data$char_col[1:2])
  )
  y <- data.frame(
    a = interact(int_col = interact_data$int_col, char_col = interact_data$char_col)
  )

  combined <- dplyr::bind_rows(x, y)
  expected <- dplyr::bind_rows(interact_data[1:2, ], interact_data) %>%
    select(int_col, char_col) %>%
    tibble::tibble()

  expect_equal(uninteract(combined$a), expected)

  # Also reverse x & y
  combined <- dplyr::bind_rows(y, x)
  expected <- dplyr::bind_rows(interact_data, interact_data[1:2, ]) %>%
    select(int_col, char_col) %>%
    tibble::tibble()

  expect_equal(uninteract(combined$a), expected)
})

test_that("Get good error when crosswalks have different column names", {
  x <- data.frame(
    a = interact(int_col = interact_data$int_col[1:2], char_col = interact_data$char_col[1:2])
  )
  y <- data.frame(
    a = interact(int_col = interact_data$int_col, fct_col = interact_data$fct_col)
  )

  expect_error(
    dplyr::bind_rows(x, y),
    "Cannot cast .+ because interacted column names don't match"
  )
})

test_that("Get good error when crosswalks have different column types", {
  x <- data.frame(
    a = interact(int_col = interact_data$int_col[1:2], char_col = interact_data$char_col[1:2])
  )
  y <- data.frame(
    a = interact(int_col = interact_data$int_col, char_col = interact_data$dbl_col)
  )

  expect_error(
    dplyr::bind_rows(x, y),
    "Crosswalk columns for .+ are incompatible"
  )
})

test_that("Get good error when casting incompatible interaction croswalks", {
  x <- interact(int_col = interact_data$int_col[1:2], char_col = interact_data$char_col[1:2])
  y <- interact(int_col = interact_data$int_col, char_col = interact_data$char_col)

  expect_error(
    vec_cast(y, x, x_arg = "y", to_arg = "x"),
    "Cannot cast `y` to `x` because not all of crosswalk values in y are in x's crosswalk"
  )
})

test_that("Interaction gets automatically undone in a summarize", {
  actual <- dstrata %>%
    group_by(interact(stype, awards)) %>%
    summarize(x = survey_mean())

  alternate <- dstrata %>%
    group_by(a = interaction(stype, awards)) %>%
    summarize(stype = stype[1], awards = awards[1], x = survey_mean()) %>%
    select(-a) %>%
    arrange(stype, awards)

  expect_equal(actual, alternate)


  # Groups are recreated too
  actual <- dstrata %>%
    group_by(
      interact(yr.rnd, meals_hi = meals > median(meals)),
      interact(stype, awards)
    ) %>%
    summarize(x = survey_mean())

  alternate <- dstrata %>%
    mutate(meals_hi = meals > median(meals)) %>%
    group_by(b = interaction(yr.rnd, meals_hi), a = interaction(stype, awards)) %>%
    summarize(
      yr.rnd = yr.rnd[1],
      meals_hi = meals_hi[1],
      stype = stype[1],
      awards = awards[1],
      x = survey_mean()
    ) %>%
    ungroup() %>%
    select(-a, -b) %>%
    arrange(yr.rnd, meals_hi, stype, awards) %>%
    group_by(yr.rnd, meals_hi)


  expect_equal(actual, alternate)
})

test_that("Duplicate names are okay when unpacking in summarize", {
  expect_warning(
    actual <- dstrata %>%
      group_by(interact(stype, awards), stype) %>%
      summarize(x = survey_mean()),
    "Duplicate names found \\(stype\\) .+"
  )

  alternate <- dstrata %>%
    group_by(interact(stype, awards), stype2 = stype) %>%
    summarize(x = survey_mean()) %>%
    select(-stype2)

  expect_equal(actual, alternate)
})

test_that("Can recast interaction terms", {
  expect_equal(
    interact_data %>%
      transmute(interact(int_col, char_col) %>% recast_interact(int_col)) %>%
      uninteract(),
    interact_data %>%
      transmute(interact(int_col)) %>%
      uninteract()
  )

  expect_equal(
    interact_data %>%
      transmute(interact(int_col, char_col, fct_col) %>% recast_interact(int_col, fct_col)) %>%
      uninteract(),
    interact_data %>%
      transmute(interact(int_col, fct_col)) %>%
      uninteract()
  )
})
gergness/srvyr documentation built on Oct. 23, 2023, 2:35 a.m.