From 6dc3ba8e5490d7900186cc59216709a1fb3325d1 Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Wed, 24 Apr 2024 13:42:23 +0200 Subject: [PATCH 01/15] required aesthetics to non-missing aes --- R/geom-rect.R | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/R/geom-rect.R b/R/geom-rect.R index d39978897a..4db536312e 100644 --- a/R/geom-rect.R +++ b/R/geom-rect.R @@ -31,7 +31,8 @@ GeomRect <- ggproto("GeomRect", Geom, default_aes = aes(colour = NA, fill = "grey35", linewidth = 0.5, linetype = 1, alpha = NA), - required_aes = c("xmin", "xmax", "ymin", "ymax"), + optional_aes = c("x", "width", "xmin", "xmax", "y", "height", "ymin", "ymax"), + non_missing_aes = c("xmin", "xmax", "ymin", "ymax"), draw_panel = function(self, data, panel_params, coord, lineend = "butt", linejoin = "mitre") { data <- check_linewidth(data, snake_class(self)) From 65030f5ecb3a63f7cdb650f900867d654d08c39a Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Wed, 24 Apr 2024 13:42:47 +0200 Subject: [PATCH 02/15] doesn't inherit `optional_aes` --- R/geom-bar.R | 2 ++ 1 file changed, 2 insertions(+) diff --git a/R/geom-bar.R b/R/geom-bar.R index e4611fbabb..03f2c76ba3 100644 --- a/R/geom-bar.R +++ b/R/geom-bar.R @@ -129,6 +129,8 @@ geom_bar <- function(mapping = NULL, data = NULL, GeomBar <- ggproto("GeomBar", GeomRect, required_aes = c("x", "y"), + optional_aes = character(), + # These aes columns are created by setup_data(). They need to be listed here so # that GeomRect$handle_na() properly removes any bars that fall outside the defined # limits, not just those for which x and y are outside the limits From 71923cc412047016d88aeacf2478dad9645fbfca Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Wed, 24 Apr 2024 13:43:19 +0200 Subject: [PATCH 03/15] fill missing aes --- R/geom-rect.R | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/R/geom-rect.R b/R/geom-rect.R index 4db536312e..3ffafcd706 100644 --- a/R/geom-rect.R +++ b/R/geom-rect.R @@ -34,6 +34,20 @@ GeomRect <- ggproto("GeomRect", Geom, optional_aes = c("x", "width", "xmin", "xmax", "y", "height", "ymin", "ymax"), non_missing_aes = c("xmin", "xmax", "ymin", "ymax"), + setup_data = function(self, data, params) { + if (is.null(data$xmin) || is.null(data$xmax)) { + x <- resolve_rect(data$xmin, data$xmax, data$x, data$width %||% params$width) + i <- lengths(x) > 1 + data[c("xmin", "xmax")[i]] <- x[i] + } + if (is.null(data$ymin) || is.null(data$ymax)) { + y <- resolve_rect(data$ymin, data$ymax, data$y, data$height %||% params$height) + i <- lengths(y) > 1 + data[c("ymin", "ymax")[i]] <- y[i] + } + data + }, + draw_panel = function(self, data, panel_params, coord, lineend = "butt", linejoin = "mitre") { data <- check_linewidth(data, snake_class(self)) if (!coord$is_linear()) { @@ -74,3 +88,25 @@ GeomRect <- ggproto("GeomRect", Geom, rename_size = TRUE ) + +resolve_rect <- function(min = NULL, max = NULL, center = NULL, length = NULL) { + if (is.null(min) && is.null(max)) { + min <- center - 0.5 * length + max <- center + 0.5 * length + return(list(min = min, max = max)) + } + if (is.null(min)) { + if (is.null(center)) { + min <- max - length + } else { + min <- max - 2 * (max - center) + } + } + if (is.null(max)) { + if (is.null(center)) { + max <- min + length + } else { + max <- min + 2 * (center - min) + } + } + list(min = min, max = max) From 93b45ad4106e261c863b68a824e2932e0ff66e2f Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Wed, 24 Apr 2024 13:43:36 +0200 Subject: [PATCH 04/15] throw error when unresolveable --- R/geom-rect.R | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/R/geom-rect.R b/R/geom-rect.R index 3ffafcd706..98a6cded81 100644 --- a/R/geom-rect.R +++ b/R/geom-rect.R @@ -45,6 +45,11 @@ GeomRect <- ggproto("GeomRect", Geom, i <- lengths(y) > 1 data[c("ymin", "ymax")[i]] <- y[i] } + check_required_aesthetics( + self$non_missing_aes, + names(data), + snake_class(self) + ) data }, @@ -110,3 +115,4 @@ resolve_rect <- function(min = NULL, max = NULL, center = NULL, length = NULL) { } } list(min = min, max = max) +} From 99293fdc1bc566bbbb05e458ec07b3f1b29063f1 Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Wed, 24 Apr 2024 14:06:55 +0200 Subject: [PATCH 05/15] protect against partial matching --- R/geom-rect.R | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/R/geom-rect.R b/R/geom-rect.R index 98a6cded81..c0a567deb0 100644 --- a/R/geom-rect.R +++ b/R/geom-rect.R @@ -36,12 +36,18 @@ GeomRect <- ggproto("GeomRect", Geom, setup_data = function(self, data, params) { if (is.null(data$xmin) || is.null(data$xmax)) { - x <- resolve_rect(data$xmin, data$xmax, data$x, data$width %||% params$width) + x <- resolve_rect( + data[["xmin"]], data[["xmax"]], + data[["x"]], data[["width"]] %||% params$width + ) i <- lengths(x) > 1 data[c("xmin", "xmax")[i]] <- x[i] } if (is.null(data$ymin) || is.null(data$ymax)) { - y <- resolve_rect(data$ymin, data$ymax, data$y, data$height %||% params$height) + y <- resolve_rect( + data[["ymin"]], data[["ymax"]], + data[["y"]], data[["height"]] %||% params$height + ) i <- lengths(y) > 1 data[c("ymin", "ymax")[i]] <- y[i] } From e992f51429209256221e25c8cc2bc9021c233961 Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Wed, 24 Apr 2024 14:07:03 +0200 Subject: [PATCH 06/15] add tests --- tests/testthat/test-geom-rect.R | 36 +++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 tests/testthat/test-geom-rect.R diff --git a/tests/testthat/test-geom-rect.R b/tests/testthat/test-geom-rect.R new file mode 100644 index 0000000000..ccf865b030 --- /dev/null +++ b/tests/testthat/test-geom-rect.R @@ -0,0 +1,36 @@ +test_that("geom_rect can derive corners", { + + corners <- c("xmin", "xmax", "ymin", "ymax") + full <- data.frame( + xmin = c(1, 2), xmax = c(3, 6), + ymin = c(1, 2), ymax = c(3, 6), + width = c(2, 4), height = c(2, 4), + x = c(2, 4), y = c(2, 4) + ) + + test <- full[, c("xmin", "ymin", "width", "height")] + test <- GeomRect$setup_data(test, NULL) + expect_equal(full[, corners], test[, corners]) + + test <- full[, c("xmin", "ymin", "x", "y")] + test <- GeomRect$setup_data(test, NULL) + expect_equal(full[, corners], test[, corners]) + + test <- full[, c("x", "y", "width", "height")] + test <- GeomRect$setup_data(test, NULL) + expect_equal(full[, corners], test[, corners]) + + test <- full[, c("xmax", "ymax", "width", "height")] + test <- GeomRect$setup_data(test, NULL) + expect_equal(full[, corners], test[, corners]) + + test <- full[, c("xmax", "ymax", "x", "y")] + test <- GeomRect$setup_data(test, NULL) + expect_equal(full[, corners], test[, corners]) + + test <- full[, c("x", "y")] + expect_error( + GeomRect$setup_data(test, NULL), + "requires the following missing aesthetics" + ) +}) From b083634f1187133af87b28ba9f58b9e3c20adb0b Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Wed, 24 Apr 2024 14:12:51 +0200 Subject: [PATCH 07/15] add news bullet --- NEWS.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS.md b/NEWS.md index cd39c0b8ad..ade8564eca 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,5 +1,8 @@ # ggplot2 (development version) +* `geom_rect()` can now derive the required corners positions from `x`/`width` + or `y`/`height` parameterisation (@teunbrand, #5861). + # ggplot2 3.5.1 This is a small release focusing on fixing regressions from 3.5.0 and From 984749c1311e238f185c0a0defc01a2783759338 Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Wed, 24 Apr 2024 14:20:26 +0200 Subject: [PATCH 08/15] adjust docs --- R/geom-tile.R | 19 ++++++++----------- man/geom_tile.Rd | 23 ++++++++++++----------- 2 files changed, 20 insertions(+), 22 deletions(-) diff --git a/R/geom-tile.R b/R/geom-tile.R index 139d6f733e..37a993beb3 100644 --- a/R/geom-tile.R +++ b/R/geom-tile.R @@ -1,12 +1,11 @@ #' Rectangles #' #' `geom_rect()` and `geom_tile()` do the same thing, but are -#' parameterised differently: `geom_rect()` uses the locations of the four -#' corners (`xmin`, `xmax`, `ymin` and `ymax`), while -#' `geom_tile()` uses the center of the tile and its size (`x`, -#' `y`, `width`, `height`). `geom_raster()` is a high -#' performance special case for when all the tiles are the same size, and no -#' pattern fills are applied. +#' parameterised differently: `geom_tile()` uses the center of the tile and its +#' size (`x`, `y`, `width`, `height`), while `geom_rect()` can use those or the +#' locations of the corners (`xmin`, `xmax`, `ymin` and `ymax`). +#' `geom_raster()` is a high performance special case for when all the tiles +#' are the same size, and no pattern fills are applied. #' #' @eval rd_aesthetics("geom", "tile", "Note that `geom_raster()` ignores `colour`.") #' @inheritParams layer @@ -15,11 +14,9 @@ #' @export #' #' @details -#' `geom_rect()` and `geom_tile()`'s respond differently to scale -#' transformations due to their parameterisation. In `geom_rect()`, the scale -#' transformation is applied to the corners of the rectangles. In `geom_tile()`, -#' the transformation is applied only to the centres and its size is determined -#' after transformation. +#' Please note that the `width` and `height` aesthetics are not true position +#' aesthetics and therefore are not subject to scale transformation. It is +#' only after transformation that these aesthetics are applied. #' #' @examples #' # The most common use for rectangles is to draw a surface. You always want diff --git a/man/geom_tile.Rd b/man/geom_tile.Rd index a45ca07008..2511051e8f 100644 --- a/man/geom_tile.Rd +++ b/man/geom_tile.Rd @@ -144,19 +144,16 @@ the default plot specification, e.g. \code{\link[=borders]{borders()}}.} } \description{ \code{geom_rect()} and \code{geom_tile()} do the same thing, but are -parameterised differently: \code{geom_rect()} uses the locations of the four -corners (\code{xmin}, \code{xmax}, \code{ymin} and \code{ymax}), while -\code{geom_tile()} uses the center of the tile and its size (\code{x}, -\code{y}, \code{width}, \code{height}). \code{geom_raster()} is a high -performance special case for when all the tiles are the same size, and no -pattern fills are applied. +parameterised differently: \code{geom_tile()} uses the center of the tile and its +size (\code{x}, \code{y}, \code{width}, \code{height}), while \code{geom_rect()} can use those or the +locations of the corners (\code{xmin}, \code{xmax}, \code{ymin} and \code{ymax}). +\code{geom_raster()} is a high performance special case for when all the tiles +are the same size, and no pattern fills are applied. } \details{ -\code{geom_rect()} and \code{geom_tile()}'s respond differently to scale -transformations due to their parameterisation. In \code{geom_rect()}, the scale -transformation is applied to the corners of the rectangles. In \code{geom_tile()}, -the transformation is applied only to the centres and its size is determined -after transformation. +Please note that the \code{width} and \code{height} aesthetics are not true position +aesthetics and therefore are not subject to scale transformation. It is +only after transformation that these aesthetics are applied. } \section{Aesthetics}{ @@ -172,6 +169,10 @@ after transformation. \item \code{\link[=aes_linetype_size_shape]{linetype}} \item \code{\link[=aes_linetype_size_shape]{linewidth}} \item \code{width} +\item \code{\link[=aes_position]{xmax}} +\item \code{\link[=aes_position]{xmin}} +\item \code{\link[=aes_position]{ymax}} +\item \code{\link[=aes_position]{ymin}} } Note that \code{geom_raster()} ignores \code{colour}. From 41c6090dc2a5d86fee9214c78d9a9da47ebad1d2 Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Fri, 26 Apr 2024 14:19:00 +0200 Subject: [PATCH 09/15] fallback for corners wired through `params` --- R/geom-rect.R | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/R/geom-rect.R b/R/geom-rect.R index c0a567deb0..867d03ec7c 100644 --- a/R/geom-rect.R +++ b/R/geom-rect.R @@ -35,6 +35,10 @@ GeomRect <- ggproto("GeomRect", Geom, non_missing_aes = c("xmin", "xmax", "ymin", "ymax"), setup_data = function(self, data, params) { + data$xmin <- data$xmin %||% params$xmin + data$xmax <- data$xmax %||% params$xmax + data$ymin <- data$ymin %||% params$ymin + data$ymax <- data$ymax %||% params$ymax if (is.null(data$xmin) || is.null(data$xmax)) { x <- resolve_rect( data[["xmin"]], data[["xmax"]], From 0581b23c95ea9cf1cadc55f3edf5995139e94305 Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Tue, 21 May 2024 11:36:12 +0200 Subject: [PATCH 10/15] Revert " doesn't inherit `optional_aes`" This reverts commit 65030f5ecb3a63f7cdb650f900867d654d08c39a. --- R/geom-bar.R | 2 -- 1 file changed, 2 deletions(-) diff --git a/R/geom-bar.R b/R/geom-bar.R index b37ce34997..de7490bfc4 100644 --- a/R/geom-bar.R +++ b/R/geom-bar.R @@ -125,8 +125,6 @@ geom_bar <- function(mapping = NULL, data = NULL, GeomBar <- ggproto("GeomBar", GeomRect, required_aes = c("x", "y"), - optional_aes = character(), - # These aes columns are created by setup_data(). They need to be listed here so # that GeomRect$handle_na() properly removes any bars that fall outside the defined # limits, not just those for which x and y are outside the limits From 939534142831c95bd33e82629ef8f8238d4215ad Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Tue, 21 May 2024 13:03:27 +0200 Subject: [PATCH 11/15] adapt `check_required_aesthetics()` to deal with multiple or-logic --- R/utilities.R | 56 ++++++++++++++++++++++-------- tests/testthat/_snaps/utilities.md | 2 +- 2 files changed, 43 insertions(+), 15 deletions(-) diff --git a/R/utilities.R b/R/utilities.R index 1a9181be69..a3357e6119 100644 --- a/R/utilities.R +++ b/R/utilities.R @@ -24,25 +24,53 @@ scales::alpha # @param name of object for error message # @keyword internal check_required_aesthetics <- function(required, present, name, call = caller_env()) { - if (is.null(required)) return() + if (is.null(required)) { + return() + } required <- strsplit(required, "|", fixed = TRUE) - if (any(lengths(required) > 1)) { - required <- lapply(required, rep_len, 2) - required <- list( - vapply(required, `[`, character(1), 1), - vapply(required, `[`, character(1), 2) + n <- lengths(required) + + is_present <- vapply( + required, + function(req) any(req %in% present), + logical(1) + ) + if (all(is_present)) { + return() + } + + # Deal with paired (bidirectional) aesthetics + pairs <- character() + missing_pairs <- n == 2 + if (any(missing_pairs)) { + pairs <- lapply(required[missing_pairs], rep_len, 2) + pairs <- list( + vapply(pairs, `[`, character(1), 1), + vapply(pairs, `[`, character(1), 2) ) - } else { - required <- list(unlist(required)) + pairs <- lapply(pairs, setdiff, present) + pairs <- vapply(pairs, function(x) { + as_cli("{.and {.field {x}}}") + }, character(1)) + pairs <- as_cli("{.or {pairs}}") } - missing_aes <- lapply(required, setdiff, present) - if (any(lengths(missing_aes) == 0)) return() - message <- "{.fn {name}} requires the following missing aesthetics: {.field {missing_aes[[1]]}}" - if (length(missing_aes) > 1) { - message <- paste0(message, " {.strong or} {.field {missing_aes[[2]]}}") + + other <- character() + missing_other <- !is_present & n != 2 + if (any(missing_other)) { + other <- lapply(required[missing_other], setdiff, present) + other <- vapply(other, function(x) { + as_cli("{.or {.field {x}}}") + }, character(1)) } - cli::cli_abort(paste0(message, "."), call = call) + + missing <- c(other, pairs) + + cli::cli_abort( + "{.fn {name}} requires the following missing aesthetics: {.and {missing}}.", + call = call + ) } # Concatenate a named list for output diff --git a/tests/testthat/_snaps/utilities.md b/tests/testthat/_snaps/utilities.md index 804ce1ad27..0101c1edd1 100644 --- a/tests/testthat/_snaps/utilities.md +++ b/tests/testthat/_snaps/utilities.md @@ -12,7 +12,7 @@ --- - `test()` requires the following missing aesthetics: x and fill or y and fill. + `test()` requires the following missing aesthetics: fill and x or y. # remove_missing checks input From f991ec5a9b4b19ba27bda58973cd5688be7fa302 Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Tue, 21 May 2024 13:25:32 +0200 Subject: [PATCH 12/15] undo aesthetic field voodoo --- R/geom-rect.R | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/R/geom-rect.R b/R/geom-rect.R index d11c42a206..b8293a9b0a 100644 --- a/R/geom-rect.R +++ b/R/geom-rect.R @@ -31,8 +31,7 @@ GeomRect <- ggproto("GeomRect", Geom, default_aes = aes(colour = NA, fill = "grey35", linewidth = 0.5, linetype = 1, alpha = NA), - optional_aes = c("x", "width", "xmin", "xmax", "y", "height", "ymin", "ymax"), - non_missing_aes = c("xmin", "xmax", "ymin", "ymax"), + required_aes = c("x|width|xmin|xmax", "y|height|ymin|ymax"), setup_data = function(self, data, params) { data$xmin <- data$xmin %||% params$xmin From b990a2bc02ea5d5e7888cf0c683fb9f2a9acd260 Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Tue, 21 May 2024 13:27:20 +0200 Subject: [PATCH 13/15] fill data from params more reliably --- R/geom-rect.R | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/R/geom-rect.R b/R/geom-rect.R index b8293a9b0a..1ee98c31da 100644 --- a/R/geom-rect.R +++ b/R/geom-rect.R @@ -34,14 +34,20 @@ GeomRect <- ggproto("GeomRect", Geom, required_aes = c("x|width|xmin|xmax", "y|height|ymin|ymax"), setup_data = function(self, data, params) { - data$xmin <- data$xmin %||% params$xmin - data$xmax <- data$xmax %||% params$xmax - data$ymin <- data$ymin %||% params$ymin - data$ymax <- data$ymax %||% params$ymax + if (all(c("xmin", "xmax", "ymin", "ymax") %in% names(data))) { + return(data) + } + + # Fill in missing aesthetics from parameters + required <- strsplit(self$required_aes, "|", fixed = TRUE) + missing <- setdiff(unlist(required), names(data)) + default <- params[intersect(missing, names(params))] + data[names(default)] <- default + if (is.null(data$xmin) || is.null(data$xmax)) { x <- resolve_rect( data[["xmin"]], data[["xmax"]], - data[["x"]], data[["width"]] %||% params$width + data[["x"]], data[["width"]] ) i <- lengths(x) > 1 data[c("xmin", "xmax")[i]] <- x[i] @@ -49,7 +55,7 @@ GeomRect <- ggproto("GeomRect", Geom, if (is.null(data$ymin) || is.null(data$ymax)) { y <- resolve_rect( data[["ymin"]], data[["ymax"]], - data[["y"]], data[["height"]] %||% params$height + data[["y"]], data[["height"]] ) i <- lengths(y) > 1 data[c("ymin", "ymax")[i]] <- y[i] From 5d01396f39ce3f2426eccfacba67da70b06db9bc Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Tue, 21 May 2024 13:43:30 +0200 Subject: [PATCH 14/15] throw error from `resolve_rect()` --- R/geom-rect.R | 34 ++++++++++++++++++++++----------- tests/testthat/test-geom-rect.R | 2 +- 2 files changed, 24 insertions(+), 12 deletions(-) diff --git a/R/geom-rect.R b/R/geom-rect.R index 1ee98c31da..0ed01e6fd6 100644 --- a/R/geom-rect.R +++ b/R/geom-rect.R @@ -47,7 +47,8 @@ GeomRect <- ggproto("GeomRect", Geom, if (is.null(data$xmin) || is.null(data$xmax)) { x <- resolve_rect( data[["xmin"]], data[["xmax"]], - data[["x"]], data[["width"]] + data[["x"]], data[["width"]], + fun = snake_class(self), type = "x" ) i <- lengths(x) > 1 data[c("xmin", "xmax")[i]] <- x[i] @@ -55,16 +56,12 @@ GeomRect <- ggproto("GeomRect", Geom, if (is.null(data$ymin) || is.null(data$ymax)) { y <- resolve_rect( data[["ymin"]], data[["ymax"]], - data[["y"]], data[["height"]] + data[["y"]], data[["height"]], + fun = snake_class(self), type = "y" ) i <- lengths(y) > 1 data[c("ymin", "ymax")[i]] <- y[i] } - check_required_aesthetics( - self$non_missing_aes, - names(data), - snake_class(self) - ) data }, @@ -109,20 +106,35 @@ GeomRect <- ggproto("GeomRect", Geom, rename_size = TRUE ) -resolve_rect <- function(min = NULL, max = NULL, center = NULL, length = NULL) { - if (is.null(min) && is.null(max)) { +resolve_rect <- function(min = NULL, max = NULL, center = NULL, length = NULL, + fun, type) { + absent <- c(is.null(min), is.null(max), is.null(center), is.null(length)) + if (sum(absent) > 2) { + missing <- switch( + type, + x = c("xmin", "xmax", "x", "width"), + y = c("ymin", "ymax", "y", "height") + ) + cli::cli_abort(c( + "{.fn {fun}} requires two of the following aesthetics: \\ + {.or {.field {missing}}}.", + i = "Currently, {.field {missing[!absent]}} is present." + )) + } + + if (absent[1] && absent[2]) { min <- center - 0.5 * length max <- center + 0.5 * length return(list(min = min, max = max)) } - if (is.null(min)) { + if (absent[1]) { if (is.null(center)) { min <- max - length } else { min <- max - 2 * (max - center) } } - if (is.null(max)) { + if (absent[2]) { if (is.null(center)) { max <- min + length } else { diff --git a/tests/testthat/test-geom-rect.R b/tests/testthat/test-geom-rect.R index ccf865b030..a0d90899f8 100644 --- a/tests/testthat/test-geom-rect.R +++ b/tests/testthat/test-geom-rect.R @@ -31,6 +31,6 @@ test_that("geom_rect can derive corners", { test <- full[, c("x", "y")] expect_error( GeomRect$setup_data(test, NULL), - "requires the following missing aesthetics" + "requires two of the following aesthetics" ) }) From b79e68e348ca02501af847b72664a1b7a5dd7669 Mon Sep 17 00:00:00 2001 From: Teun van den Brand Date: Tue, 21 May 2024 13:49:52 +0200 Subject: [PATCH 15/15] document --- R/geom-tile.R | 6 +++++- R/utilities-help.R | 2 +- man/geom_tile.Rd | 13 ++++--------- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/R/geom-tile.R b/R/geom-tile.R index ddc56c407e..a5e3232080 100644 --- a/R/geom-tile.R +++ b/R/geom-tile.R @@ -7,7 +7,11 @@ #' `geom_raster()` is a high performance special case for when all the tiles #' are the same size, and no pattern fills are applied. #' -#' @eval rd_aesthetics("geom", "tile", "Note that `geom_raster()` ignores `colour`.") +#' @eval rd_aesthetics( +#' "geom", "rect", +#' "`geom_tile()` understands only the `x`/`width` and `y`/`height` combinations. +#' Note that `geom_raster()` ignores `colour`." +#' ) #' @inheritParams layer #' @inheritParams geom_point #' @inheritParams geom_segment diff --git a/R/utilities-help.R b/R/utilities-help.R index 4a2312b549..87f5419612 100644 --- a/R/utilities-help.R +++ b/R/utilities-help.R @@ -23,7 +23,7 @@ rd_aesthetics <- function(type, name, extra_note = NULL) { rd_aesthetics_item <- function(x) { req <- x$required_aes - req <- sub("|", "} \\emph{or} \\code{", req, fixed = TRUE) + req <- gsub("|", "} \\emph{or} \\code{", req, fixed = TRUE) req_aes <- unlist(strsplit(x$required_aes, "|", fixed = TRUE)) optional_aes <- setdiff(x$aesthetics(), req_aes) all <- union(req, sort(optional_aes)) diff --git a/man/geom_tile.Rd b/man/geom_tile.Rd index 2511051e8f..ac32298ee7 100644 --- a/man/geom_tile.Rd +++ b/man/geom_tile.Rd @@ -157,23 +157,18 @@ only after transformation that these aesthetics are applied. } \section{Aesthetics}{ -\code{geom_tile()} understands the following aesthetics (required aesthetics are in bold): +\code{geom_rect()} understands the following aesthetics (required aesthetics are in bold): \itemize{ -\item \strong{\code{\link[=aes_position]{x}}} -\item \strong{\code{\link[=aes_position]{y}}} +\item \strong{\code{\link[=aes_position]{x}} \emph{or} \code{width} \emph{or} \code{\link[=aes_position]{xmin}} \emph{or} \code{\link[=aes_position]{xmax}}} +\item \strong{\code{\link[=aes_position]{y}} \emph{or} \code{height} \emph{or} \code{\link[=aes_position]{ymin}} \emph{or} \code{\link[=aes_position]{ymax}}} \item \code{\link[=aes_colour_fill_alpha]{alpha}} \item \code{\link[=aes_colour_fill_alpha]{colour}} \item \code{\link[=aes_colour_fill_alpha]{fill}} \item \code{\link[=aes_group_order]{group}} -\item \code{height} \item \code{\link[=aes_linetype_size_shape]{linetype}} \item \code{\link[=aes_linetype_size_shape]{linewidth}} -\item \code{width} -\item \code{\link[=aes_position]{xmax}} -\item \code{\link[=aes_position]{xmin}} -\item \code{\link[=aes_position]{ymax}} -\item \code{\link[=aes_position]{ymin}} } +\code{geom_tile()} understands only the \code{x}/\code{width} and \code{y}/\code{height} combinations. Note that \code{geom_raster()} ignores \code{colour}. Learn more about setting these aesthetics in \code{vignette("ggplot2-specs")}.