diff --git a/vignettes/ggplot2-in-packages.Rmd b/vignettes/ggplot2-in-packages.Rmd index fb40d8ba44..507562ba53 100644 --- a/vignettes/ggplot2-in-packages.Rmd +++ b/vignettes/ggplot2-in-packages.Rmd @@ -79,6 +79,8 @@ There are three situations in which you will encounter this problem: - You have the column name as a character vector. - The user specifies the column name or expression, and you want your function to use the same kind of non-standard evaluation used by `aes()` and `vars()`. +### Mapping is known in advance + If you already know the mapping in advance (like the above example) you should use the `.data` pronoun from [rlang](https://rlang.r-lib.org/) to make it explicit that you are referring to the `drv` in the layer data and not some other variable named `drv` (which may or may not exist elsewhere). To avoid a similar note from the CMD check about `.data`, use `#' @importFrom rlang .data` in any roxygen code block (typically this should be in the package documentation as generated by `usethis::use_package_doc()`). ```{r} @@ -89,6 +91,8 @@ mpg_drv_summary <- function() { } ``` +### Character columns + If you have the column name as a character vector (e.g., `col = "drv"`), use `.data[[col]]`: ```{r} @@ -101,6 +105,28 @@ col_summary <- function(df, col, by) { col_summary(mpg, "drv", "year") ``` +When using this strategy, you may need some extra care in passing optional arguments. +You can use optional arguments by setting `NULL` as a default value, and treating non-null input with `rlang::data_syms`. +Thereafter, these arguments can be spliced using the `!!!` operation. + +```{r} +col_summary <- function(df, col, by = NULL, fill = NULL, ...) { + + optional <- list(fill = fill, ...) + is_symbol <- lengths(optional) > 0 + optional <- c(rlang::data_syms(optional[is_symbol]), optional[!is_symbol]) + + by <- if (!is.null(by)) facet_wrap(vars(.data[[by]])) + + ggplot(df) + + geom_bar(aes(y = .data[[col]], !!!optional)) + + by +} + +col_summary(mpg, "drv", colour = "class") +``` +### Non-standard evaluation + If the column name or expression is supplied by the user, you can also pass it to `aes()` or `vars()` using `{{ col }}`. This tidy eval operator captures the expression supplied by the user and forwards it to another tidy eval-enabled function such as `aes()` or `vars()`. ```{r} @@ -114,6 +140,8 @@ col_summary <- function(df, col, by) { col_summary(mpg, drv, year) ``` +### Summary + To summarise: - If you know the mapping or facet specification is `col` in advance, use `aes(.data$col)` or `vars(.data$col)`.