Skip to content

Commit

Permalink
New labeller: label_dictionary() (#461)
Browse files Browse the repository at this point in the history
  • Loading branch information
teunbrand authored Oct 22, 2024
1 parent 0f3929a commit e5bb288
Show file tree
Hide file tree
Showing 9 changed files with 120 additions and 1 deletion.
1 change: 1 addition & 0 deletions NAMESPACE
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ export(label_comma)
export(label_currency)
export(label_date)
export(label_date_short)
export(label_dictionary)
export(label_dollar)
export(label_glue)
export(label_log)
Expand Down
1 change: 1 addition & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using `get_palette()` or registered using `set_palette()` (#396).
* `label_log()` has a `signed` argument for displaying negative numbers
(@teunbrand, #421).
* New `label_dictionary()` for named lookup of labels (#458).

* New function `compose_label()` to chain together label formatting functions
(#462)
Expand Down
54 changes: 54 additions & 0 deletions R/label-dictionary.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@

#' Labels from lookup tables
#'
#' Use `label_dictionary()` for looking up succinct breaks in a named character
#' vector giving complete labels.
#'
#' @param dictionary A named character vector of labels. The names are expected
#' to match the breaks, and the values become the labels.
#' @param nomatch A string to label breaks that do not match any name in
#' `dictionary`. When `NULL` (default), the breaks are not translated but are
#' kept as-is.
#'
#' @return A labeller function that takes a character vector of breaks and
#' returns a character vector of labels.
#' @export
#' @family labels for discrete scales
#' @examples
#' # Example lookup table
#' lut <- c(
#' "4" = "four wheel drive",
#' "r" = "rear wheel drive",
#' "f" = "front wheel drive"
#' )
#'
#' # Typical usage
#' demo_discrete(c("4", "r", "f"), labels = label_dictionary(lut))
#' # By default, extra values ('w') will remain as-is
#' demo_discrete(c("4", "r", "f", "w"), labels = label_dictionary(lut))
#' # Alternatively, you can relabel extra values
#' demo_discrete(
#' c("4", "r", "f", "w"),
#' labels = label_dictionary(lut, nomatch = "unknown")
#' )
label_dictionary <- function(dictionary = character(), nomatch = NULL) {

if (!is.character(dictionary)) {
cli::cli_abort("The {.arg dictionary} argument must be a character vector.")
}
if (!is_named2(dictionary)) {
cli::cli_abort("The {.arg dictionary} argument must have names.")
}
names <- names(dictionary)
values <- unname(dictionary)

force(nomatch)

function(x) {
i <- match(x, names, nomatch = NA_integer_)
out <- values[i]
missing <- is.na(i)
out[missing] <- if (is.null(nomatch)) x[missing] else nomatch
out
}
}
49 changes: 49 additions & 0 deletions man/label_dictionary.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions man/label_glue.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions man/label_parse.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions man/label_wrap.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion man/number_options.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions tests/testthat/test-label-dictionary.R
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
test_that("label_dictionary gives correct answers", {

short <- c("A", "B", "C")
lut <- c("A" = "Apple", "C" = "Cherry", "D" = "Date")

expect_equal(label_dictionary(lut)(short), c("Apple", "B", "Cherry"))
expect_equal(
label_dictionary(lut, nomatch = "Banana")(short),
c("Apple", "Banana", "Cherry")
)
})

0 comments on commit e5bb288

Please sign in to comment.