You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: vignettes/ggplot2-in-packages.Rmd
+41-47Lines changed: 41 additions & 47 deletions
Original file line number
Diff line number
Diff line change
@@ -16,7 +16,7 @@ This vignette is intended for package developers who use ggplot2 within their pa
16
16
17
17
## Referring to ggplot2 functions
18
18
19
-
As with any function from another package, you will have to list ggplot2 in your `DESCRIPTION` under `Imports`or `Suggests`and refer to its functions using `::` (e.g., `ggplot2::function_name`).
19
+
As with any function from another package, you will have to list ggplot2 in your `DESCRIPTION` under `Imports` and refer to its functions using `::` (e.g., `ggplot2::function_name`):
20
20
21
21
```{r}
22
22
mpg_drv_summary <- function() {
@@ -31,7 +31,7 @@ mpg_drv_summary <- function() {
31
31
mpg_drv_summary()
32
32
```
33
33
34
-
If you use ggplot2 functions frequently, you may wish to import one or more functions from ggplot2 into your `NAMESPACE`. If you use [roxygen2](https://cran.r-project.org/package=roxygen2), you can include `#' @importFrom ggplot2 <one or more function names>` in any roxygen comment block (this will not work for datasets like `mpg`). If you do this, you will need to put ggplot2 in your `Imports` rather than your `Suggests`.
34
+
If you use ggplot2 functions frequently, you may wish to import one or more functions from ggplot2 into your `NAMESPACE`. If you use [roxygen2](https://cran.r-project.org/package=roxygen2), you can include `#' @importFrom ggplot2 <one or more function names>` in any roxygen comment block (this will not work for datasets like `mpg`).
If you use infix operators from ggplot2 like `%+replace%` and you want to keep ggplot2 in `Suggests`, you can assign the operator within the function before it is used.
Even if you use many ggplot2 functions in your package, it is unwise to use ggplot2 in `Depends` or import the entire package into your `NAMESPACE`. Using ggplot2 in `Depends` will attach ggplot2 when your package is attached, which includes when your package is tested. This makes it difficult to ensure that others can use the functions in your package without attaching it (i.e., using `::`). Similarly, importing all 450 of ggplot2's exported objects into your namespace makes it difficult to separate the responsibility of your package and the responsibility of ggplot2, in addition to making it difficult for readers of your code to figure out where functions are coming from!
81
51
82
52
## Using `aes()` and `vars()` in a package function
@@ -99,6 +69,12 @@ N checking R code for possible problems (2.7s)
99
69
drv
100
70
```
101
71
72
+
There are three situations in which you will encounter this problem:
73
+
74
+
- You already know the column name or expression in advance.
75
+
- You have the column name as a character vector.
76
+
- 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()`.
77
+
102
78
If you already know the mapping in advance (like the above example) you should use the `.data` pronoun from [rlang](https://cran.r-project.org/package=rlang) to make it explicit that you are referring to the `drv` in the data and not some other variable named `drv` (which may or may not exist elsewhere).
If the user specifies a part of the mapping, you can either specify this as a column name (e.g., `col = "drv"`) or using the same kind of non-standard evaluation used by `aes()` and `vars()` (e.g., `col = drv`). In the first case, use `.data[[col]]`:
89
+
If you have the column name as a character vector (e.g., `col = "drv"`), use `.data[[col]]`:
To use the same kind of non-standard evaluation that `aes()`uses, use `{{ col }}` to pass the unevaluated expression the user typed in `col` to `aes()`.
102
+
To use the same kind of non-standard evaluation used by `aes()`and `vars()`, use `{{ col }}` to pass the unevaluated expression the user typed in `col` to `aes()`.
127
103
128
104
<!-- this uses development rlang, which is not yet released -->
To summarise, if you know the mapping or facet specification is `col` in advance, use `aes(.data$col)` or `vars(.data$col)`. If `col` is a variable that contains the column name as a character scalar, use `aes(.data[[col]]` or `vars(.data[[col]])`. If you would like the behaviour of `col` to look and feel like `aes()` and `vars()`, use `aes({{ col }})` or `vars({{ col }})`.
116
+
To summarise, if you know the mapping or facet specification is `col` in advance, use `aes(.data$col)` or `vars(.data$col)`. If `col` is a variable that contains the column name as a character scalar, use `aes(.data[[col]]` or `vars(.data[[col]])`. If you would like the behaviour of `col` to look and feel like `aes()` and `vars()`, use `aes({{ col }})` or `vars({{ col }})`.
141
117
142
-
You will see a lot of other ways to do this in the wild, but the syntax we use here is the only one we can guarantee will work in the future! In particular, don't use `aes_()` or `aes_string()`, as they are deprecated and may be removed in a future version. Finally, don't skip the step of creating a data frame and a mapping to pass in to `ggplot()` or its layers! You will see other ways of doing this in the wild, but these rely on undocumented behaviour and can fail in unexpected ways.
118
+
You will see a lot of other ways to do this in the wild, but the syntax we use here is the only one we can guarantee will work in the future! In particular, don't use `aes_()` or `aes_string()`, as they are deprecated and may be removed in a future version. Finally, don't skip the step of creating a data frame and a mapping to pass in to `ggplot()` or its layers! You will see other ways of doing this in the wild, but these may rely on undocumented behaviour and can fail in unexpected ways.
If you don't use ggplot2 for your visualizations but would like to implement `autoplot()` for users that do, it is possible to register your generics only if ggplot2 is installed using `vctrs::s3_register()`.
198
-
199
-
```{r, eval=FALSE}
200
-
.onLoad <- function(...) {
201
-
if (requireNamespace("ggplot2", quietly = TRUE)) {
It is considered bad practice to implement an S3 generic like `plot()`, or `autoplot()` if you don't have any control over the S3 object, as it makes it hard for the package developer who does have control over the S3 to implement the method themselves. This shouldn't stop you from creating your own functions to visualize these objects!
173
+
It is considered bad practice to implement an S3 generic like `plot()`, or `autoplot()` if you don't own the S3 object, as it makes it hard for the package developer who does have control over the S3 to implement the method themselves. This shouldn't stop you from creating your own functions to visualize these objects!
208
174
209
175
### Creating a new theme
210
176
@@ -245,3 +211,31 @@ test_that("output of ggplot() is stable", {
If you use ggplot2 in your package, most likely you will want to list it under `Imports`. If you would like to list ggplot2 in `Suggests` instead, you will not be able to `#' @importFrom ggplot2 ...` (i.e., you must refer to ggplot2 objects using `::`). If you use infix operators from ggplot2 like `%+replace%` and you want to keep ggplot2 in `Suggests`, you can assign the operator within the function before it is used:
Generally, if you add a method for a ggplot2 generic like `autoplot()`, ggplot2 should be in `Imports`. If for some reason you would like to keep ggplot2 in `Suggests`, it is possible to register your generics only if ggplot2 is installed using `vctrs::s3_register()`. If you do this, you should copy and paste the source of `vctrs::s3_register()` into your own package to avoid adding a [vctrs](https://cran.r-project.org/package=vctrs) dependency.
234
+
235
+
```{r, eval=FALSE}
236
+
.onLoad <- function(...) {
237
+
if (requireNamespace("ggplot2", quietly = TRUE)) {
0 commit comments