From b526a2ed52ca47145bbea414e394540a05c31b19 Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Mon, 8 Apr 2024 16:04:06 +0200 Subject: [PATCH 1/7] format signed numbers --- R/label-log.R | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/R/label-log.R b/R/label-log.R index 802d2a13..905c7668 100644 --- a/R/label-log.R +++ b/R/label-log.R @@ -12,14 +12,25 @@ #' @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) { +label_log <- function(base = 10, digits = 3, signed = NULL) { function(x) { if (length(x) == 0) { return(expression()) } + prefix <- rep("", length(x)) + signed <- signed %||% if (any(is.finite(x))) any(x <= 0) else FALSE + if (signed) { + sign <- sign(x) + prefix[sign == +1] <- "+" + prefix[sign == -1] <- "-" + x <- abs(x) + } - exponent <- format(log(x, base = base), digits = digits) - text <- paste0(base, "^", exponent) + exponent <- format(zapsmall(log(x, base = base)), digits = digits) + text <- paste0(prefix, base, "^", exponent) + if (signed) { + text[x == 0] <- "0" + } ret <- parse_safe(text) # restore NAs from input vector From d0fc2d3a925577c5115b6f543d55726f34181046 Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Mon, 8 Apr 2024 16:04:37 +0200 Subject: [PATCH 2/7] document --- R/label-log.R | 3 +++ man/label_log.Rd | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/R/label-log.R b/R/label-log.R index 905c7668..2bc62ca9 100644 --- a/R/label-log.R +++ b/R/label-log.R @@ -5,6 +5,9 @@ #' @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. #' @inherit label_number return #' @seealso [breaks_log()] for the related breaks algorithm. #' @export diff --git a/man/label_log.Rd b/man/label_log.Rd index daf576fb..9c9cf999 100644 --- a/man/label_log.Rd +++ b/man/label_log.Rd @@ -4,13 +4,17 @@ \alias{label_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) } \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.} } \value{ All \code{label_()} functions return a "labelling" function, i.e. a function that From fb0c9eea49b818c9486090bb8500eb7838ad5129 Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Mon, 8 Apr 2024 16:04:43 +0200 Subject: [PATCH 3/7] add test --- tests/testthat/test-label-log.R | 1 + 1 file changed, 1 insertion(+) 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)) }) From 89e9e9274404230d8257807327831c9b7ed0e7e0 Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Mon, 8 Apr 2024 16:05:41 +0200 Subject: [PATCH 4/7] add news bullet --- NEWS.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS.md b/NEWS.md index 9646d4a5..6e2d1bb7 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,8 @@ # scales (development version) +* `label_log()` has a `signed` argument for displaying negative numbers + (@teunbrand, #421). + # scales 1.3.0 ## Better type support From 9215dc14208154c6144cb272afd8b23169d30cef Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Tue, 16 Apr 2024 13:05:27 +0200 Subject: [PATCH 5/7] deal with non-finite numbers better --- R/label-log.R | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/R/label-log.R b/R/label-log.R index 2bc62ca9..9f48289a 100644 --- a/R/label-log.R +++ b/R/label-log.R @@ -21,7 +21,8 @@ label_log <- function(base = 10, digits = 3, signed = NULL) { return(expression()) } prefix <- rep("", length(x)) - signed <- signed %||% if (any(is.finite(x))) any(x <= 0) else FALSE + xfinite <- x[is.finite(x)] + signed <- signed %||% any(xfinite <= 0) if (signed) { sign <- sign(x) prefix[sign == +1] <- "+" From a2990740b5258d40c515f53205fa9f99ceb5cf83 Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Fri, 4 Oct 2024 12:50:11 +0200 Subject: [PATCH 6/7] isolate formatting function --- DESCRIPTION | 2 +- NAMESPACE | 1 + R/label-log.R | 57 ++++++++++++++++++++++++++++++------------------ man/label_log.Rd | 9 +++++++- 4 files changed, 46 insertions(+), 23 deletions(-) diff --git a/DESCRIPTION b/DESCRIPTION index 38d99259..0ee8fe58 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -39,4 +39,4 @@ Config/testthat/edition: 3 Encoding: UTF-8 LazyLoad: yes Roxygen: list(markdown = TRUE, r6 = FALSE) -RoxygenNote: 7.2.3 +RoxygenNote: 7.3.2 diff --git a/NAMESPACE b/NAMESPACE index 115ded97..efa1bf22 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -83,6 +83,7 @@ export(exp_trans) export(expand_range) export(extended_breaks) export(format_format) +export(format_log) export(fullseq) export(gradient_n_pal) export(grey_pal) diff --git a/R/label-log.R b/R/label-log.R index 9f48289a..0e5321bd 100644 --- a/R/label-log.R +++ b/R/label-log.R @@ -1,6 +1,8 @@ #' 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 base Base of logarithm to use #' @param digits Number of significant digits to show for the exponent. Argument @@ -8,6 +10,7 @@ #' @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 @@ -15,31 +18,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)) +#' format_log(c(0.1, 1, 10)) label_log <- function(base = 10, digits = 3, signed = NULL) { function(x) { - if (length(x) == 0) { - return(expression()) - } - prefix <- rep("", length(x)) - xfinite <- x[is.finite(x)] - signed <- signed %||% any(xfinite <= 0) - if (signed) { - sign <- sign(x) - prefix[sign == +1] <- "+" - prefix[sign == -1] <- "-" - x <- abs(x) - } - - exponent <- format(zapsmall(log(x, base = base)), digits = digits) - text <- paste0(prefix, base, "^", exponent) - if (signed) { - text[x == 0] <- "0" - } + 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/man/label_log.Rd b/man/label_log.Rd index 9c9cf999..ebca3496 100644 --- a/man/label_log.Rd +++ b/man/label_log.Rd @@ -2,9 +2,12 @@ % 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, signed = NULL) + +format_log(x, base = 10, signed = NULL, ...) } \arguments{ \item{base}{Base of logarithm to use} @@ -15,6 +18,8 @@ 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{...}{Passed on to \code{format()}.} } \value{ All \code{label_()} functions return a "labelling" function, i.e. a function that @@ -27,7 +32,9 @@ 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()) From 9e6d5d19dafc085571e8de697b5501ba25c2905e Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Fri, 4 Oct 2024 12:56:41 +0200 Subject: [PATCH 7/7] lol at my incompetence --- R/label-log.R | 2 ++ man/label_log.Rd | 3 +++ 2 files changed, 5 insertions(+) diff --git a/R/label-log.R b/R/label-log.R index 0e5321bd..e31e2bb8 100644 --- a/R/label-log.R +++ b/R/label-log.R @@ -4,6 +4,8 @@ #' 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()]. diff --git a/man/label_log.Rd b/man/label_log.Rd index ebca3496..d0dee6ab 100644 --- a/man/label_log.Rd +++ b/man/label_log.Rd @@ -19,6 +19,8 @@ is passed on to \code{\link[base:format]{base::format()}}.} 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{ @@ -39,6 +41,7 @@ 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.