diff --git a/NAMESPACE b/NAMESPACE index 323e34ba..4f9a1766 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,9 +1,11 @@ # Generated by roxygen2: do not edit by hand S3method(as_continuous_pal,"function") +S3method(as_continuous_pal,character) S3method(as_continuous_pal,default) S3method(as_continuous_pal,pal_discrete) S3method(as_discrete_pal,"function") +S3method(as_discrete_pal,character) S3method(as_discrete_pal,default) S3method(as_discrete_pal,pal_continuous) S3method(fullseq,Date) @@ -50,6 +52,7 @@ export(asinh_trans) export(asn_trans) export(atanh_trans) export(boxcox_trans) +export(breaks_exp) export(breaks_extended) export(breaks_log) export(breaks_pretty) @@ -96,7 +99,9 @@ export(exp_trans) export(expand_range) export(extended_breaks) export(format_format) +export(format_log) export(fullseq) +export(get_palette) export(gradient_n_pal) export(grey_pal) export(hms_trans) @@ -138,6 +143,7 @@ export(log_trans) export(logit_trans) export(manual_pal) export(math_format) +export(minor_breaks_log) export(minor_breaks_n) export(minor_breaks_width) export(modulus_trans) @@ -149,6 +155,7 @@ export(number) export(number_bytes) export(number_bytes_format) export(number_format) +export(number_options) export(oob_censor) export(oob_censor_any) export(oob_discard) @@ -176,6 +183,7 @@ export(pal_seq_gradient) export(pal_shape) export(pal_viridis) export(palette_na_safe) +export(palette_names) export(palette_nlevels) export(palette_type) export(parse_format) @@ -194,10 +202,12 @@ export(rescale_max) export(rescale_mid) export(rescale_none) export(rescale_pal) +export(reset_palettes) export(reverse_trans) export(scientific) export(scientific_format) export(seq_gradient_pal) +export(set_palette) export(shape_pal) export(show_col) export(sqrt_trans) diff --git a/NEWS.md b/NEWS.md index 9e2f72f3..21c97925 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,13 @@ # scales (development version) * New `label_date_short(leading)` argument to replace leading zeroes (#442) +* `breaks_pretty()` will return the input limit when it has no range (#446) +* `transform_exp()` now has more sensible breaks, available in `breaks_exp()` + (@teunbrand, #405). +* The scales package now keeps track of known palettes. These can be retrieved + using `get_palette()` or registered using `set_palette()` (#396). +* `label_log()` has a `signed` argument for displaying negative numbers + (@teunbrand, #421). # scales 1.3.0 diff --git a/R/breaks-log.R b/R/breaks-log.R index 79acceb4..cbfe7cfc 100644 --- a/R/breaks-log.R +++ b/R/breaks-log.R @@ -82,6 +82,89 @@ breaks_log <- function(n = 5, base = 10) { #' @rdname breaks_log log_breaks <- breaks_log +#' Minor breaks for log-10 axes +#' +#' This break function is designed to mark every power, multiples of 5 and/or 1 +#' of that power for base 10. +#' +#' @param detail Any of `1`, `5` and `10` to mark multiples of +#' powers, multiples of 5 of powers or just powers respectively. +#' @param smallest Smallest absolute value to mark when the range includes +#' negative numbers. +#' +#' @return A function to generate minor ticks. +#' @export +#' +#' @examples +#' # Standard usage with log10 scale +#' demo_log10(c(1, 1e10), minor_breaks = minor_breaks_log()) +#' # Increasing detail over many powers +#' demo_log10(c(1, 1e10), minor_breaks = minor_breaks_log(detail = 1)) +#' # Adjusting until where to draw minor breaks +#' demo_continuous( +#' c(-1000, 1000), +#' transform = asinh_trans(), +#' minor_breaks = minor_breaks_log(smallest = 1) +#' ) +minor_breaks_log <- function(detail = NULL, smallest = NULL) { + if (!is.null(detail) && (!length(detail) == 1 || !detail %in% c(1, 5, 10))) { + cli::cli_abort("The {.arg detail} argument must be one of 1, 5 or 10.") + } + if (!is.null(smallest) && + (!length(smallest) == 1 || smallest < 1e-100 || !is.finite(smallest))) { + cli::cli_abort( + "The {.arg smallest} argument must be a finite, positive, non-zero number." + ) + } + force(smallest) + function(x, ...) { + + has_negatives <- any(x <= 0) + + if (has_negatives) { + large <- max(abs(x)) + small <- smallest %||% min(c(1, large) * 0.1) + x <- sort(c(small * 10, large)) + } + + start <- floor(log10(min(x))) - 1L + end <- ceiling(log10(max(x))) + 1L + + if (is.null(detail)) { + i <- findInterval(abs(end - start), c(8, 15), left.open = TRUE) + 1L + detail <- c(1, 5, 10)[i] + } + + ladder <- 10^seq(start, end, by = 1L) + tens <- fives <- ones <- numeric() + if (detail %in% c(10, 5, 1)) { + tens <- ladder + } + if (detail %in% c(5, 1)) { + fives <- 5 * ladder + } + if (detail == 1) { + ones <- as.vector(outer(1:9, ladder)) + ones <- setdiff(ones, c(tens, fives)) + } + + if (has_negatives) { + tens <- tens[tens >= small] + tens <- c(tens, -tens, 0) + fives <- fives[fives >= small] + fives <- c(fives, -fives) + ones <- ones[ones >= small] + ones <- c(ones, -ones) + } + + ticks <- c(tens, fives, ones) + n <- c(length(tens), length(fives), length(ones)) + + attr(ticks, "detail") <- rep(c(10, 5, 1), n) + ticks + } +} + #' @author Thierry Onkelinx, \email{thierry.onkelinx@inbo.be} #' @noRd log_sub_breaks <- function(rng, n = 5, base = 10) { diff --git a/R/breaks.R b/R/breaks.R index 947f3aa6..adf194d2 100644 --- a/R/breaks.R +++ b/R/breaks.R @@ -122,6 +122,9 @@ breaks_pretty <- function(n = 5, ...) { force_all(n, ...) n_default <- n function(x, n = n_default) { + if (zero_range(as.numeric(x))) { + return(x[1]) + } breaks <- pretty(x, n, ...) names(breaks) <- attr(breaks, "labels") breaks @@ -182,3 +185,31 @@ breaks_timespan <- function(unit = c("secs", "mins", "hours", "days", "weeks"), as.difftime(breaks * scale, units = "secs") } } + +#' Breaks for exponentially transformed data +#' +#' This breaks function typically labels zero and the last `n - 1` integers of a +#' range if that range is large enough (currently: 3). For smaller ranges, it +#' uses [`breaks_extended()`]. +#' +#' @inheritParams breaks_extended +#' @export +#' @examples +#' # Small range +#' demo_continuous(c(100, 102), transform = "exp", breaks = breaks_exp()) +#' # Large range +#' demo_continuous(c(0, 100), transform = "exp", breaks = breaks_exp(n = 4)) +breaks_exp <- function(n = 5, ...) { + n_default <- n + default <- extended_breaks(n = n_default, ...) + function(x, n = n_default) { + # Discard -Infs + x <- sort(pmax(x, 0)) + top <- floor(x[2]) + if (top >= 3 && abs(diff(x)) >= 3) { + unique(c(top - seq_len(min(top, n_default - 1)) + 1, 0)) + } else { + default(x) + } + } +} diff --git a/R/colour-manip.R b/R/colour-manip.R index 5de30897..c4f15d85 100644 --- a/R/colour-manip.R +++ b/R/colour-manip.R @@ -87,6 +87,14 @@ alpha <- function(colour, alpha = NA) { show_col <- function(colours, labels = TRUE, borders = NULL, cex_label = 1, ncol = NULL) { n <- length(colours) + if (n == 1 && (is.function(colours) || !is_color(colours))) { + colours <- as_discrete_pal(colours) + n <- palette_nlevels(colours) + n <- if (is.na(n)) 16 else n + colours <- colours(n = n) + n <- length(colours) + } + ncol <- ncol %||% ceiling(sqrt(length(colours))) nrow <- ceiling(n / ncol) diff --git a/R/label-currency.R b/R/label-currency.R index 56979a2f..98d18e3d 100644 --- a/R/label-currency.R +++ b/R/label-currency.R @@ -48,8 +48,11 @@ #' scale_cut = c(0, k = 1e3, m = 1e6, bn = 1e9, tn = 1e12) #' ) #' demo_log10(c(1, 1e12), breaks = log_breaks(5, 1e3), labels = gbp) -label_currency <- function(accuracy = NULL, scale = 1, prefix = "$", - suffix = "", big.mark = ",", decimal.mark = ".", +label_currency <- function(accuracy = NULL, scale = 1, + prefix = NULL, + suffix = NULL, + big.mark = NULL, + decimal.mark = NULL, trim = TRUE, largest_with_fractional = 100000, ...) { force_all( @@ -144,13 +147,17 @@ dollar_format <- function(accuracy = NULL, scale = 1, prefix = "$", #' @export #' @rdname dollar_format #' @param x A numeric vector -dollar <- function(x, accuracy = NULL, scale = 1, prefix = "$", - suffix = "", big.mark = ",", decimal.mark = ".", +dollar <- function(x, accuracy = NULL, scale = 1, prefix = NULL, + suffix = NULL, big.mark = NULL, decimal.mark = NULL, trim = TRUE, largest_with_cents = 100000, negative_parens = deprecated(), style_negative = c("hyphen", "minus", "parens"), scale_cut = NULL, ...) { + prefix <- prefix %||% getOption("scales.currency.prefix", default = "$") + suffix <- suffix %||% getOption("scales.currency.suffix", default = "") + big.mark <- big.mark %||% getOption("scales.currency.big.mark", default = ",") + decimal.mark <- decimal.mark %||% getOption("scales.currency.decimal.mark", default = ".") if (length(x) == 0) { return(character()) } diff --git a/R/label-date.R b/R/label-date.R index adb82262..b2735eac 100644 --- a/R/label-date.R +++ b/R/label-date.R @@ -11,10 +11,10 @@ #' suffix to the input (ns, us, ms, s, m, h, d, w). #' #' @inherit label_number return -#' @param format For `date_format()` and `time_format()` a date/time format +#' @param format For `label_date()` and `label_time()` a date/time format #' string using standard POSIX specification. See [strptime()] for details. #' -#' For `date_short()` a character vector of length 4 giving the format +#' For `label_date_short()` a character vector of length 4 giving the format #' components to use for year, month, day, and hour respectively. #' @param tz a time zone name, see [timezones()]. Defaults #' to UTC @@ -33,9 +33,9 @@ #' #' two_months <- date_range("2020-05-01", 60) #' demo_datetime(two_months) -#' demo_datetime(two_months, labels = date_format("%m/%d")) -#' demo_datetime(two_months, labels = date_format("%e %b", locale = "fr")) -#' demo_datetime(two_months, labels = date_format("%e %B", locale = "es")) +#' demo_datetime(two_months, labels = label_date("%m/%d")) +#' demo_datetime(two_months, labels = label_date("%e %b", locale = "fr")) +#' demo_datetime(two_months, labels = label_date("%e %B", locale = "es")) #' # ggplot2 provides a short-hand: #' demo_datetime(two_months, date_labels = "%m/%d") #' diff --git a/R/label-log.R b/R/label-log.R index 802d2a13..e31e2bb8 100644 --- a/R/label-log.R +++ b/R/label-log.R @@ -1,10 +1,18 @@ #' Label numbers in log format (10^3, 10^6, etc) #' -#' `label_log()` displays numbers as base^exponent, using superscript formatting. +#' `label_log()` and `format_log()` display numbers as base^exponent, using +#' superscript formatting. `label_log()` returns expressions suitable for +#' labelling in scales, whereas `format_log()` returns deparsed text. #' +#' +#' @param x A numeric vector to format #' @param base Base of logarithm to use #' @param digits Number of significant digits to show for the exponent. Argument #' is passed on to [base::format()]. +#' @param signed Should a `+` or `-` be displayed as a prefix? The +#' default, `NULL`, displays signs if there are zeroes or negative numbers +#' present. +#' @param ... Passed on to `format()`. #' @inherit label_number return #' @seealso [breaks_log()] for the related breaks algorithm. #' @export @@ -12,19 +20,43 @@ #' @examples #' demo_log10(c(1, 1e5), labels = label_log()) #' demo_log10(c(1, 1e5), breaks = breaks_log(base = 2), labels = label_log(base = 2)) -label_log <- function(base = 10, digits = 3) { +#' format_log(c(0.1, 1, 10)) +label_log <- function(base = 10, digits = 3, signed = NULL) { function(x) { - if (length(x) == 0) { - return(expression()) - } - - exponent <- format(log(x, base = base), digits = digits) - text <- paste0(base, "^", exponent) + text <- format_log(x, base = base, signed = signed, digits = digits) ret <- parse_safe(text) - # restore NAs from input vector ret[is.na(x)] <- NA - ret } } + +#' @export +#' @rdname label_log +format_log <- function(x, base = 10, signed = NULL, ...) { + + if (length(x) == 0) { + return(character()) + } + prefix <- rep("", length(x)) + finites <- x[is.finite(x)] + + signed <- signed %||% any(finites <= 0) + if (signed) { + sign <- sign(x) + prefix[sign == +1] <- "+" + prefix[sign == -1] <- "-" + x <- abs(x) + x[x == 0] <- 1 + } + + exponent <- format(zapsmall(log(x, base = base)), ...) + text <- paste0(prefix, base, "^", exponent) + + if (signed) { + text[sign == 0] <- "0" + } + text[is.na(x)] <- NA + + text +} diff --git a/R/label-number.R b/R/label-number.R index a8a335ae..b5dd04de 100644 --- a/R/label-number.R +++ b/R/label-number.R @@ -28,8 +28,11 @@ #' processed so that `prefix = "$"` will yield (e.g.) `-$1` and `($1)`. #' @param suffix Additional text to display after the number. #' @param big.mark Character used between every 3 digits to separate thousands. +#' The default (`NULL`) retrieves the setting from the +#' [number options][number_options]. #' @param decimal.mark The character to be used to indicate the numeric -#' decimal point. +#' decimal point. The default (`NULL`) retrieves the setting from the +#' [number options][number_options]. #' @param style_positive A string that determines the style of positive numbers: #' #' * `"none"` (the default): no change, e.g. `1`. @@ -38,6 +41,9 @@ #' as wide as a number or `+`. Compared to `"none"`, adding a figure space #' can ensure numbers remain properly aligned when they are left- or #' right-justified. +#' +#' The default (`NULL`) retrieves the setting from the +#' [number options][number_options]. #' @param style_negative A string that determines the style of negative numbers: #' #' * `"hyphen"` (the default): preceded by a standard hypen `-`, e.g. `-1`. @@ -45,6 +51,9 @@ #' nicety that ensures `-` aligns with the horizontal bar of the #' the horizontal bar of `+`. #' * `"parens"`, wrapped in parentheses, e.g. `(1)`. +#' +#' The default (`NULL`) retrieves the setting from the +#' [number options][number_options]. #' @param scale_cut Named numeric vector that allows you to rescale large #' (or small) numbers and add a prefix. Built-in helpers include: #' * `cut_short_scale()`: [10^3, 10^6) = K, [10^6, 10^9) = M, [10^9, 10^12) = B, [10^12, Inf) = T. @@ -109,9 +118,9 @@ #' demo_continuous(c(32, 212), labels = label_number(suffix = "\u00b0F")) #' demo_continuous(c(0, 100), labels = label_number(suffix = "\u00b0C")) label_number <- function(accuracy = NULL, scale = 1, prefix = "", - suffix = "", big.mark = " ", decimal.mark = ".", - style_positive = c("none", "plus", "space"), - style_negative = c("hyphen", "minus", "parens"), + suffix = "", big.mark = NULL, decimal.mark = NULL, + style_positive = NULL, + style_negative = NULL, scale_cut = NULL, trim = TRUE, ...) { force_all( @@ -225,17 +234,21 @@ comma_format <- label_comma #' @inheritParams label_number #' @return A character vector of `length(x)`. number <- function(x, accuracy = NULL, scale = 1, prefix = "", - suffix = "", big.mark = " ", decimal.mark = ".", - style_positive = c("none", "plus", "space"), - style_negative = c("hyphen", "minus", "parens"), + suffix = "", big.mark = NULL, decimal.mark = NULL, + style_positive = NULL, + style_negative = NULL, scale_cut = NULL, trim = TRUE, ...) { if (length(x) == 0) { return(character()) } + big.mark <- big.mark %||% getOption("scales.big.mark", default = " ") + decimal.mark <- decimal.mark %||% getOption("scales.decimal.mark", default = ".") + style_positive <- style_positive %||% getOption("scales.style_positive", default = "none") + style_negative <- style_negative %||% getOption("scales.style_negative", default = "hyphen") - style_positive <- arg_match(style_positive) - style_negative <- arg_match(style_negative) + style_positive <- arg_match(style_positive, c("none", "plus", "space")) + style_negative <- arg_match(style_negative, c("hyphen", "minus", "parens")) if (!is.null(scale_cut)) { cut <- scale_cut(x, @@ -298,6 +311,58 @@ number <- function(x, accuracy = NULL, scale = 1, prefix = "", ret } +#' Number options +#' +#' Control the settings for formatting numbers globally. +#' +#' @inheritParams label_number +#' @param currency.prefix,currency.suffix,currency.decimal.mark,currency.big.mark +#' Settings for [`label_currency()`] passed on without the `currency.`-prefix. +#' @param ordinal.rules Setting for [`label_ordinal()`] passed on without the +#' `ordinal.`-prefix. +#' +#' @return The old options invisibly +#' @export +#' +#' @examples +#' # Default number formatting +#' x <- c(0.1, 1, 1000) +#' label_number()(x) +#' +#' # Now again with new options set +#' number_options(style_positive = "plus", decimal.mark = ",") +#' label_number()(x) +#' +#' # The options are the argument names with a 'scales.'-prefix +#' options("scales.style_positive") +#' +#' # Resetting the options to their defaults +#' number_options() +#' label_number()(x) +number_options <- function( + decimal.mark = ".", + big.mark = " ", + style_positive = c("none", "plus", "space"), + style_negative = c("hyphen", "minus", "parens"), + currency.prefix = "$", + currency.suffix = "", + currency.decimal.mark = decimal.mark, + currency.big.mark = setdiff(c(".", ","), currency.decimal.mark)[1], + ordinal.rules = ordinal_english() +) { + opts <- options( + scales.decimal.mark = decimal.mark, + scales.big.mark = big.mark, + scales.style_positive = arg_match(style_positive), + scales.style_negative = arg_match(style_negative), + scales.currency.prefix = currency.prefix, + scales.currency.suffix = currency.suffix, + scales.currency.decimal.mark = currency.decimal.mark, + scales.currency.big.mark = currency.big.mark, + scales.ordinal.rules = ordinal.rules + ) + invisible(opts) +} # Helpers ----------------------------------------------------------------- @@ -350,6 +415,7 @@ scale_cut <- function(x, breaks, scale = 1, accuracy = NULL, suffix = "") { if (any(bad_break)) { # If the break below result in a perfect cut, prefer it lower_break <- breaks[match(break_suffix[bad_break], names(breaks)) - 1] + lower_break[lower_break == 0] <- 1 # Avoid choosing a non-existent break improved_break <- (x[bad_break] * scale / lower_break) %% 1 == 0 # Unless the break below is a power of 10 change (1.25 is as good as 1250) power10_break <- log10(breaks[break_suffix[bad_break]] / lower_break) %% 1 == 0 diff --git a/R/label-ordinal.R b/R/label-ordinal.R index b9de36f4..c4cdeafc 100644 --- a/R/label-ordinal.R +++ b/R/label-ordinal.R @@ -28,8 +28,8 @@ #' labels = label_ordinal(), #' breaks = breaks_width(2) #' ) -label_ordinal <- function(prefix = "", suffix = "", big.mark = " ", - rules = ordinal_english(), ...) { +label_ordinal <- function(prefix = "", suffix = "", big.mark = NULL, + rules = NULL, ...) { force_all(prefix, suffix, big.mark, rules, ...) function(x) { ordinal( @@ -96,7 +96,9 @@ ordinal_format <- label_ordinal #' @export #' @rdname ordinal_format ordinal <- function(x, prefix = "", suffix = "", big.mark = " ", - rules = ordinal_english(), ...) { + rules = NULL, ...) { + + rules <- rules %||% getOption("scales.ordinal.rules", default = ordinal_english()) na_idx <- is.na(x) x <- round(x, digits = 0) x[na_idx] <- 1 # replace NAs with dummy value diff --git a/R/label-percent.R b/R/label-percent.R index 5e482d31..2dbd3d7d 100644 --- a/R/label-percent.R +++ b/R/label-percent.R @@ -15,7 +15,7 @@ #' ) #' demo_continuous(c(0, .01), labels = french_percent) label_percent <- function(accuracy = NULL, scale = 100, prefix = "", - suffix = "%", big.mark = " ", decimal.mark = ".", + suffix = "%", big.mark = NULL, decimal.mark = NULL, trim = TRUE, ...) { number_format( accuracy = accuracy, @@ -45,7 +45,7 @@ percent_format <- label_percent #' @export #' @rdname percent_format percent <- function(x, accuracy = NULL, scale = 100, prefix = "", - suffix = "%", big.mark = " ", decimal.mark = ".", + suffix = "%", big.mark = NULL, decimal.mark = NULL, trim = TRUE, ...) { number( x = x, diff --git a/R/label-pvalue.R b/R/label-pvalue.R index 2564daf0..2b6a328b 100644 --- a/R/label-pvalue.R +++ b/R/label-pvalue.R @@ -4,8 +4,8 @@ #' #' @inherit label_number return params #' @param prefix A character vector of length 3 giving the prefixes to -#' put in front of numbers. The default values are `c("<", "", ">")` -#' if `add_p` is `TRUE` and `c("p<", "p=", "p>")` if `FALSE`. +#' put in front of numbers. The default values are `c("p<", "p=", "p>")` +#' if `add_p` is `TRUE` and `c("<", "", ">")` if `FALSE`. #' @param add_p Add "p=" before the value? #' @export #' @family labels for continuous scales @@ -18,7 +18,7 @@ #' # Or provide your own prefixes #' prefix <- c("p < ", "p = ", "p > ") #' demo_continuous(c(0, 1), labels = label_pvalue(prefix = prefix)) -label_pvalue <- function(accuracy = .001, decimal.mark = ".", prefix = NULL, add_p = FALSE) { +label_pvalue <- function(accuracy = .001, decimal.mark = NULL, prefix = NULL, add_p = FALSE) { force_all(accuracy, decimal.mark, add_p) function(x) { pvalue( @@ -49,9 +49,10 @@ pvalue_format <- label_pvalue #' @export pvalue <- function(x, accuracy = .001, - decimal.mark = ".", + decimal.mark = NULL, prefix = NULL, add_p = FALSE) { + decimal.mark <- decimal.mark %||% getOption("scales.decimal.mark", default = ".") out <- number(x, accuracy, decimal.mark = decimal.mark) below <- number(accuracy, accuracy, decimal.mark = decimal.mark) above <- number(1 - accuracy, accuracy, decimal.mark = decimal.mark) diff --git a/R/label-scientific.R b/R/label-scientific.R index 694073d9..ade16cad 100644 --- a/R/label-scientific.R +++ b/R/label-scientific.R @@ -14,7 +14,7 @@ #' #' demo_log10(c(1, 1e9)) label_scientific <- function(digits = 3, scale = 1, prefix = "", suffix = "", - decimal.mark = ".", trim = TRUE, ...) { + decimal.mark = NULL, trim = TRUE, ...) { force_all(digits, scale, prefix, suffix, decimal.mark, trim, ...) function(x) { scientific( @@ -45,11 +45,12 @@ scientific_format <- label_scientific #' @export #' @rdname scientific_format scientific <- function(x, digits = 3, scale = 1, prefix = "", suffix = "", - decimal.mark = ".", trim = TRUE, ...) { + decimal.mark = NULL, trim = TRUE, ...) { if (length(x) == 0) { return(character()) } x <- signif(x * scale, digits) + decimal.mark <- decimal.mark %||% getOption("scales.decimal.mark", default = ".") ret <- paste0( prefix, format(x, decimal.mark = decimal.mark, trim = trim, scientific = TRUE, ...), diff --git a/R/labels-retired.R b/R/labels-retired.R index be1e2fe6..62026af1 100644 --- a/R/labels-retired.R +++ b/R/labels-retired.R @@ -111,7 +111,7 @@ trans_format <- function(trans, format = scientific_format()) { #' demo_continuous(c(0, 2500), labels = km) unit_format <- function(accuracy = NULL, scale = 1, prefix = "", unit = "m", sep = " ", suffix = paste0(sep, unit), - big.mark = " ", decimal.mark = ".", + big.mark = NULL, decimal.mark = NULL, trim = TRUE, ...) { number_format( accuracy = accuracy, diff --git a/R/pal-.R b/R/pal-.R index 46e34573..8665dfc6 100644 --- a/R/pal-.R +++ b/R/pal-.R @@ -156,6 +156,14 @@ as_discrete_pal.pal_continuous <- function(x, ...) { ) } +#' @export +as_discrete_pal.character <- function(x, ...) { + if (length(x) > 1) { + return(pal_manual(x)) + } + as_discrete_pal(get_palette(x, ...)) +} + ## As continuous palette -------------------------------------------------- #' @rdname new_continuous_palette @@ -197,3 +205,11 @@ as_continuous_pal.pal_discrete <- function(x, ...) { ) ) } + +#' @export +as_continuous_pal.character <- function(x, ...) { + if (length(x) > 1) { + return(colour_ramp(x)) + } + as_continuous_pal(get_palette(x, ...)) +} diff --git a/R/pal-shape.r b/R/pal-shape.r index 7090631e..065e0c0f 100644 --- a/R/pal-shape.r +++ b/R/pal-shape.r @@ -8,7 +8,7 @@ pal_shape <- function(solid = TRUE) { if (n > 6) { cli::cli_warn(c( "The shape palette can deal with a maximum of 6 discrete values because more than 6 becomes difficult to discriminate", - i = "you have requested {n} values. Consider specifying shapes manually if you need that many have them." + i = "you have requested {n} values. Consider specifying shapes manually if you need that many of them." )) } diff --git a/R/palette-registry.R b/R/palette-registry.R new file mode 100644 index 00000000..6ef38ab7 --- /dev/null +++ b/R/palette-registry.R @@ -0,0 +1,157 @@ +.known_palettes <- new_environment(parent = empty_env()) + +#' Known palettes +#' +#' The scales packages keeps track of a set of palettes it considers 'known'. +#' The benefit of a known palette is that it can be called by name in functions +#' as `as_continuous_pal()` or `as_discrete_pal()`. +#' +#' @param name A string giving the palette name. +#' @param palette A [palette][new_continuous_palette], `function` or character +#' vector. +#' @param warn_conflict A boolean which if `TRUE` (default), warns when +#' replacing a known palette. +#' @param ... Additional arguments to pass to palette when it is a function +#' but not a palette class function. +#' +#' @return The `get_palette()` function returns a palette. The `set_palette()` +#' function is called for side effects and returns nothing. +#' @export +#' +#' @examples +#' # Get one of the known palettes +#' get_palette("hue") +#' +#' # Set a new custom palette +#' cols <- c("palegreen", "deepskyblue", "magenta") +#' set_palette("aurora", palette = cols) +#' +#' # Palette is now known +#' "aurora" %in% palette_names() +#' as_continuous_pal("aurora") +#' +#' # Resetting palettes +#' reset_palettes() +get_palette <- function(name, ...) { + + name <- tolower(name) + if (!exists(name, envir = .known_palettes)) { + cli::cli_abort("Unknown palette: {name}") + } + + pal <- env_get(.known_palettes, name) + + # Palette could be factory, in which case we want the product, or + # palette can be a palette function that isn't registered as such, + # in which case we want the colours it gives + if (is_function(pal) && !is_pal(pal)) { + pal <- try_fetch( + pal(...), + error = function(cnd) { + cli::cli_abort("Failed to interpret {name} as palette.", parent = cnd) + } + ) + } + if (is.character(pal)) { + pal <- manual_pal(pal, type = "colour") + } + if (is_pal(pal)) { + return(pal) + } + cli::cli_abort("Failed to interpret {name} as palette.") +} + +#' @export +#' @rdname get_palette +set_palette <- function(name, palette, warn_conflict = TRUE) { + name <- tolower(name) + if (!is_function(palette) && !is_character(palette)) { + cli::cli_abort( + "The {.arg palette} argument must be a {.cls function} or \\ + {.cls character} vector." + ) + } + if (warn_conflict & exists(name, envir = .known_palettes)) { + cli::cli_warn("Overwriting pre-existing {.val {name}} palette.") + } + env_bind(.known_palettes, !!name := palette) + invisible(NULL) +} + +#' @export +#' @rdname get_palette +palette_names <- function() { + names(.known_palettes) +} + +#' @export +#' @rdname get_palette +reset_palettes <- function() { + env_unbind(.known_palettes, palette_names()) + init_palettes() +} + +init_palettes <- function() { + register_hcl_pals() + register_base_pals() + register_viridis_pals() + register_brewer_pals() + register_dichromat_pals() + set_palette("grey", pal_grey, warn_conflict = FALSE) + set_palette("hue", pal_hue, warn_conflict = FALSE) +} + +on_load(init_palettes()) + +register_hcl_pals <- function(n = 31) { + names <- grDevices::hcl.pals() + for (name in names) { + fun <- colour_ramp(grDevices::hcl.colors(n, palette = name)) + set_palette(name, fun, warn_conflict = FALSE) + } + invisible(NULL) +} + +register_base_pals <- function() { + if (getRversion() < "4.0.0") { + return(invisible(NULL)) + } + names <- utils::getFromNamespace("palette.pals", "grDevices")() + palette <- utils::getFromNamespace("palette.colors", "grDevices") + for (name in names) { + fun <- manual_pal(palette(palette = name), type = "colour") + set_palette(name, fun, warn_conflict = FALSE) + } + invisible(NULL) +} + +register_viridis_pals <- function() { + names <- c("magma", "inferno", "plasma", "viridis", + "cividis", "rocket", "mako", "turbo") + for (name in names) { + fun <- pal_viridis(option = name) + set_palette(name, fun, warn_conflict = FALSE) + } + invisible(NULL) +} + +register_brewer_pals <- function() { + names <- rownames(RColorBrewer::brewer.pal.info) + for (name in names) { + fun <- pal_brewer(palette = name) + set_palette(name, fun, warn_conflict = FALSE) + } + invisible(NULL) +} + +register_dichromat_pals <- function() { + if (!is_installed("dichromat")) { + return(invisible(NULL)) + } + names <- names(dichromat::colorschemes) + for (name in names) { + fun <- manual_pal(dichromat::colorschemes[[name]], type = "colour") + set_palette(name, fun, warn_conflict = FALSE) + } + invisible(NULL) +} diff --git a/R/range.R b/R/range.R index e2aa3476..f74ec500 100644 --- a/R/range.R +++ b/R/range.R @@ -18,9 +18,10 @@ DiscreteRange <- R6::R6Class( inherit = Range, list( factor = NULL, - train = function(x, drop = FALSE, na.rm = FALSE) { + train = function(x, drop = FALSE, na.rm = FALSE, call = caller_env()) { self$factor <- self$factor %||% is.factor(x) - self$range <- train_discrete(x, self$range, drop, na.rm, self$factor) + self$range <- train_discrete(x, self$range, drop, na.rm, + self$factor, call = call) }, reset = function() { self$range <- NULL @@ -35,7 +36,9 @@ ContinuousRange <- R6::R6Class( "ContinuousRange", inherit = Range, list( - train = function(x) self$range <- train_continuous(x, self$range), + train = function(x, call = caller_env()) { + self$range <- train_continuous(x, self$range, call = call) + }, reset = function() self$range <- NULL ) ) diff --git a/R/scale-continuous.R b/R/scale-continuous.R index 102b325f..b5095fbe 100644 --- a/R/scale-continuous.R +++ b/R/scale-continuous.R @@ -37,13 +37,18 @@ cscale <- function(x, palette, na.value = NA_real_, trans = transform_identity() #' #' @inheritParams train_discrete #' @export -train_continuous <- function(new, existing = NULL) { +train_continuous <- function(new, existing = NULL, call = caller_env()) { if (is.null(new)) { return(existing) } if (is.factor(new) || !typeof(new) %in% c("integer", "double")) { - cli::cli_abort("Discrete value supplied to a continuous scale") + example <- unique(new) + example <- example[seq_len(pmin(length(example), 5))] + cli::cli_abort(c( + "Discrete value supplied to a continuous scale.", + i = "Example values: {.and {.val {example}}}." + ), call = call) } # Needs casting to numeric because some `new` vectors can misbehave when diff --git a/R/scale-discrete.R b/R/scale-discrete.R index 3e95e13b..8957583a 100644 --- a/R/scale-discrete.R +++ b/R/scale-discrete.R @@ -25,14 +25,20 @@ is.discrete <- function(x) { #' @param drop `TRUE`, will drop factor levels not associated with data #' @param na.rm If `TRUE`, will remove missing values #' @param fct Treat `existing` as if it came from a factor (ie. don't sort the range) +#' @param call A call to display in error messages #' @export -train_discrete <- function(new, existing = NULL, drop = FALSE, na.rm = FALSE, fct = NA) { +train_discrete <- function(new, existing = NULL, drop = FALSE, + na.rm = FALSE, fct = NA, call = caller_env()) { if (is.null(new)) { return(existing) } - if (!is.discrete(new)) { - cli::cli_abort("Continuous value supplied to a discrete scale") + example <- unique(new) + example <- example[seq_len(pmin(length(example), 5))] + cli::cli_abort(c( + "Continuous value supplied to a discrete scale.", + i = "Example values: {.and {.val {example}}}." + ), call = call) } discrete_range(existing, new, drop = drop, na.rm = na.rm, fct = fct) } diff --git a/R/transform-numeric.R b/R/transform-numeric.R index 641b7f53..0b55a1e1 100644 --- a/R/transform-numeric.R +++ b/R/transform-numeric.R @@ -67,16 +67,16 @@ asinh_trans <- transform_asinh #' Box-Cox to also work with negative values. #' #' The Box-Cox power transformation (type 1) requires strictly positive values and -#' takes the following form for `y > 0`: +#' takes the following form for \eqn{\lambda > 0}: #' \deqn{y^{(\lambda)} = \frac{y^\lambda - 1}{\lambda}}{y^(\lambda) = (y^\lambda - 1)/\lambda} -#' When `y = 0`, the natural log transform is used. +#' When \eqn{\lambda = 0}, the natural log transform is used. #' #' The modulus transformation implements a generalisation of the Box-Cox #' transformation that works for data with both positive and negative values. -#' The equation takes the following forms, when `y != 0` : +#' The equation takes the following forms, when \eqn{\lambda \neq 0} : #' \deqn{y^{(\lambda)} = sign(y) * \frac{(|y| + 1)^\lambda - 1}{\lambda}}{ #' y^(\lambda) = sign(y)*((|y|+1)^\lambda - 1)/\lambda} -#' and when `y = 0`: \deqn{y^{(\lambda)} = sign(y) * \ln(|y| + 1)}{ +#' and when \eqn{\lambda = 0}: \deqn{y^{(\lambda)} = sign(y) * \ln(|y| + 1)}{ #' y^(\lambda) = sign(y) * ln(|y| + 1)} #' #' @param p Transformation exponent, \eqn{\lambda}. @@ -255,7 +255,8 @@ transform_exp <- function(base = exp(1)) { function(x) base^x, function(x) log(x, base = base), d_transform = function(x) base^x * log(base), - d_inverse = function(x) 1 / x / log(base) + d_inverse = function(x) 1 / x / log(base), + breaks = breaks_exp(), ) } diff --git a/R/utils.R b/R/utils.R index fc80a5a4..25cfa505 100644 --- a/R/utils.R +++ b/R/utils.R @@ -73,11 +73,7 @@ recycle_common <- function(..., size = NULL, call = caller_env()) { n <- setdiff(n, 1L) ns <- length(n) - if (ns == 0) { # All have length 1 - if (is.null(size)) { - return(xs) - } - } else if (ns == 1) { + if (ns == 1) { if (is.null(size)) { size <- n } else if (n != size) { @@ -100,3 +96,7 @@ recycle_common <- function(..., size = NULL, call = caller_env()) { x[to_recycle] <- lapply(x[to_recycle], rep_len, length.out = size) x } + +.onLoad <- function(lib, pkg) { + run_on_load() +} diff --git a/_pkgdown.yml b/_pkgdown.yml index 3e26d4b2..12c48200 100644 --- a/_pkgdown.yml +++ b/_pkgdown.yml @@ -19,6 +19,7 @@ reference: contents: - starts_with("label_") - matches("format") + - number_options - title: Axis breaks desc: > @@ -27,6 +28,7 @@ reference: contents: - starts_with("breaks_") - minor_breaks_width + - minor_breaks_log - title: "Bounds: ranges & rescaling" desc: > @@ -68,6 +70,7 @@ reference: - contains("col") - muted - alpha + - get_palette - title: Non-colour palette functions desc: > diff --git a/man/breaks_exp.Rd b/man/breaks_exp.Rd new file mode 100644 index 00000000..536b4412 --- /dev/null +++ b/man/breaks_exp.Rd @@ -0,0 +1,25 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/breaks.R +\name{breaks_exp} +\alias{breaks_exp} +\title{Breaks for exponentially transformed data} +\usage{ +breaks_exp(n = 5, ...) +} +\arguments{ +\item{n}{Desired number of breaks. You may get slightly more or fewer +breaks that requested.} + +\item{...}{other arguments passed on to \code{\link[labeling:extended]{labeling::extended()}}} +} +\description{ +This breaks function typically labels zero and the last \code{n - 1} integers of a +range if that range is large enough (currently: 3). For smaller ranges, it +uses \code{\link[=breaks_extended]{breaks_extended()}}. +} +\examples{ +# Small range +demo_continuous(c(100, 102), transform = "exp", breaks = breaks_exp()) +# Large range +demo_continuous(c(0, 100), transform = "exp", breaks = breaks_exp(n = 4)) +} diff --git a/man/comma.Rd b/man/comma.Rd index 38f9b7f9..bb03854a 100644 --- a/man/comma.Rd +++ b/man/comma.Rd @@ -24,10 +24,10 @@ number_format( scale = 1, prefix = "", suffix = "", - big.mark = " ", - decimal.mark = ".", - style_positive = c("none", "plus", "space"), - style_negative = c("hyphen", "minus", "parens"), + big.mark = NULL, + decimal.mark = NULL, + style_positive = NULL, + style_negative = NULL, scale_cut = NULL, trim = TRUE, ... @@ -65,10 +65,13 @@ processed so that \code{prefix = "$"} will yield (e.g.) \verb{-$1} and \verb{($1 \item{suffix}{Additional text to display after the number.} -\item{big.mark}{Character used between every 3 digits to separate thousands.} +\item{big.mark}{Character used between every 3 digits to separate thousands. +The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} \item{decimal.mark}{The character to be used to indicate the numeric -decimal point.} +decimal point. The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} \item{trim}{Logical, if \code{FALSE}, values are right-justified to a common width (see \code{\link[base:format]{base::format()}}).} @@ -85,7 +88,10 @@ width (see \code{\link[base:format]{base::format()}}).} as wide as a number or \code{+}. Compared to \code{"none"}, adding a figure space can ensure numbers remain properly aligned when they are left- or right-justified. -}} +} + +The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} \item{style_negative}{A string that determines the style of negative numbers: \itemize{ @@ -94,7 +100,10 @@ right-justified. nicety that ensures \code{-} aligns with the horizontal bar of the the horizontal bar of \code{+}. \item \code{"parens"}, wrapped in parentheses, e.g. \code{(1)}. -}} +} + +The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} \item{scale_cut}{Named numeric vector that allows you to rescale large (or small) numbers and add a prefix. Built-in helpers include: diff --git a/man/date_format.Rd b/man/date_format.Rd index 8d3ab9e3..6de951f4 100644 --- a/man/date_format.Rd +++ b/man/date_format.Rd @@ -10,10 +10,10 @@ date_format(format = "\%Y-\%m-\%d", tz = "UTC", locale = NULL) time_format(format = "\%H:\%M:\%S", tz = "UTC", locale = NULL) } \arguments{ -\item{format}{For \code{date_format()} and \code{time_format()} a date/time format +\item{format}{For \code{label_date()} and \code{label_time()} a date/time format string using standard POSIX specification. See \code{\link[=strptime]{strptime()}} for details. -For \code{date_short()} a character vector of length 4 giving the format +For \code{label_date_short()} a character vector of length 4 giving the format components to use for year, month, day, and hour respectively.} \item{tz}{a time zone name, see \code{\link[=timezones]{timezones()}}. Defaults diff --git a/man/dollar_format.Rd b/man/dollar_format.Rd index fc65b2df..0791f2c6 100644 --- a/man/dollar_format.Rd +++ b/man/dollar_format.Rd @@ -23,10 +23,10 @@ dollar( x, accuracy = NULL, scale = 1, - prefix = "$", - suffix = "", - big.mark = ",", - decimal.mark = ".", + prefix = NULL, + suffix = NULL, + big.mark = NULL, + decimal.mark = NULL, trim = TRUE, largest_with_cents = 1e+05, negative_parens = deprecated(), @@ -55,10 +55,13 @@ large.} \item{prefix, suffix}{Symbols to display before and after value.} -\item{big.mark}{Character used between every 3 digits to separate thousands.} +\item{big.mark}{Character used between every 3 digits to separate thousands. +The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} \item{decimal.mark}{The character to be used to indicate the numeric -decimal point.} +decimal point. The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} \item{trim}{Logical, if \code{FALSE}, values are right-justified to a common width (see \code{\link[base:format]{base::format()}}).} diff --git a/man/get_palette.Rd b/man/get_palette.Rd new file mode 100644 index 00000000..e48def8e --- /dev/null +++ b/man/get_palette.Rd @@ -0,0 +1,53 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/palette-registry.R +\name{get_palette} +\alias{get_palette} +\alias{set_palette} +\alias{palette_names} +\alias{reset_palettes} +\title{Known palettes} +\usage{ +get_palette(name, ...) + +set_palette(name, palette, warn_conflict = TRUE) + +palette_names() + +reset_palettes() +} +\arguments{ +\item{name}{A string giving the palette name.} + +\item{...}{Additional arguments to pass to palette when it is a function +but not a palette class function.} + +\item{palette}{A \link[=new_continuous_palette]{palette}, \code{function} or character +vector.} + +\item{warn_conflict}{A boolean which if \code{TRUE} (default), warns when +replacing a known palette.} +} +\value{ +The \code{get_palette()} function returns a palette. The \code{set_palette()} +function is called for side effects and returns nothing. +} +\description{ +The scales packages keeps track of a set of palettes it considers 'known'. +The benefit of a known palette is that it can be called by name in functions +as \code{as_continuous_pal()} or \code{as_discrete_pal()}. +} +\examples{ +# Get one of the known palettes +get_palette("hue") + +# Set a new custom palette +cols <- c("palegreen", "deepskyblue", "magenta") +set_palette("aurora", palette = cols) + +# Palette is now known +"aurora" \%in\% palette_names() +as_continuous_pal("aurora") + +# Resetting palettes +reset_palettes() +} diff --git a/man/label_bytes.Rd b/man/label_bytes.Rd index 02054433..266649bc 100644 --- a/man/label_bytes.Rd +++ b/man/label_bytes.Rd @@ -35,9 +35,12 @@ large.} applied to absolute value before \code{style_positive} and \code{style_negative} are processed so that \code{prefix = "$"} will yield (e.g.) \verb{-$1} and \verb{($1)}.} \item{\code{suffix}}{Additional text to display after the number.} - \item{\code{big.mark}}{Character used between every 3 digits to separate thousands.} + \item{\code{big.mark}}{Character used between every 3 digits to separate thousands. +The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} \item{\code{decimal.mark}}{The character to be used to indicate the numeric -decimal point.} +decimal point. The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} \item{\code{style_positive}}{A string that determines the style of positive numbers: \itemize{ \item \code{"none"} (the default): no change, e.g. \code{1}. @@ -46,7 +49,10 @@ decimal point.} as wide as a number or \code{+}. Compared to \code{"none"}, adding a figure space can ensure numbers remain properly aligned when they are left- or right-justified. -}} +} + +The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} \item{\code{style_negative}}{A string that determines the style of negative numbers: \itemize{ \item \code{"hyphen"} (the default): preceded by a standard hypen \code{-}, e.g. \code{-1}. @@ -54,7 +60,10 @@ right-justified. nicety that ensures \code{-} aligns with the horizontal bar of the the horizontal bar of \code{+}. \item \code{"parens"}, wrapped in parentheses, e.g. \code{(1)}. -}} +} + +The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} \item{\code{scale_cut}}{Named numeric vector that allows you to rescale large (or small) numbers and add a prefix. Built-in helpers include: \itemize{ diff --git a/man/label_currency.Rd b/man/label_currency.Rd index a29feb17..c0118d92 100644 --- a/man/label_currency.Rd +++ b/man/label_currency.Rd @@ -7,10 +7,10 @@ label_currency( accuracy = NULL, scale = 1, - prefix = "$", - suffix = "", - big.mark = ",", - decimal.mark = ".", + prefix = NULL, + suffix = NULL, + big.mark = NULL, + decimal.mark = NULL, trim = TRUE, largest_with_fractional = 1e+05, ... @@ -29,10 +29,13 @@ large.} \item{prefix, suffix}{Symbols to display before and after value.} -\item{big.mark}{Character used between every 3 digits to separate thousands.} +\item{big.mark}{Character used between every 3 digits to separate thousands. +The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} \item{decimal.mark}{The character to be used to indicate the numeric -decimal point.} +decimal point. The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} \item{trim}{Logical, if \code{FALSE}, values are right-justified to a common width (see \code{\link[base:format]{base::format()}}).} @@ -48,7 +51,10 @@ width (see \code{\link[base:format]{base::format()}}).} as wide as a number or \code{+}. Compared to \code{"none"}, adding a figure space can ensure numbers remain properly aligned when they are left- or right-justified. -}} +} + +The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} \item{\code{style_negative}}{A string that determines the style of negative numbers: \itemize{ \item \code{"hyphen"} (the default): preceded by a standard hypen \code{-}, e.g. \code{-1}. @@ -56,7 +62,10 @@ right-justified. nicety that ensures \code{-} aligns with the horizontal bar of the the horizontal bar of \code{+}. \item \code{"parens"}, wrapped in parentheses, e.g. \code{(1)}. -}} +} + +The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} \item{\code{scale_cut}}{Named numeric vector that allows you to rescale large (or small) numbers and add a prefix. Built-in helpers include: \itemize{ diff --git a/man/label_date.Rd b/man/label_date.Rd index e713f019..928f8cd5 100644 --- a/man/label_date.Rd +++ b/man/label_date.Rd @@ -24,10 +24,10 @@ label_timespan( ) } \arguments{ -\item{format}{For \code{date_format()} and \code{time_format()} a date/time format +\item{format}{For \code{label_date()} and \code{label_time()} a date/time format string using standard POSIX specification. See \code{\link[=strptime]{strptime()}} for details. -For \code{date_short()} a character vector of length 4 giving the format +For \code{label_date_short()} a character vector of length 4 giving the format components to use for year, month, day, and hour respectively.} \item{tz}{a time zone name, see \code{\link[=timezones]{timezones()}}. Defaults @@ -63,9 +63,12 @@ large.} applied to absolute value before \code{style_positive} and \code{style_negative} are processed so that \code{prefix = "$"} will yield (e.g.) \verb{-$1} and \verb{($1)}.} \item{\code{suffix}}{Additional text to display after the number.} - \item{\code{big.mark}}{Character used between every 3 digits to separate thousands.} + \item{\code{big.mark}}{Character used between every 3 digits to separate thousands. +The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} \item{\code{decimal.mark}}{The character to be used to indicate the numeric -decimal point.} +decimal point. The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} \item{\code{style_positive}}{A string that determines the style of positive numbers: \itemize{ \item \code{"none"} (the default): no change, e.g. \code{1}. @@ -74,7 +77,10 @@ decimal point.} as wide as a number or \code{+}. Compared to \code{"none"}, adding a figure space can ensure numbers remain properly aligned when they are left- or right-justified. -}} +} + +The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} \item{\code{style_negative}}{A string that determines the style of negative numbers: \itemize{ \item \code{"hyphen"} (the default): preceded by a standard hypen \code{-}, e.g. \code{-1}. @@ -82,7 +88,10 @@ right-justified. nicety that ensures \code{-} aligns with the horizontal bar of the the horizontal bar of \code{+}. \item \code{"parens"}, wrapped in parentheses, e.g. \code{(1)}. -}} +} + +The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} \item{\code{trim}}{Logical, if \code{FALSE}, values are right-justified to a common width (see \code{\link[base:format]{base::format()}}).} }} @@ -116,9 +125,9 @@ date_range <- function(start, days) { two_months <- date_range("2020-05-01", 60) demo_datetime(two_months) -demo_datetime(two_months, labels = date_format("\%m/\%d")) -demo_datetime(two_months, labels = date_format("\%e \%b", locale = "fr")) -demo_datetime(two_months, labels = date_format("\%e \%B", locale = "es")) +demo_datetime(two_months, labels = label_date("\%m/\%d")) +demo_datetime(two_months, labels = label_date("\%e \%b", locale = "fr")) +demo_datetime(two_months, labels = label_date("\%e \%B", locale = "es")) # ggplot2 provides a short-hand: demo_datetime(two_months, date_labels = "\%m/\%d") diff --git a/man/label_log.Rd b/man/label_log.Rd index daf576fb..d0dee6ab 100644 --- a/man/label_log.Rd +++ b/man/label_log.Rd @@ -2,15 +2,26 @@ % Please edit documentation in R/label-log.R \name{label_log} \alias{label_log} +\alias{format_log} \title{Label numbers in log format (10^3, 10^6, etc)} \usage{ -label_log(base = 10, digits = 3) +label_log(base = 10, digits = 3, signed = NULL) + +format_log(x, base = 10, signed = NULL, ...) } \arguments{ \item{base}{Base of logarithm to use} \item{digits}{Number of significant digits to show for the exponent. Argument is passed on to \code{\link[base:format]{base::format()}}.} + +\item{signed}{Should a \code{+} or \code{-} be displayed as a prefix? The +default, \code{NULL}, displays signs if there are zeroes or negative numbers +present.} + +\item{x}{A numeric vector to format} + +\item{...}{Passed on to \code{format()}.} } \value{ All \code{label_()} functions return a "labelling" function, i.e. a function that @@ -23,11 +34,14 @@ they work similarly for all scales, including those that generate legends rather than axes. } \description{ -\code{label_log()} displays numbers as base^exponent, using superscript formatting. +\code{label_log()} and \code{format_log()} display numbers as base^exponent, using +superscript formatting. \code{label_log()} returns expressions suitable for +labelling in scales, whereas \code{format_log()} returns deparsed text. } \examples{ demo_log10(c(1, 1e5), labels = label_log()) demo_log10(c(1, 1e5), breaks = breaks_log(base = 2), labels = label_log(base = 2)) +format_log(c(0.1, 1, 10)) } \seealso{ \code{\link[=breaks_log]{breaks_log()}} for the related breaks algorithm. diff --git a/man/label_number.Rd b/man/label_number.Rd index cb91f2a9..322f20db 100644 --- a/man/label_number.Rd +++ b/man/label_number.Rd @@ -10,10 +10,10 @@ label_number( scale = 1, prefix = "", suffix = "", - big.mark = " ", - decimal.mark = ".", - style_positive = c("none", "plus", "space"), - style_negative = c("hyphen", "minus", "parens"), + big.mark = NULL, + decimal.mark = NULL, + style_positive = NULL, + style_negative = NULL, scale_cut = NULL, trim = TRUE, ... @@ -49,10 +49,13 @@ processed so that \code{prefix = "$"} will yield (e.g.) \verb{-$1} and \verb{($1 \item{suffix}{Additional text to display after the number.} -\item{big.mark}{Character used between every 3 digits to separate thousands.} +\item{big.mark}{Character used between every 3 digits to separate thousands. +The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} \item{decimal.mark}{The character to be used to indicate the numeric -decimal point.} +decimal point. The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} \item{style_positive}{A string that determines the style of positive numbers: \itemize{ @@ -62,7 +65,10 @@ decimal point.} as wide as a number or \code{+}. Compared to \code{"none"}, adding a figure space can ensure numbers remain properly aligned when they are left- or right-justified. -}} +} + +The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} \item{style_negative}{A string that determines the style of negative numbers: \itemize{ @@ -71,7 +77,10 @@ right-justified. nicety that ensures \code{-} aligns with the horizontal bar of the the horizontal bar of \code{+}. \item \code{"parens"}, wrapped in parentheses, e.g. \code{(1)}. -}} +} + +The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} \item{scale_cut}{Named numeric vector that allows you to rescale large (or small) numbers and add a prefix. Built-in helpers include: diff --git a/man/label_number_si.Rd b/man/label_number_si.Rd index fd8c8ece..c3a9eeaf 100644 --- a/man/label_number_si.Rd +++ b/man/label_number_si.Rd @@ -28,9 +28,12 @@ prefix.} \item{\code{prefix}}{Additional text to display before the number. The suffix is applied to absolute value before \code{style_positive} and \code{style_negative} are processed so that \code{prefix = "$"} will yield (e.g.) \verb{-$1} and \verb{($1)}.} - \item{\code{big.mark}}{Character used between every 3 digits to separate thousands.} + \item{\code{big.mark}}{Character used between every 3 digits to separate thousands. +The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} \item{\code{decimal.mark}}{The character to be used to indicate the numeric -decimal point.} +decimal point. The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} \item{\code{style_positive}}{A string that determines the style of positive numbers: \itemize{ \item \code{"none"} (the default): no change, e.g. \code{1}. @@ -39,7 +42,10 @@ decimal point.} as wide as a number or \code{+}. Compared to \code{"none"}, adding a figure space can ensure numbers remain properly aligned when they are left- or right-justified. -}} +} + +The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} \item{\code{style_negative}}{A string that determines the style of negative numbers: \itemize{ \item \code{"hyphen"} (the default): preceded by a standard hypen \code{-}, e.g. \code{-1}. @@ -47,7 +53,10 @@ right-justified. nicety that ensures \code{-} aligns with the horizontal bar of the the horizontal bar of \code{+}. \item \code{"parens"}, wrapped in parentheses, e.g. \code{(1)}. -}} +} + +The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} \item{\code{scale_cut}}{Named numeric vector that allows you to rescale large (or small) numbers and add a prefix. Built-in helpers include: \itemize{ diff --git a/man/label_ordinal.Rd b/man/label_ordinal.Rd index 471c0ebd..77da0587 100644 --- a/man/label_ordinal.Rd +++ b/man/label_ordinal.Rd @@ -7,13 +7,7 @@ \alias{ordinal_spanish} \title{Label ordinal numbers (1st, 2nd, 3rd, etc)} \usage{ -label_ordinal( - prefix = "", - suffix = "", - big.mark = " ", - rules = ordinal_english(), - ... -) +label_ordinal(prefix = "", suffix = "", big.mark = NULL, rules = NULL, ...) ordinal_english() @@ -24,7 +18,9 @@ ordinal_spanish() \arguments{ \item{prefix, suffix}{Symbols to display before and after value.} -\item{big.mark}{Character used between every 3 digits to separate thousands.} +\item{big.mark}{Character used between every 3 digits to separate thousands. +The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} \item{rules}{Named list of regular expressions, matched in order. Name gives suffix, and value specifies which numbers to match.} @@ -42,7 +38,8 @@ Applied to rescaled data.} formatting. This is useful if the underlying data is very small or very large.} \item{\code{decimal.mark}}{The character to be used to indicate the numeric -decimal point.} +decimal point. The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} \item{\code{style_positive}}{A string that determines the style of positive numbers: \itemize{ \item \code{"none"} (the default): no change, e.g. \code{1}. @@ -51,7 +48,10 @@ decimal point.} as wide as a number or \code{+}. Compared to \code{"none"}, adding a figure space can ensure numbers remain properly aligned when they are left- or right-justified. -}} +} + +The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} \item{\code{style_negative}}{A string that determines the style of negative numbers: \itemize{ \item \code{"hyphen"} (the default): preceded by a standard hypen \code{-}, e.g. \code{-1}. @@ -59,7 +59,10 @@ right-justified. nicety that ensures \code{-} aligns with the horizontal bar of the the horizontal bar of \code{+}. \item \code{"parens"}, wrapped in parentheses, e.g. \code{(1)}. -}} +} + +The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} \item{\code{scale_cut}}{Named numeric vector that allows you to rescale large (or small) numbers and add a prefix. Built-in helpers include: \itemize{ diff --git a/man/label_percent.Rd b/man/label_percent.Rd index a705538c..4fe707a8 100644 --- a/man/label_percent.Rd +++ b/man/label_percent.Rd @@ -9,8 +9,8 @@ label_percent( scale = 100, prefix = "", suffix = "\%", - big.mark = " ", - decimal.mark = ".", + big.mark = NULL, + decimal.mark = NULL, trim = TRUE, ... ) @@ -33,10 +33,13 @@ processed so that \code{prefix = "$"} will yield (e.g.) \verb{-$1} and \verb{($1 \item{suffix}{Additional text to display after the number.} -\item{big.mark}{Character used between every 3 digits to separate thousands.} +\item{big.mark}{Character used between every 3 digits to separate thousands. +The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} \item{decimal.mark}{The character to be used to indicate the numeric -decimal point.} +decimal point. The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} \item{trim}{Logical, if \code{FALSE}, values are right-justified to a common width (see \code{\link[base:format]{base::format()}}).} @@ -52,7 +55,10 @@ width (see \code{\link[base:format]{base::format()}}).} as wide as a number or \code{+}. Compared to \code{"none"}, adding a figure space can ensure numbers remain properly aligned when they are left- or right-justified. -}} +} + +The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} \item{\code{style_negative}}{A string that determines the style of negative numbers: \itemize{ \item \code{"hyphen"} (the default): preceded by a standard hypen \code{-}, e.g. \code{-1}. @@ -60,7 +66,10 @@ right-justified. nicety that ensures \code{-} aligns with the horizontal bar of the the horizontal bar of \code{+}. \item \code{"parens"}, wrapped in parentheses, e.g. \code{(1)}. -}} +} + +The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} \item{\code{scale_cut}}{Named numeric vector that allows you to rescale large (or small) numbers and add a prefix. Built-in helpers include: \itemize{ diff --git a/man/label_pvalue.Rd b/man/label_pvalue.Rd index ae9e2b83..f38d49f6 100644 --- a/man/label_pvalue.Rd +++ b/man/label_pvalue.Rd @@ -6,7 +6,7 @@ \usage{ label_pvalue( accuracy = 0.001, - decimal.mark = ".", + decimal.mark = NULL, prefix = NULL, add_p = FALSE ) @@ -20,11 +20,12 @@ difference between adjacent values. Applied to rescaled data.} \item{decimal.mark}{The character to be used to indicate the numeric -decimal point.} +decimal point. The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} \item{prefix}{A character vector of length 3 giving the prefixes to -put in front of numbers. The default values are \code{c("<", "", ">")} -if \code{add_p} is \code{TRUE} and \code{c("p<", "p=", "p>")} if \code{FALSE}.} +put in front of numbers. The default values are \code{c("p<", "p=", "p>")} +if \code{add_p} is \code{TRUE} and \code{c("<", "", ">")} if \code{FALSE}.} \item{add_p}{Add "p=" before the value?} } diff --git a/man/label_scientific.Rd b/man/label_scientific.Rd index 97db3367..b28a8608 100644 --- a/man/label_scientific.Rd +++ b/man/label_scientific.Rd @@ -9,7 +9,7 @@ label_scientific( scale = 1, prefix = "", suffix = "", - decimal.mark = ".", + decimal.mark = NULL, trim = TRUE, ... ) @@ -24,7 +24,8 @@ large.} \item{prefix, suffix}{Symbols to display before and after value.} \item{decimal.mark}{The character to be used to indicate the numeric -decimal point.} +decimal point. The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} \item{trim}{Logical, if \code{FALSE}, values are right-justified to a common width (see \code{\link[base:format]{base::format()}}).} diff --git a/man/minor_breaks_log.Rd b/man/minor_breaks_log.Rd new file mode 100644 index 00000000..1efb1da2 --- /dev/null +++ b/man/minor_breaks_log.Rd @@ -0,0 +1,34 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/breaks-log.R +\name{minor_breaks_log} +\alias{minor_breaks_log} +\title{Minor breaks for log-10 axes} +\usage{ +minor_breaks_log(detail = NULL, smallest = NULL) +} +\arguments{ +\item{detail}{Any of \code{1}, \code{5} and \code{10} to mark multiples of +powers, multiples of 5 of powers or just powers respectively.} + +\item{smallest}{Smallest absolute value to mark when the range includes +negative numbers.} +} +\value{ +A function to generate minor ticks. +} +\description{ +This break function is designed to mark every power, multiples of 5 and/or 1 +of that power for base 10. +} +\examples{ +# Standard usage with log10 scale +demo_log10(c(1, 1e10), minor_breaks = minor_breaks_log()) +# Increasing detail over many powers +demo_log10(c(1, 1e10), minor_breaks = minor_breaks_log(detail = 1)) +# Adjusting until where to draw minor breaks +demo_continuous( + c(-1000, 1000), + transform = asinh_trans(), + minor_breaks = minor_breaks_log(smallest = 1) +) +} diff --git a/man/number.Rd b/man/number.Rd index 2ac5a42c..57696e96 100644 --- a/man/number.Rd +++ b/man/number.Rd @@ -14,10 +14,10 @@ number( scale = 1, prefix = "", suffix = "", - big.mark = " ", - decimal.mark = ".", - style_positive = c("none", "plus", "space"), - style_negative = c("hyphen", "minus", "parens"), + big.mark = NULL, + decimal.mark = NULL, + style_positive = NULL, + style_negative = NULL, scale_cut = NULL, trim = TRUE, ... @@ -49,10 +49,13 @@ processed so that \code{prefix = "$"} will yield (e.g.) \verb{-$1} and \verb{($1 \item{suffix}{Additional text to display after the number.} -\item{big.mark}{Character used between every 3 digits to separate thousands.} +\item{big.mark}{Character used between every 3 digits to separate thousands. +The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} \item{decimal.mark}{The character to be used to indicate the numeric -decimal point.} +decimal point. The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} \item{style_positive}{A string that determines the style of positive numbers: \itemize{ @@ -62,7 +65,10 @@ decimal point.} as wide as a number or \code{+}. Compared to \code{"none"}, adding a figure space can ensure numbers remain properly aligned when they are left- or right-justified. -}} +} + +The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} \item{style_negative}{A string that determines the style of negative numbers: \itemize{ @@ -71,7 +77,10 @@ right-justified. nicety that ensures \code{-} aligns with the horizontal bar of the the horizontal bar of \code{+}. \item \code{"parens"}, wrapped in parentheses, e.g. \code{(1)}. -}} +} + +The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} \item{scale_cut}{Named numeric vector that allows you to rescale large (or small) numbers and add a prefix. Built-in helpers include: diff --git a/man/number_options.Rd b/man/number_options.Rd new file mode 100644 index 00000000..d9c81aa5 --- /dev/null +++ b/man/number_options.Rd @@ -0,0 +1,79 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/label-number.R +\name{number_options} +\alias{number_options} +\title{Number options} +\usage{ +number_options( + decimal.mark = ".", + big.mark = " ", + style_positive = c("none", "plus", "space"), + style_negative = c("hyphen", "minus", "parens"), + currency.prefix = "$", + currency.suffix = "", + currency.decimal.mark = decimal.mark, + currency.big.mark = setdiff(c(".", ","), currency.decimal.mark)[1], + ordinal.rules = ordinal_english() +) +} +\arguments{ +\item{decimal.mark}{The character to be used to indicate the numeric +decimal point. The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} + +\item{big.mark}{Character used between every 3 digits to separate thousands. +The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} + +\item{style_positive}{A string that determines the style of positive numbers: +\itemize{ +\item \code{"none"} (the default): no change, e.g. \code{1}. +\item \code{"plus"}: preceded by \code{+}, e.g. \code{+1}. +\item \code{"space"}: preceded by a Unicode "figure space", i.e., a space equally +as wide as a number or \code{+}. Compared to \code{"none"}, adding a figure space +can ensure numbers remain properly aligned when they are left- or +right-justified. +} + +The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} + +\item{style_negative}{A string that determines the style of negative numbers: +\itemize{ +\item \code{"hyphen"} (the default): preceded by a standard hypen \code{-}, e.g. \code{-1}. +\item \code{"minus"}, uses a proper Unicode minus symbol. This is a typographical +nicety that ensures \code{-} aligns with the horizontal bar of the +the horizontal bar of \code{+}. +\item \code{"parens"}, wrapped in parentheses, e.g. \code{(1)}. +} + +The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} + +\item{currency.prefix, currency.suffix, currency.decimal.mark, currency.big.mark}{Settings for \code{\link[=label_currency]{label_currency()}} passed on without the \code{currency.}-prefix.} + +\item{ordinal.rules}{Setting for \code{\link[=label_ordinal]{label_ordinal()}} passed on without the +\code{ordinal.}-prefix.} +} +\value{ +The old options invisibly +} +\description{ +Control the settings for formatting numbers globally. +} +\examples{ +# Default number formatting +x <- c(0.1, 1, 1000) +label_number()(x) + +# Now again with new options set +number_options(style_positive = "plus", decimal.mark = ",") +label_number()(x) + +# The options are the argument names with a 'scales.'-prefix +options("scales.style_positive") + +# Resetting the options to their defaults +number_options() +label_number()(x) +} diff --git a/man/ordinal_format.Rd b/man/ordinal_format.Rd index c2a692a3..1de83ed9 100644 --- a/man/ordinal_format.Rd +++ b/man/ordinal_format.Rd @@ -5,27 +5,16 @@ \alias{ordinal} \title{Superseded interface to \code{label_ordinal()}} \usage{ -ordinal_format( - prefix = "", - suffix = "", - big.mark = " ", - rules = ordinal_english(), - ... -) +ordinal_format(prefix = "", suffix = "", big.mark = NULL, rules = NULL, ...) -ordinal( - x, - prefix = "", - suffix = "", - big.mark = " ", - rules = ordinal_english(), - ... -) +ordinal(x, prefix = "", suffix = "", big.mark = " ", rules = NULL, ...) } \arguments{ \item{prefix, suffix}{Symbols to display before and after value.} -\item{big.mark}{Character used between every 3 digits to separate thousands.} +\item{big.mark}{Character used between every 3 digits to separate thousands. +The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} \item{rules}{Named list of regular expressions, matched in order. Name gives suffix, and value specifies which numbers to match.} diff --git a/man/percent_format.Rd b/man/percent_format.Rd index aad6ad30..26120995 100644 --- a/man/percent_format.Rd +++ b/man/percent_format.Rd @@ -10,8 +10,8 @@ percent_format( scale = 100, prefix = "", suffix = "\%", - big.mark = " ", - decimal.mark = ".", + big.mark = NULL, + decimal.mark = NULL, trim = TRUE, ... ) @@ -22,8 +22,8 @@ percent( scale = 100, prefix = "", suffix = "\%", - big.mark = " ", - decimal.mark = ".", + big.mark = NULL, + decimal.mark = NULL, trim = TRUE, ... ) @@ -46,10 +46,13 @@ processed so that \code{prefix = "$"} will yield (e.g.) \verb{-$1} and \verb{($1 \item{suffix}{Additional text to display after the number.} -\item{big.mark}{Character used between every 3 digits to separate thousands.} +\item{big.mark}{Character used between every 3 digits to separate thousands. +The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} \item{decimal.mark}{The character to be used to indicate the numeric -decimal point.} +decimal point. The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} \item{trim}{Logical, if \code{FALSE}, values are right-justified to a common width (see \code{\link[base:format]{base::format()}}).} diff --git a/man/pvalue_format.Rd b/man/pvalue_format.Rd index 71e4436a..a6be62a3 100644 --- a/man/pvalue_format.Rd +++ b/man/pvalue_format.Rd @@ -7,12 +7,12 @@ \usage{ pvalue_format( accuracy = 0.001, - decimal.mark = ".", + decimal.mark = NULL, prefix = NULL, add_p = FALSE ) -pvalue(x, accuracy = 0.001, decimal.mark = ".", prefix = NULL, add_p = FALSE) +pvalue(x, accuracy = 0.001, decimal.mark = NULL, prefix = NULL, add_p = FALSE) } \arguments{ \item{accuracy}{A number to round to. Use (e.g.) \code{0.01} to show 2 decimal @@ -23,11 +23,12 @@ difference between adjacent values. Applied to rescaled data.} \item{decimal.mark}{The character to be used to indicate the numeric -decimal point.} +decimal point. The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} \item{prefix}{A character vector of length 3 giving the prefixes to -put in front of numbers. The default values are \code{c("<", "", ">")} -if \code{add_p} is \code{TRUE} and \code{c("p<", "p=", "p>")} if \code{FALSE}.} +put in front of numbers. The default values are \code{c("p<", "p=", "p>")} +if \code{add_p} is \code{TRUE} and \code{c("<", "", ">")} if \code{FALSE}.} \item{add_p}{Add "p=" before the value?} } diff --git a/man/scientific_format.Rd b/man/scientific_format.Rd index dfa483d9..e0b2e715 100644 --- a/man/scientific_format.Rd +++ b/man/scientific_format.Rd @@ -10,7 +10,7 @@ scientific_format( scale = 1, prefix = "", suffix = "", - decimal.mark = ".", + decimal.mark = NULL, trim = TRUE, ... ) @@ -21,7 +21,7 @@ scientific( scale = 1, prefix = "", suffix = "", - decimal.mark = ".", + decimal.mark = NULL, trim = TRUE, ... ) @@ -36,7 +36,8 @@ large.} \item{prefix, suffix}{Symbols to display before and after value.} \item{decimal.mark}{The character to be used to indicate the numeric -decimal point.} +decimal point. The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} \item{trim}{Logical, if \code{FALSE}, values are right-justified to a common width (see \code{\link[base:format]{base::format()}}).} diff --git a/man/train_continuous.Rd b/man/train_continuous.Rd index ece41995..16d62955 100644 --- a/man/train_continuous.Rd +++ b/man/train_continuous.Rd @@ -4,12 +4,14 @@ \alias{train_continuous} \title{Train (update) a continuous scale} \usage{ -train_continuous(new, existing = NULL) +train_continuous(new, existing = NULL, call = caller_env()) } \arguments{ \item{new}{New data to add to scale} \item{existing}{Optional existing scale to update} + +\item{call}{A call to display in error messages} } \description{ Strips attributes and always returns a numeric vector diff --git a/man/train_discrete.Rd b/man/train_discrete.Rd index 9e717429..cbeb1ef4 100644 --- a/man/train_discrete.Rd +++ b/man/train_discrete.Rd @@ -4,7 +4,14 @@ \alias{train_discrete} \title{Train (update) a discrete scale} \usage{ -train_discrete(new, existing = NULL, drop = FALSE, na.rm = FALSE, fct = NA) +train_discrete( + new, + existing = NULL, + drop = FALSE, + na.rm = FALSE, + fct = NA, + call = caller_env() +) } \arguments{ \item{new}{New data to add to scale} @@ -16,6 +23,8 @@ train_discrete(new, existing = NULL, drop = FALSE, na.rm = FALSE, fct = NA) \item{na.rm}{If \code{TRUE}, will remove missing values} \item{fct}{Treat \code{existing} as if it came from a factor (ie. don't sort the range)} + +\item{call}{A call to display in error messages} } \description{ Train (update) a discrete scale diff --git a/man/transform_boxcox.Rd b/man/transform_boxcox.Rd index cc6d8ea5..00d9ca28 100644 --- a/man/transform_boxcox.Rd +++ b/man/transform_boxcox.Rd @@ -29,16 +29,16 @@ Box-Cox to also work with negative values. } \details{ The Box-Cox power transformation (type 1) requires strictly positive values and -takes the following form for \code{y > 0}: +takes the following form for \eqn{\lambda > 0}: \deqn{y^{(\lambda)} = \frac{y^\lambda - 1}{\lambda}}{y^(\lambda) = (y^\lambda - 1)/\lambda} -When \code{y = 0}, the natural log transform is used. +When \eqn{\lambda = 0}, the natural log transform is used. The modulus transformation implements a generalisation of the Box-Cox transformation that works for data with both positive and negative values. -The equation takes the following forms, when \code{y != 0} : +The equation takes the following forms, when \eqn{\lambda \neq 0} : \deqn{y^{(\lambda)} = sign(y) * \frac{(|y| + 1)^\lambda - 1}{\lambda}}{ y^(\lambda) = sign(y)*((|y|+1)^\lambda - 1)/\lambda} -and when \code{y = 0}: \deqn{y^{(\lambda)} = sign(y) * \ln(|y| + 1)}{ +and when \eqn{\lambda = 0}: \deqn{y^{(\lambda)} = sign(y) * \ln(|y| + 1)}{ y^(\lambda) = sign(y) * ln(|y| + 1)} } \examples{ diff --git a/man/unit_format.Rd b/man/unit_format.Rd index edbaad83..615a2411 100644 --- a/man/unit_format.Rd +++ b/man/unit_format.Rd @@ -11,8 +11,8 @@ unit_format( unit = "m", sep = " ", suffix = paste0(sep, unit), - big.mark = " ", - decimal.mark = ".", + big.mark = NULL, + decimal.mark = NULL, trim = TRUE, ... ) @@ -39,10 +39,13 @@ processed so that \code{prefix = "$"} will yield (e.g.) \verb{-$1} and \verb{($1 \item{suffix}{Additional text to display after the number.} -\item{big.mark}{Character used between every 3 digits to separate thousands.} +\item{big.mark}{Character used between every 3 digits to separate thousands. +The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} \item{decimal.mark}{The character to be used to indicate the numeric -decimal point.} +decimal point. The default (\code{NULL}) retrieves the setting from the +\link[=number_options]{number options}.} \item{trim}{Logical, if \code{FALSE}, values are right-justified to a common width (see \code{\link[base:format]{base::format()}}).} diff --git a/tests/testthat/_snaps/breaks-log.md b/tests/testthat/_snaps/breaks-log.md new file mode 100644 index 00000000..aa7153eb --- /dev/null +++ b/tests/testthat/_snaps/breaks-log.md @@ -0,0 +1,16 @@ +# minor_breaks_log rejects invalid arguments + + Code + minor_breaks_log(7) + Condition + Error in `minor_breaks_log()`: + ! The `detail` argument must be one of 1, 5 or 10. + +--- + + Code + minor_breaks_log(smallest = 0) + Condition + Error in `minor_breaks_log()`: + ! The `smallest` argument must be a finite, positive, non-zero number. + diff --git a/tests/testthat/test-breaks-log.R b/tests/testthat/test-breaks-log.R index be32793e..5cbecb8c 100644 --- a/tests/testthat/test-breaks-log.R +++ b/tests/testthat/test-breaks-log.R @@ -90,3 +90,26 @@ test_that("breaks_log with very small ranges fall back to extended_breaks", { extended_breaks(n = 5)(c(0.95, 3)) )) }) + +test_that("minor_breaks_log has correct amount of detail", { + range <- c(1, 10) + + test <- minor_breaks_log(detail = 1)(range) + expect_true(all(1:10 %in% test)) + + test <- minor_breaks_log(detail = 5)(range) + expect_false(all(1:10 %in% test)) + expect_true(all(c(1, 5, 10) %in% test)) + + test <- minor_breaks_log(detail = 10)(range) + expect_true(all(c(1, 10) %in% test)) + expect_false(5 %in% test) + + test <- minor_breaks_log(detail = 1)(c(-10, 10)) + expect_true(all(-10:10 %in% test)) +}) + +test_that("minor_breaks_log rejects invalid arguments", { + expect_snapshot(minor_breaks_log(7), error = TRUE) + expect_snapshot(minor_breaks_log(smallest = 0), error = TRUE) +}) diff --git a/tests/testthat/test-breaks.R b/tests/testthat/test-breaks.R index 121b3400..0ceddca0 100644 --- a/tests/testthat/test-breaks.R +++ b/tests/testthat/test-breaks.R @@ -30,3 +30,21 @@ test_that("breaks_pretty() arguments are forcely evaluated on each call #81", { expect_equal(subfun1(1), subfuns[[1]](1)) expect_equal(subfun2(1), subfuns[[2]](1)) }) + +test_that("breaks_pretty() returns input when given zero-width range (#446)", { + expect_equal(breaks_pretty()(c(1, 1)), 1) +}) + +test_that("exponential breaks give sensible values", { + x <- breaks_exp()(c(0, 2)) + expect_equal(x, c(0, 0.5, 1, 1.5, 2)) + + x <- breaks_exp()(c(0, 5)) + expect_equal(x, c(5, 4, 3, 2, 0)) + + x <- breaks_exp()(c(100, 102)) + expect_equal(x, c(0, 0.5, 1, 1.5, 2) + 100) + + x <- breaks_exp()(c(0, 100)) + expect_equal(x, c(100, 99, 98, 97, 0)) +}) diff --git a/tests/testthat/test-label-log.R b/tests/testthat/test-label-log.R index 0a555ae0..2aee4f49 100644 --- a/tests/testthat/test-label-log.R +++ b/tests/testthat/test-label-log.R @@ -5,4 +5,5 @@ test_that("label_log() returns expression", { expect_equal(label_log()(c(0.1, 10)), expression(10^-1, 10^1)) expect_equal(label_log(base = 2)(8), expression(2^3)) expect_equal(label_log(base = 2, digits = 3)(7), expression(2^2.81)) + expect_equal(label_log(signed = TRUE)(c(-100, 100)), expression(-10^2, +10^2)) }) diff --git a/tests/testthat/test-label-number.R b/tests/testthat/test-label-number.R index 4a4cd490..d003816e 100644 --- a/tests/testthat/test-label-number.R +++ b/tests/testthat/test-label-number.R @@ -179,6 +179,11 @@ test_that("scale_cut prefers clean cuts", { x <- c(518400, 691200) # prefers days over week in second element expect_equal(number(x, scale_cut = cut_time_scale()), c("6d", "8d")) + + # do not select off-scale breaks + x <- c(0, 500, 1500, 2000, 2500) + expect_equal(number(x, scale_cut = cut_short_scale()), c("0", "500", "1.5K", "2.0K", "2.5K")) + }) test_that("built-in functions return expected values", { @@ -188,3 +193,49 @@ test_that("built-in functions return expected values", { expect_equal(number(1e9, scale_cut = cut_long_scale()), "1 000M") expect_equal(number(1e9, scale_cut = cut_si("m")), "1 Gm") }) + +# options ----------------------------------------------------------------- + +test_that("number_options are observed", { + + number_options(decimal.mark = ",", big.mark = ".") + expect_equal( + label_number()(c(0.1, 10, 1e6)), + c("0,1", "10,0", "1.000.000,0") + ) + + number_options(style_positive = "plus", style_negative = "parens") + expect_equal( + label_number()(c(-0.1, 0, 1)), + c("(0.1)", "0.0", "+1.0") + ) + + number_options( + currency.prefix = "", currency.suffix = " GBP", + currency.decimal.mark = ",", currency.big.mark = "." + ) + # Regular number are not affected + expect_equal( + label_number()(c(0.1, 10, 1e6)), + c("0.1", "10.0", "1 000 000.0") + ) + # But currency is affected + expect_equal( + label_currency(accuracy = 0.1)(c(0.1, 10, 1e6)), + c("0,1 GBP", "10,0 GBP", "1.000.000,0 GBP") + ) + + number_options(ordinal.rules = ordinal_french(plural = TRUE)) + expect_equal( + label_ordinal()(1:4), + c("1ers", "2es", "3es", "4es") + ) + + # Can be reset + number_options() + expect_equal( + label_ordinal()(1:4), + c("1st", "2nd", "3rd", "4th") + ) +}) + diff --git a/tests/testthat/test-palette-registry.R b/tests/testthat/test-palette-registry.R new file mode 100644 index 00000000..06e09074 --- /dev/null +++ b/tests/testthat/test-palette-registry.R @@ -0,0 +1,41 @@ +test_that("palette getters and setters work as intended", { + + # Test that palettes have been populated in .onLoad + expect_in(c("hue", "grey"), palette_names()) + + # We cannot get unknown palettes + expect_error(get_palette("rgb"), "Unknown palette") + + # We cannot set nonsense palettes + expect_error( + set_palette("foobar", list(a = 1:2, b = "A")), + "must be a" + ) + + # Test we can set custom palettes + colours <- c("red", "green", 'blue') + set_palette("rgb", palette = colours) + expect_in("rgb", palette_names()) + + # Test we can get custom palettes + pal <- get_palette("rgb") + expect_equal(pal(length(colours)), colours) + + # Test we can reset palettes + reset_palettes() + expect_false("rgb" %in% palette_names()) +}) + +test_that("as_continuous_pal and as_discrete_pal can retrieve known palettes", { + + colours <- c("#FF0000", "#00FF00", '#0000FF') + set_palette("rgb", colours) + + pal <- as_discrete_pal("rgb") + expect_equal(pal(length(colours)), colours) + + pal <- as_continuous_pal("rgb") + expect_equal(pal(seq(0, 1, length.out = length(colours))), colours) + + reset_palettes() +})