tests/testthat/test-fact.R

# fact.logical() ----

test_that("fact.logical() works", {
  x <- fact(c(TRUE, FALSE, NA))
  expect_message(capture.output(print(x)), NA)

  x <- fact(c(FALSE, NA, NA, TRUE, FALSE))
  res <- new_fact(c(2L, 3L, 3L, 1L, 2L), c(TRUE, FALSE, NA))
  expect_identical(x, res)

  expect_false(anyNA(x))
})

# fact.pseudo_id() ----

test_that("fact.pseudo_id() works", {
  expect_message(
    capture.output(print(fact(pseudo_id(c("a", "a", "b", NA_character_))))),
    NA
  )

  # Should appropriately order numeric values
  x <- c(0L, 10L, 10L, NA, 0L, 5L)
  id <- pseudo_id(x)
  f <- fact(id)
  res <- new_fact(c(1L, 3L, 3L, 4L, 1L, 2L), c(0L, 5L, 10L, NA_integer_))

  expect_identical(fact(x), f)
  expect_identical(fact(x), res)

  # Shouldn't have any NA
  expect_false(anyNA(fact(x)))

  # pseudo_id() ordered by appearance, fact() has pre-set ordering
  expect_identical(pseudo_id(f), id)

  # factors store levels as characters
  o <- order(as.integer(levels(f)))
  expect_identical(o, 1:4)
})

# fact.integer() ----

test_that("fact.integer() works", {
  expect_equal(
    fact(struct(1L, c("foo", "integer"))),
    new_fact(1L, levels = 1L)
  )
})

# fact.factor() ----

test_that("fact.factor() works", {
  x <- factor(letters)
  class(x) <- c("fact", "factor")
  expect_identical(fact(x), x)

  x <- ordered(letters)
  class(x) <- c("fact", "ordered", "factor")
  expect_identical(fact(x), x)

  x <- struct(1L, c("fact", "factor"), levels = c("a", NA_character_))
  expect_identical(fact(x), x)

  # fact.fact() checks for NA and adds
  x <- factor(c(1, NA, 2))
  expect_identical(levels(fact(x)), c("1", "2", NA_character_))

  # moves NA to the end and reordered when number
  x <- factor(c(1, NA, 2), levels = c(2, NA, 1), exclude = NULL)
  res <- new_fact(c(1, 3, 2), levels = c(1, 2, NA))
  expect_identical(fact(x), res)

  x <- factor(c(NA, TRUE, FALSE))
  res <- new_fact(c(3L, 1L, 2L), levels = c(TRUE, FALSE, NA))
  expect_identical(fact(x), res)

  x <- factor(c(NA, TRUE, FALSE), exclude = NULL)
  res <- new_fact(c(3L, 1L, 2L), levels = c(TRUE, FALSE, NA))
  expect_identical(fact(x), res)
})

# fact.haven_labelled() ----

test_that("fact.haven_labelled() works", {
  skip_if_not_installed("haven")
  .haven_as_factor <- "haven" %:::% "as_factor.haven_labelled"
  haven_as_fact <- function(...) {
    res <- fact(.haven_as_factor(...))
    attr(res, "label") <- exattr(..1, "label")
    res
  }

  expect_id_fact <- function(x) {
    testthat::expect_identical(
      fact(x),
      haven_as_fact(x),
      ignore_attr = c("uniques", "na")
    )
  }

  # Integers
  r <- rep(1:3, 2)
  x <- haven::labelled(r, labels = c(good = 1, bad = 3))
  expect_id_fact(x)

  x <- haven::labelled(r, labels = c(good = 1, bad = 3), label = "this")
  expect_id_fact(x)

  x <- haven::labelled(
    r,
    labels = c(good = 1, neutral = 2, bad = 3),
    label = "this"
  )
  expect_id_fact(x)

  x <- haven::labelled(r, label = "this")
  expect_id_fact(x)

  # Doubles
  x <- haven::labelled(c(0, 0.5, 1), c(a = 0, b = 1))
  expect_id_fact(x)

  # Character
  x <- haven::labelled(letters, c(good = "j", something = "m", cool = "b"))
  expect_id_fact(x)

  # Unique not in levels; levels not in unique
  x <- haven::labelled(
    c(-10, 20, 40, 60),
    labels = c(a = 10, b = 20, c = 30, d = 40),
    label = "foo"
  )
  expect_id_fact(x)
})

# nas ----

test_that("fact() correctly labels NAs [#24]", {
  expect_equal(
    fact(c(NA, "a", "b")),
    new_fact(c(3L, 1L, 2L), c("a", "b", NA))
  )

  expect_equal(
    fact(c(NA, 1, 3)),
    new_fact(c(3L, 1L, 2L), c(1, 3, NA))
  )

  expect_equal(
    fact(c(1, NA, NA, 3)),
    new_fact(c(1L, 3L, 3L, 2L), c(1, 3, NA))
  )

  expect_equal(
    fact(c(TRUE, TRUE, NA, FALSE, TRUE)),
    new_fact(c(1L, 1L, 3L, 2L, 1L), c(TRUE, FALSE, NA))
  )
})


test_that("fact() ignores NaN", {
  # ignore NaN
  res <- fact(c(1, 2, NA, 3, NaN))
  exp <- struct(
    c(1L, 2L, 4L, 3L, 4L),
    class = c("fact", "factor"),
    levels = c("1", "2", "3", NA),
    uniques = c(1, 2, 3, NA),
    na = 4L
  )

  expect_identical(res, exp)
})


# ordering ----

test_that("as_ordered() works", {
  res <- fact(c(1:3, NA_integer_))
  exp <- struct(
    c(1:3, NA_integer_),
    c("fact", "ordered", "factor"),
    levels = as.character(1:3),
    uniques = 1:3,
    na = 0L
  )
  expect_identical(as_ordered(res), exp)
})

test_that("as_ordered() doesn't duplicate class", {
  res <- class(as_ordered(as.ordered(letters[1:3])))
  expect_identical(res, c("fact", "ordered", "factor"))
})


# fact.default() ----------------------------------------------------------

test_that("fact.default() fails", {
  expect_error(fact(struct(NULL, "foo")))
})


# `fact_levels<-`() -------------------------------------------------------

test_that("`fact_levels<-`() works", {
  x <- fact(1:3)
  fact_levels(x) <- 1:4
  exp <- struct(
    1:3,
    class = c("fact", "factor"),
    levels = as.character(1:4),
    uniques = 1:4,
    na = 0L
  )
  expect_identical(x, exp)
})


# fact_coerce_levels() ----------------------------------------------------

test_that("fact_coerce_levels() works", {
  x <- as.Date("2021-09-03") + 0:2
  expect_equal(fact_coerce_levels(as.character(x)), x)

  # Be careful about setting a time zone
  # Not very good for dealing with local
  # NOTE r-dev after 4.2.1 has some weird behavior with the 0 and returns:
  #  ('2021-09-03', '2021-09-03 00:00:01', '2021-09-03 00:00:02')
  x <- as.POSIXlt("2021-09-03", tz = "UTC") + 1:3
  expect_equal(fact_coerce_levels(as.character(x)), x)

  x <- as.POSIXlt("2021-09-03", tz = "UTC") + 1:3
  expect_equal(fact_coerce_levels(as.character(x)), x)
})


# try_numeric() -----------------------------------------------------------

test_that("try_numeric() works", {
  x <- 1
  expect_identical(try_numeric(x), x)

  x <- c(NA, NA)
  expect_identical(try_numeric(x), x)

  x <- c("a", 1)
  expect_identical(try_numeric(x), x)

  x <- c(1, NA, 2)
  expect_identical(try_numeric(as.character(x)), x)
})


# drop_levels -------------------------------------------------------------

test_that("drop_levels() works", {
  x <- factor(1, 1:2)
  exp <- factor(1, 1)
  expect_equal(drop_levels(x), exp)

  df <- quick_dfl(x = x, y = 1)
  df_exp <- quick_dfl(x = exp, y = 1)
  expect_equal(drop_levels(df), df_exp)

  # facts and ordered
  x <- fact(1:10)
  expect_identical(drop_levels(x), x)

  x <- as_ordered(factor(1, 1:2))
  exp <- struct(
    1L,
    class = c("fact", "ordered", "factor"),
    levels = "1",
    uniques = 1L,
    na = 0L
  )
  expect_equal(drop_levels(x), exp)
})


# fact_reverse() ----------------------------------------------------------

test_that("fact_reverse() works", {
  res <- fact_reverse(1:4)
  exp <- new_fact(4:1, 4:1)
  expect_identical(res, exp)

  res <- fact_reverse(as_ordered(1:4))
  exp <- new_fact(4:1, 4:1, ordered = TRUE)
  expect_identical(res, exp)

  res <- fact_reverse(c(1:3, NA))
  exp <- new_fact(c(3:1, 4L), c(3:1, NA))
  expect_identical(res, exp)

  res <- fact_reverse(as_ordered(c(1:3, NA)))
  exp <- struct(
    c(3:1, NA),
    class = c("fact", "ordered", "factor"),
    levels = c("3", "2", "1"),
    uniques = 3:1,
    na = 0L
  )

  expect_identical(res, exp)
})



# other methods -----------------------------------------------------------

test_that("[.fact() works", {
  x <- fact(1:3)
  x1 <- do.call(structure, c(1, attributes(x)))
  x2 <- do.call(structure, c(2, attributes(x)))
  expect_identical(x[1], x1)
  expect_identical(x[2], x2)
})

test_that("is.na.fact(), works", {
  x <- fact(c(1, 2, NA, 3))
  res <- is.na(x)
  exp <- c(FALSE, FALSE, FALSE, FALSE)
  expect_identical(res, exp)

  x <- fact_na(c(1, 2, NA, 3))
  res <- is.na(x)
  exp <- c(FALSE, FALSE, TRUE, FALSE)
  expect_identical(res, exp)

  x <- fact_na(c("a", "b", "c"))
  res <- is.na(x)
  exp <- c(FALSE, FALSE, FALSE)
  expect_identical(res, exp)
})

test_that("as.integer.fact() works", {
  x <- fact(c(1, 2, NA, 3))
  res <- as.integer(x)
  exp <- c(1L, 2L, NA_integer_, 3L)
  expect_identical(res, exp)
})

test_that("as.integer.fact() works", {
  x <- fact(c(1, 2, NA, 3))
  res <- as.double(x)
  exp <- c(1, 2, NA_real_, 3)
  expect_identical(res, exp)
  expect_identical(as.numeric(x), exp)
})

test_that("unique.fact() works", {
  x <- fact(c(1, 2, NA, 3, 2))
  exp <- fact(c(1, 2, NA, 3))
  res <- unique(x)
  expect_identical(exp, res)

  x <- as_ordered(x)
  exp <- as_ordered(exp)
  res <- unique(x)
  expect_identical(exp, res)
})

test_that("as.Date.fact() works", {
  exp <- as.Date(c("2022-01-02", NA, "1908-12-21"))
  res <- as.Date(fact(exp))
  expect_identical(exp, res)

  x <- c("01-01-2022", "01-02-2000")
  exp <- as.Date(x, "%d-%m-%Y")
  res <- as.Date(fact(x), "%d-%m-%Y")
  expect_identical(exp, res)
})

test_that("as.character.fact() works", {
  exp <- c("a", NA_character_, "b", "b", "a")
  res <- as.character(fact(exp))
  expect_identical(exp, res)
})

# snapshots ---------------------------------------------------------------

test_that("snapshots", {
  expect_snapshot(fact(character()))
  expect_snapshot(fact(1:5))
  expect_snapshot(print(fact(1:100), max_levels = TRUE))
  expect_snapshot(print(fact(1:100), max_levels = 20))
  expect_snapshot(print(fact(1:100), max_levels = 100))
})
jmbarbone/jordan documentation built on April 1, 2024, 7:46 p.m.