From c8df06048c5b195a8503309344c76c6cd506e967 Mon Sep 17 00:00:00 2001 From: Teun van den Brand <49372158+teunbrand@users.noreply.github.com> Date: Mon, 18 Mar 2024 09:03:09 +0100 Subject: [PATCH] Adopt suggestions of #5590 (#5721) * document `Stat$dropped_aes` * replace `stat()` with `after_stat()` * tweak ggproto docs --- R/ggproto.R | 10 +++++++++- R/stat-.R | 3 +++ man/ggplot2-ggproto.Rd | 3 +++ man/ggproto.Rd | 12 +++++++++++- vignettes/extending-ggplot2.Rmd | 8 ++++---- 5 files changed, 30 insertions(+), 6 deletions(-) diff --git a/R/ggproto.R b/R/ggproto.R index f1dec864a4..48b1fcf96f 100644 --- a/R/ggproto.R +++ b/R/ggproto.R @@ -27,12 +27,20 @@ #' To explicitly call a methods in a parent, use #' `ggproto_parent(Parent, self)`. #' +#' @section Working with ggproto classes: +#' The ggproto objects constructed are build on top of environments, which has +#' some ramifications. Environments do not follow the 'copy on modify' semantics +#' one might be accustomed to in regular objects. Instead they have +#' ['modify in place'](https://adv-r.hadley.nz/names-values.html#env-modify) +#' semantics. +#' #' @param _class Class name to assign to the object. This is stored as the class #' attribute of the object. This is optional: if `NULL` (the default), #' no class name will be added to the object. #' @param _inherit ggproto object to inherit from. If `NULL`, don't #' inherit from any object. -#' @param ... A list of members in the ggproto object. +#' @param ... A list of named members in the ggproto object. These can be +#' functions that become methods of the class or regular objects. #' @seealso #' The `r link_book("ggproto introduction section", "internals#sec-ggproto")` #' @export diff --git a/R/stat-.R b/R/stat-.R index 6f93f266ba..2d56937b06 100644 --- a/R/stat-.R +++ b/R/stat-.R @@ -45,6 +45,9 @@ #' render the geom. #' - `default_aes`: A list (generated by [aes()] of #' default values for aesthetics. +#' - `dropped_aes` is a vecor of aesthetic names that are safe to drop after +#' statistical transformation. A classic example is the `weight` aesthetic +#' that is consumed during computation of the stat. #' #' See also the `r link_book("new stats section", "extensions#sec-new-stats")` #' @rdname ggplot2-ggproto diff --git a/man/ggplot2-ggproto.Rd b/man/ggplot2-ggproto.Rd index 776429048c..5f8e570dae 100644 --- a/man/ggplot2-ggproto.Rd +++ b/man/ggplot2-ggproto.Rd @@ -381,6 +381,9 @@ required aesthetics (with a warning if \code{!na.rm}). render the geom. \item \code{default_aes}: A list (generated by \code{\link[=aes]{aes()}} of default values for aesthetics. +\item \code{dropped_aes} is a vecor of aesthetic names that are safe to drop after +statistical transformation. A classic example is the \code{weight} aesthetic +that is consumed during computation of the stat. } See also the \href{https://ggplot2-book.org/extensions#sec-new-stats}{new stats section} of the online ggplot2 book. diff --git a/man/ggproto.Rd b/man/ggproto.Rd index 7643d0cd1c..c00c2000f6 100644 --- a/man/ggproto.Rd +++ b/man/ggproto.Rd @@ -20,7 +20,8 @@ no class name will be added to the object.} \item{_inherit}{ggproto object to inherit from. If \code{NULL}, don't inherit from any object.} -\item{...}{A list of members in the ggproto object.} +\item{...}{A list of named members in the ggproto object. These can be +functions that become methods of the class or regular objects.} \item{parent, self}{Access parent class \code{parent} of object \code{self}.} @@ -59,6 +60,15 @@ To explicitly call a methods in a parent, use \code{ggproto_parent(Parent, self)}. } +\section{Working with ggproto classes}{ + +The ggproto objects constructed are build on top of environments, which has +some ramifications. Environments do not follow the 'copy on modify' semantics +one might be accustomed to in regular objects. Instead they have +\href{https://adv-r.hadley.nz/names-values.html#env-modify}{'modify in place'} +semantics. +} + \examples{ Adder <- ggproto("Adder", x = 0, diff --git a/vignettes/extending-ggplot2.Rmd b/vignettes/extending-ggplot2.Rmd index 09da823cda..e658092339 100644 --- a/vignettes/extending-ggplot2.Rmd +++ b/vignettes/extending-ggplot2.Rmd @@ -284,7 +284,7 @@ This stat illustrates another important point. If we want to make this stat usab #| the kernel density estimate of the displacement." StatDensityCommon <- ggproto("StatDensity2", Stat, required_aes = "x", - default_aes = aes(y = stat(density)), + default_aes = aes(y = after_stat(density)), compute_group = function(data, scales, bandwidth = 1) { d <- density(data$x, bw = bandwidth) @@ -292,7 +292,7 @@ StatDensityCommon <- ggproto("StatDensity2", Stat, } ) -ggplot(mpg, aes(displ, drv, colour = stat(density))) + +ggplot(mpg, aes(displ, drv, colour = after_stat(density))) + stat_density_common(bandwidth = 1, geom = "point") ``` @@ -322,7 +322,7 @@ This is because each density is computed independently, and the estimated `x`s d #| ) StatDensityCommon <- ggproto("StatDensityCommon", Stat, required_aes = "x", - default_aes = aes(y = stat(density)), + default_aes = aes(y = after_stat(density)), setup_params = function(data, params) { min <- min(data$x) - 3 * params$bandwidth @@ -344,7 +344,7 @@ StatDensityCommon <- ggproto("StatDensityCommon", Stat, ggplot(mpg, aes(displ, fill = drv)) + stat_density_common(bandwidth = 1, geom = "area", position = "stack") -ggplot(mpg, aes(displ, drv, fill = stat(density))) + +ggplot(mpg, aes(displ, drv, fill = after_stat(density))) + stat_density_common(bandwidth = 1, geom = "raster") ```