From a91d4f5b56392648a254ab905d0d5f9a7223fdb0 Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Thu, 18 Jul 2024 17:01:36 +0200 Subject: [PATCH 1/9] cast expressions to lists --- R/guide-bins.R | 3 +++ R/guide-colorsteps.R | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/R/guide-bins.R b/R/guide-bins.R index e2bd0db428..9a8fa03d64 100644 --- a/R/guide-bins.R +++ b/R/guide-bins.R @@ -169,6 +169,9 @@ GuideBins <- ggproto( } else { key$.show[nrow(key)] <- TRUE } + if (is.expression(labels)) { + labels <- as.list(labels) + } key$.label <- labels key <- vec_slice(key, !is.na(oob_censor_any(key$.value))) diff --git a/R/guide-colorsteps.R b/R/guide-colorsteps.R index 52b6e1809d..2df02cd972 100644 --- a/R/guide-colorsteps.R +++ b/R/guide-colorsteps.R @@ -114,7 +114,11 @@ GuideColoursteps <- ggproto( } else { key$.value <- breaks } - key$.label <- scale$get_labels(breaks) + labels <- scale$get_labels(breaks) + if (is.expression(labels)) { + labels <- as.list(labels) + } + key$.label <- labels if (breaks[1] %in% limits) { key$.value <- key$.value - 1L From 4bc4e4f90079cddbf2137e2544cb3b5e8eaac941 Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Thu, 18 Jul 2024 17:07:30 +0200 Subject: [PATCH 2/9] additional workaround for expressions --- R/guide-bins.R | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/R/guide-bins.R b/R/guide-bins.R index 9a8fa03d64..d1856a69ed 100644 --- a/R/guide-bins.R +++ b/R/guide-bins.R @@ -154,7 +154,7 @@ GuideBins <- ggproto( key$.show <- NA labels <- scale$get_labels(breaks) - if (is.character(scale$labels) || is.numeric(scale$labels)) { + if (is.character(scale$labels) || is.numeric(scale$labels) || is.expression(scale$labels)) { limit_lab <- c(NA, NA) } else { limit_lab <- scale$get_labels(limits) @@ -261,7 +261,7 @@ GuideBins <- ggproto( list(labels = flip_element_grob( elements$text, - label = key$.label, + label = validate_labels(key$.label), x = unit(key$.value, "npc"), margin_x = FALSE, margin_y = TRUE, From 3899709fbdf5aab695627fd5244458d53369b6cb Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Mon, 11 Nov 2024 16:05:48 +0100 Subject: [PATCH 3/9] linearise discrete `get_labels()` logic --- R/scale-.R | 45 ++++++++++++++++++--------------------------- 1 file changed, 18 insertions(+), 27 deletions(-) diff --git a/R/scale-.R b/R/scale-.R index b8c03571bd..fce964b3ea 100644 --- a/R/scale-.R +++ b/R/scale-.R @@ -1074,47 +1074,38 @@ ScaleDiscrete <- ggproto("ScaleDiscrete", Scale, return(NULL) } - if (is.null(self$labels)) { + labels <- self$labels + if (is.null(labels)) { return(NULL) } - if (identical(self$labels, NA)) { + if (identical(labels, NA)) { cli::cli_abort( "Invalid {.arg labels} specification. Use {.code NULL}, not {.code NA}.", call = self$call ) } - if (is.waiver(self$labels)) { + if (is.waiver(labels)) { if (!is.null(names(breaks))) { - return(names(breaks)) - } - if (is.numeric(breaks)) { + labels <- names(breaks) + } else if (is.numeric(breaks)) { # Only format numbers, because on Windows, format messes up encoding - format(breaks, justify = "none") + labels <- format(breaks, justify = "none") } else { - as.character(breaks) + labels <- as.character(breaks) } - } else if (is.function(self$labels)) { - self$labels(breaks) - } else { - if (!is.null(names(self$labels))) { - # If labels have names, use them to match with breaks - labels <- breaks - - map <- match(names(self$labels), labels, nomatch = 0) - labels[map] <- self$labels[map != 0] - labels - } else { - labels <- self$labels + } else if (is.function(labels)) { + labels <- labels(breaks) + } else if (!is.null(names(labels))) { + # If labels have names, use them to match with breaks + map <- match(names(self$labels), breaks, nomatch = 0) + labels <- replace(breaks, map, labels[map != 0]) + } else if (!is.null(attr(breaks, "pos"))) { + # Need to ensure that if breaks were dropped, corresponding labels are too + labels <- labels[attr(breaks, "pos")] + } - # Need to ensure that if breaks were dropped, corresponding labels are too - pos <- attr(breaks, "pos") - if (!is.null(pos)) { - labels <- labels[pos] - } - labels - } } }, From 4d85780726a4d857d9d3405b36690417add4115d Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Mon, 11 Nov 2024 16:10:58 +0100 Subject: [PATCH 4/9] scales cast expressions as lists --- R/scale-.R | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/R/scale-.R b/R/scale-.R index fce964b3ea..33752f9ec2 100644 --- a/R/scale-.R +++ b/R/scale-.R @@ -861,12 +861,9 @@ ScaleContinuous <- ggproto("ScaleContinuous", Scale, labels[lengths(labels) == 0] <- "" # Make sure each element is scalar labels <- lapply(labels, `[`, 1) - - if (any(vapply(labels, is.language, logical(1)))) { - labels <- inject(expression(!!!labels)) - } else { - labels <- unlist(labels) - } + } + if (is.expression(labels)) { + labels <- as.list(labels) } labels @@ -1106,7 +1103,10 @@ ScaleDiscrete <- ggproto("ScaleDiscrete", Scale, labels <- labels[attr(breaks, "pos")] } + if (is.expression(labels)) { + labels <- as.list(labels) } + labels }, clone = function(self) { @@ -1342,6 +1342,9 @@ ScaleBinned <- ggproto("ScaleBinned", Scale, call = self$call ) } + if (is.expression(labels)) { + labels <- as.list(labels) + } labels }, From 3074d3c56368730181cd13e3e439a561aaf996bb Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Mon, 11 Nov 2024 16:17:39 +0100 Subject: [PATCH 5/9] alleviate wrangling label expressions --- R/guide-.R | 7 +------ R/guide-axis-theta.R | 2 +- R/guide-bins.R | 3 --- R/guide-colorsteps.R | 13 +++---------- 4 files changed, 5 insertions(+), 20 deletions(-) diff --git a/R/guide-.R b/R/guide-.R index fc002c33d2..aa2aa7b37d 100644 --- a/R/guide-.R +++ b/R/guide-.R @@ -225,13 +225,8 @@ Guide <- ggproto( mapped <- scale$map(breaks) labels <- scale$get_labels(breaks) - # {vctrs} doesn't play nice with expressions, convert to list. - # see also https://github.com/r-lib/vctrs/issues/559 - if (is.expression(labels)) { - labels <- as.list(labels) - } - key <- data_frame(mapped, .name_repair = ~ aesthetic) + key <- data_frame(!!aesthetic := mapped) key$.value <- breaks key$.label <- labels diff --git a/R/guide-axis-theta.R b/R/guide-axis-theta.R index 7c7b62a9d0..dc4e1b405d 100644 --- a/R/guide-axis-theta.R +++ b/R/guide-axis-theta.R @@ -110,7 +110,7 @@ GuideAxisTheta <- ggproto( # labels of these positions ends_apart <- (key$theta[n] - key$theta[1]) %% (2 * pi) if (n > 0 && ends_apart < 0.05 && !is.null(key$.label)) { - if (is.expression(key$.label)) { + if (is.expression(key$.label[[1]])) { combined <- substitute( paste(a, "/", b), list(a = key$.label[[1]], b = key$.label[[n]]) diff --git a/R/guide-bins.R b/R/guide-bins.R index f5a554f0f0..5bc695b010 100644 --- a/R/guide-bins.R +++ b/R/guide-bins.R @@ -176,9 +176,6 @@ GuideBins <- ggproto( } else { key$.show[nrow(key)] <- TRUE } - if (is.expression(labels)) { - labels <- as.list(labels) - } key$.label <- labels key <- vec_slice(key, !is.na(oob_censor_any(key$.value))) diff --git a/R/guide-colorsteps.R b/R/guide-colorsteps.R index c998e0d026..14e03cb916 100644 --- a/R/guide-colorsteps.R +++ b/R/guide-colorsteps.R @@ -111,16 +111,9 @@ GuideColoursteps <- ggproto( breaks <- parsed$breaks key <- data_frame0(!!aesthetic := scale$map(breaks)) - if (even.steps) { - key$.value <- seq_along(breaks) - } else { - key$.value <- breaks - } - labels <- scale$get_labels(breaks) - if (is.expression(labels)) { - labels <- as.list(labels) - } - key$.label <- labels + fmt <- if (even.steps) seq_along else identity + key$.value <- fmt(breaks) + key$.label <- scale$get_labels(breaks) if (breaks[1] %in% limits) { key$.value <- key$.value - 1L From dd29d6d73eb2dde111d8c70bbeb3fd73a86d3671 Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Mon, 11 Nov 2024 16:29:05 +0100 Subject: [PATCH 6/9] fix deprecated argument name --- tests/testthat/test-scale-binned.R | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/testthat/test-scale-binned.R b/tests/testthat/test-scale-binned.R index 1f558b6c77..527d862339 100644 --- a/tests/testthat/test-scale-binned.R +++ b/tests/testthat/test-scale-binned.R @@ -47,7 +47,7 @@ test_that("binned limits should not compute out-of-bounds breaks", { test_that("binned scales can use limits and transformations simultaneously (#6144)", { s <- scale_x_binned( limits = function(x) x + 1, - trans = transform_log10() + transform = transform_log10() ) s$train(c(0, 1)) # c(1, 10) in untransformed space out <- s$get_limits() From e861ac8605198a27741bd7e16c1fa57d3ab1729c Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Mon, 11 Nov 2024 16:38:52 +0100 Subject: [PATCH 7/9] add news bullets --- NEWS.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS.md b/NEWS.md index 081504c782..c9eac7d42c 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,7 @@ # ggplot2 (development version) +* Binned guides now accept expressions as labels (@teunbrand, #6005) +* (internal) `Scale$get_labels()` format expressions as lists. * When discrete breaks have names, they'll be used as labels by default (@teunbrand, #6147). * The helper function `is.waiver()` is now exported to help extensions to work From e4fc71c6fc831b096b67bcab406408ccf5df9bc6 Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Mon, 2 Dec 2024 10:16:02 +0100 Subject: [PATCH 8/9] revert even.steps logic --- R/guide-colorsteps.R | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/R/guide-colorsteps.R b/R/guide-colorsteps.R index 14e03cb916..aea85f9cfe 100644 --- a/R/guide-colorsteps.R +++ b/R/guide-colorsteps.R @@ -111,7 +111,11 @@ GuideColoursteps <- ggproto( breaks <- parsed$breaks key <- data_frame0(!!aesthetic := scale$map(breaks)) - fmt <- if (even.steps) seq_along else identity + if (even.steps) { + key$.value <- seq_along(breaks) + } else { + key$.value <- breaks + } key$.value <- fmt(breaks) key$.label <- scale$get_labels(breaks) From 65db1e2e3adc65946600737a0b908b0741f320de Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Mon, 2 Dec 2024 10:51:36 +0100 Subject: [PATCH 9/9] lol at my incompetence --- R/guide-colorsteps.R | 1 - 1 file changed, 1 deletion(-) diff --git a/R/guide-colorsteps.R b/R/guide-colorsteps.R index aea85f9cfe..54cd89a948 100644 --- a/R/guide-colorsteps.R +++ b/R/guide-colorsteps.R @@ -116,7 +116,6 @@ GuideColoursteps <- ggproto( } else { key$.value <- breaks } - key$.value <- fmt(breaks) key$.label <- scale$get_labels(breaks) if (breaks[1] %in% limits) {