From 08f9d8e4bd4a761e4972a6ba828bacf0f5a462b1 Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Wed, 4 Sep 2024 16:22:28 +0200 Subject: [PATCH 1/5] first implementation of `labs(dict)` --- R/labels.R | 20 ++++++++++++++++++-- man/labs.Rd | 13 +++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/R/labels.R b/R/labels.R index 20cc929d37..f22ea6be58 100644 --- a/R/labels.R +++ b/R/labels.R @@ -84,6 +84,10 @@ setup_plot_labels <- function(plot, layers, data) { )) } + if (length(plot_labels$dict) > 0) { + labels <- lapply(labels, revalue, replace = plot_labels$dict) + } + defaults(plot_labels, labels) } @@ -114,6 +118,9 @@ setup_plot_labels <- function(plot, layers, data) { #' bottom-right of the plot by default. #' @param tag The text for the tag label which will be displayed at the #' top-left of the plot by default. +#' @param dict A named character vector to serve as dictionary. Automatically +#' derived labels, such as those based on variables will be matched with +#' `names(dict)` and replaced by the matching entry in `dict`. #' @param alt,alt_insight Text used for the generation of alt-text for the plot. #' See [get_alt_text] for examples. `alt` can also be a function that #' takes the plot as input and returns text as output. `alt` also accepts @@ -128,6 +135,14 @@ setup_plot_labels <- function(plot, layers, data) { #' p + labs(colour = "Cylinders") #' p + labs(x = "New x label") #' +#' # Set labels by variable name instead of aesthetic +#' p + labs(dict = c( +#' disp = "Displacment", # Not in use +#' cyl = "Number of cylinders", +#' mpg = "Miles per gallon", +#' wt = "Weight (1000 lbs)" +#' )) +#' #' # The plot title appears at the top-left, with the subtitle #' # display in smaller text underneath it #' p + labs(title = "New plot title") @@ -146,10 +161,11 @@ setup_plot_labels <- function(plot, layers, data) { #' labs(title = "title") + #' labs(title = NULL) labs <- function(..., title = waiver(), subtitle = waiver(), caption = waiver(), - tag = waiver(), alt = waiver(), alt_insight = waiver()) { + tag = waiver(), dict = waiver(), alt = waiver(), + alt_insight = waiver()) { # .ignore_empty = "all" is needed to allow trailing commas, which is NOT a trailing comma for dots_list() as it's in ... args <- dots_list(..., title = title, subtitle = subtitle, caption = caption, - tag = tag, alt = allow_lambda(alt), alt_insight = alt_insight, + tag = tag, alt = allow_lambda(alt), alt_insight = alt_insight, dict = dict, .ignore_empty = "all") is_waive <- vapply(args, is.waive, logical(1)) diff --git a/man/labs.Rd b/man/labs.Rd index 6fc7e9aa08..54940de43e 100644 --- a/man/labs.Rd +++ b/man/labs.Rd @@ -13,6 +13,7 @@ labs( subtitle = waiver(), caption = waiver(), tag = waiver(), + dict = waiver(), alt = waiver(), alt_insight = waiver() ) @@ -37,6 +38,10 @@ bottom-right of the plot by default.} \item{tag}{The text for the tag label which will be displayed at the top-left of the plot by default.} +\item{dict}{A named character vector to serve as dictionary. Automatically +derived labels, such as those based on variables will be matched with +\code{names(dict)} and replaced by the matching entry in \code{dict}.} + \item{alt, alt_insight}{Text used for the generation of alt-text for the plot. See \link{get_alt_text} for examples. \code{alt} can also be a function that takes the plot as input and returns text as output. \code{alt} also accepts @@ -68,6 +73,14 @@ p <- ggplot(mtcars, aes(mpg, wt, colour = cyl)) + geom_point() p + labs(colour = "Cylinders") p + labs(x = "New x label") +# Set labels by variable name instead of aesthetic +p + labs(dict = c( + disp = "Displacment", # Not in use + cyl = "Number of cylinders", + mpg = "Miles per gallon", + wt = "Weight (1000 lbs)" +)) + # The plot title appears at the top-left, with the subtitle # display in smaller text underneath it p + labs(title = "New plot title") From 6da58b70cbf4d7adafb199677498d51e3bce1106 Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Wed, 4 Sep 2024 16:29:22 +0200 Subject: [PATCH 2/5] add test --- tests/testthat/test-labels.R | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tests/testthat/test-labels.R b/tests/testthat/test-labels.R index 60f5165c1b..f5053f7000 100644 --- a/tests/testthat/test-labels.R +++ b/tests/testthat/test-labels.R @@ -267,6 +267,31 @@ test_that("moving guide positions lets titles follow", { ) }) +test_that("label dictionaries work", { + + p <- ggplot(mtcars, aes(disp, mpg, shape = factor(cyl), size = drat)) + + geom_point() + + labs(dict = c( + disp = "Displacement", + mpg = "Miles per gallon", + `factor(cyl)` = "Number of cylinders", + drat = "Rear axle ratio" + )) + p <- ggplot_build(p) + + x <- p$layout$resolve_label(p$layout$panel_scales_x[[1]], p$plot$labels) + expect_equal(x$primary, "Displacement") + + y <- p$layout$resolve_label(p$layout$panel_scales_y[[1]], p$plot$labels) + expect_equal(y$primary, "Miles per gallon") + + shape <- p$plot$guides$get_params("shape")$title + expect_equal(shape, "Number of cylinders") + + size <- p$plot$guides$get_params("size")$title + expect_equal(size, "Rear axle ratio") +}) + # Visual tests ------------------------------------------------------------ test_that("tags are drawn correctly", { From 1c87bf0da884e0145bb3a6eca287f3d7066d03cb Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Wed, 4 Sep 2024 16:31:37 +0200 Subject: [PATCH 3/5] add news bullet --- NEWS.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/NEWS.md b/NEWS.md index 40bdb3d156..a486c7daac 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,7 @@ # ggplot2 (development version) +* New argument `labs(dict)` to label based on variable name rather than based + on aesthetic (@teunbrand, #5178) * `guide_bins()`, `guide_colourbar()` and `guide_coloursteps()` gain an `angle` argument to overrule theme settings, similar to `guide_axis(angle)` (@teunbrand, #4594). From 2f8d981b884addf4871f6214b63538687c9870c7 Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Tue, 10 Sep 2024 12:03:21 +0200 Subject: [PATCH 4/5] rename dict --> dictionary --- NEWS.md | 4 ++-- R/labels.R | 17 +++++++++-------- man/labs.Rd | 9 +++++---- tests/testthat/test-labels.R | 2 +- 4 files changed, 17 insertions(+), 15 deletions(-) diff --git a/NEWS.md b/NEWS.md index a486c7daac..2dd0043cf1 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,7 +1,7 @@ # ggplot2 (development version) -* New argument `labs(dict)` to label based on variable name rather than based - on aesthetic (@teunbrand, #5178) +* New argument `labs(dictionary)` to label based on variable name rather than + based on aesthetic (@teunbrand, #5178) * `guide_bins()`, `guide_colourbar()` and `guide_coloursteps()` gain an `angle` argument to overrule theme settings, similar to `guide_axis(angle)` (@teunbrand, #4594). diff --git a/R/labels.R b/R/labels.R index f22ea6be58..39809dca8f 100644 --- a/R/labels.R +++ b/R/labels.R @@ -84,8 +84,8 @@ setup_plot_labels <- function(plot, layers, data) { )) } - if (length(plot_labels$dict) > 0) { - labels <- lapply(labels, revalue, replace = plot_labels$dict) + if (length(plot_labels$dictionary) > 0) { + labels <- lapply(labels, revalue, replace = plot_labels$dictionary) } defaults(plot_labels, labels) @@ -118,9 +118,10 @@ setup_plot_labels <- function(plot, layers, data) { #' bottom-right of the plot by default. #' @param tag The text for the tag label which will be displayed at the #' top-left of the plot by default. -#' @param dict A named character vector to serve as dictionary. Automatically -#' derived labels, such as those based on variables will be matched with -#' `names(dict)` and replaced by the matching entry in `dict`. +#' @param dictionary A named character vector to serve as dictionary. +#' Automatically derived labels, such as those based on variables will +#' be matched with `names(dictionary)` and replaced by the matching +#' entry in `dictionary`. #' @param alt,alt_insight Text used for the generation of alt-text for the plot. #' See [get_alt_text] for examples. `alt` can also be a function that #' takes the plot as input and returns text as output. `alt` also accepts @@ -161,12 +162,12 @@ setup_plot_labels <- function(plot, layers, data) { #' labs(title = "title") + #' labs(title = NULL) labs <- function(..., title = waiver(), subtitle = waiver(), caption = waiver(), - tag = waiver(), dict = waiver(), alt = waiver(), + tag = waiver(), dictionary = waiver(), alt = waiver(), alt_insight = waiver()) { # .ignore_empty = "all" is needed to allow trailing commas, which is NOT a trailing comma for dots_list() as it's in ... args <- dots_list(..., title = title, subtitle = subtitle, caption = caption, - tag = tag, alt = allow_lambda(alt), alt_insight = alt_insight, dict = dict, - .ignore_empty = "all") + tag = tag, alt = allow_lambda(alt), alt_insight = alt_insight, + dictionary = dictionary, .ignore_empty = "all") is_waive <- vapply(args, is.waive, logical(1)) args <- args[!is_waive] diff --git a/man/labs.Rd b/man/labs.Rd index 54940de43e..33c131e26f 100644 --- a/man/labs.Rd +++ b/man/labs.Rd @@ -13,7 +13,7 @@ labs( subtitle = waiver(), caption = waiver(), tag = waiver(), - dict = waiver(), + dictionary = waiver(), alt = waiver(), alt_insight = waiver() ) @@ -38,9 +38,10 @@ bottom-right of the plot by default.} \item{tag}{The text for the tag label which will be displayed at the top-left of the plot by default.} -\item{dict}{A named character vector to serve as dictionary. Automatically -derived labels, such as those based on variables will be matched with -\code{names(dict)} and replaced by the matching entry in \code{dict}.} +\item{dictionary}{A named character vector to serve as dictionary. +Automatically derived labels, such as those based on variables will +be matched with \code{names(dictionary)} and replaced by the matching +entry in \code{dictionary}.} \item{alt, alt_insight}{Text used for the generation of alt-text for the plot. See \link{get_alt_text} for examples. \code{alt} can also be a function that diff --git a/tests/testthat/test-labels.R b/tests/testthat/test-labels.R index f5053f7000..3cebda6785 100644 --- a/tests/testthat/test-labels.R +++ b/tests/testthat/test-labels.R @@ -271,7 +271,7 @@ test_that("label dictionaries work", { p <- ggplot(mtcars, aes(disp, mpg, shape = factor(cyl), size = drat)) + geom_point() + - labs(dict = c( + labs(dictionary = c( disp = "Displacement", mpg = "Miles per gallon", `factor(cyl)` = "Number of cylinders", From 814df05b822b7721cf313ba7eae4d5d73edf2700 Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Thu, 31 Oct 2024 14:34:50 +0100 Subject: [PATCH 5/5] `revalue` was removed --- R/labels.R | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/R/labels.R b/R/labels.R index 4894ad6777..bbbf28b6f6 100644 --- a/R/labels.R +++ b/R/labels.R @@ -84,8 +84,13 @@ setup_plot_labels <- function(plot, layers, data) { )) } - if (length(plot_labels$dictionary) > 0) { - labels <- lapply(labels, revalue, replace = plot_labels$dictionary) + dict <- plot_labels$dictionary + if (length(dict) > 0) { + labels <- lapply(labels, function(x) { + dict <- dict[names(dict) %in% x] + x[match(names(dict), x)] <- dict + x + }) } defaults(plot_labels, labels)