-
Notifications
You must be signed in to change notification settings - Fork 127
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fixes #299
- Loading branch information
Showing
9 changed files
with
192 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
#' Create a factor | ||
#' | ||
#' `fct()` is a stricter version of [factor()] that errors if your | ||
#' specification of `levels` is inconsistent with the values in `x`. | ||
#' | ||
#' @param x A character vector. Values must occur in either `levels` or `na`. | ||
#' @param levels A character vector of known levels. If not supplied, will | ||
#' be computed from the unique values of `x`, in the order in which they | ||
#' occur. | ||
#' @param na A character vector of values that should become missing values. | ||
#' @return A factor. | ||
#' @export | ||
#' @examples | ||
#' # Use factors when you know the set of possible values a variable might take | ||
#' x <- c("A", "O", "O", "AB", "A") | ||
#' fct(x, levels = c("O", "A", "B", "AB")) | ||
#' | ||
#' # If you don't specify the levels, fct will create from the data | ||
#' # in the order that they're seen | ||
#' fct(x) | ||
#' | ||
#' | ||
#' # Differences with base R ----------------------------------------------- | ||
#' # factor() silently generates NAs | ||
#' x <- c("a", "b", "c") | ||
#' factor(x, levels = c("a", "b")) | ||
#' # fct() errors | ||
#' try(fct(x, levels = c("a", "b"))) | ||
#' # Unless you explicitly supply NA: | ||
#' fct(x, levels = c("a", "b"), na = "c") | ||
#' | ||
#' # factor() sorts default levels: | ||
#' factor(c("y", "x")) | ||
#' # fct() uses in order of appearance: | ||
#' fct(c("y", "x")) | ||
fct <- function(x = character(), levels = NULL, na = character()) { | ||
if (!is.character(x)) { | ||
cli::cli_abort("{.arg x} must be a character vector") | ||
} | ||
if (!is.character(na)) { | ||
cli::cli_abort("{.arg na} must be a character vector") | ||
} | ||
|
||
x[x %in% na] <- NA | ||
|
||
if (is.null(levels)) { | ||
levels <- unique(x) | ||
levels <- levels[!is.na(levels)] | ||
} else if (!is.character(levels)) { | ||
cli::cli_abort("{.arg levels} must be a character vector") | ||
} | ||
|
||
invalid <- setdiff(x, c(levels, NA)) | ||
if (length(invalid) > 0 ) { | ||
cli::cli_abort(c( | ||
"All values of {.arg x} must appear in {.arg levels} or {.arg na}", | ||
i = "Missing level{?s}: {.str {invalid}}" | ||
)) | ||
} | ||
|
||
factor(x, levels = levels, exclude = NULL) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -57,6 +57,7 @@ reference: | |
|
||
- title: Other helpers | ||
contents: | ||
- fct | ||
- as_factor | ||
- fct_count | ||
- fct_match | ||
|
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# checks input types | ||
|
||
Code | ||
fct(1:3) | ||
Condition | ||
Error in `fct()`: | ||
! `x` must be a character vector | ||
Code | ||
fct("x", 1:3) | ||
Condition | ||
Error in `fct()`: | ||
! `levels` must be a character vector | ||
Code | ||
fct("x", "y", na = 1) | ||
Condition | ||
Error in `fct()`: | ||
! `na` must be a character vector | ||
|
||
# clear error if levels are incomplete | ||
|
||
Code | ||
fct(c("x", "y", "z"), c("x", "y")) | ||
Condition | ||
Error in `fct()`: | ||
! All values of `x` must appear in `levels` or `na` | ||
i Missing level: "z" | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
test_that("can create simple example", { | ||
expect_equal( | ||
fct(c("x", "y", "z")), | ||
factor(c("x", "y", "z")) | ||
) | ||
}) | ||
|
||
test_that("orders by appearance", { | ||
expect_equal( | ||
fct(c("y", "x")), | ||
factor(c("y", "x"), levels = c("y", "x")) | ||
) | ||
}) | ||
|
||
test_that("checks input types", { | ||
expect_snapshot(error = TRUE, { | ||
fct(1:3) | ||
fct("x", 1:3) | ||
fct("x", "y", na = 1) | ||
}) | ||
}) | ||
|
||
test_that("clear error if levels are incomplete", { | ||
expect_snapshot(error = TRUE, | ||
fct(c("x", "y", "z"), c("x", "y")) | ||
) | ||
}) | ||
|
||
test_that("can covert values to implicit or explcit NA", { | ||
expect_equal( | ||
fct(c("x", "y", "z"), na = "z"), | ||
factor(c("x", "y", NA), levels = c("x", "y")) | ||
) | ||
expect_equal( | ||
fct(c("x", "y", "z"), c("x", "y"), na = "z"), | ||
factor(c("x", "y", NA), levels = c("x", "y")) | ||
) | ||
expect_equal( | ||
fct(c("x", "y", "z"), c("x", "y", NA), na = "z"), | ||
factor(c("x", "y", NA), levels = c("x", "y", NA), exclude = NULL) | ||
) | ||
}) |