|
1 | 1 | #' Control aesthetic evaluation
|
2 | 2 | #'
|
3 |
| -#' Most aesthetics are mapped from variables found in the data. Sometimes, |
4 |
| -#' however, you want to delay the mapping until later in the rendering process. |
5 |
| -#' ggplot2 has three stages of the data that you can map aesthetics from. The |
6 |
| -#' default is to map at the beginning, using the layer data provided by the |
7 |
| -#' user. The second stage is after the data has been transformed by the layer |
8 |
| -#' stat. The third and last stage is after the data has been transformed and |
9 |
| -#' mapped by the plot scales. The most common example of mapping from stat |
10 |
| -#' transformed data is the height of bars in [geom_histogram()]: |
11 |
| -#' the height does not come from a variable in the underlying data, but |
12 |
| -#' is instead mapped to the `count` computed by [stat_bin()]. An example of |
13 |
| -#' mapping from scaled data could be to use a desaturated version of the stroke |
14 |
| -#' colour for fill. If you want to map directly from the layer data you should |
15 |
| -#' not do anything special. In order to map from stat transformed data you |
| 3 | +#' @description |
| 4 | +#' Most [aesthetics][aes()] are mapped from variables found in the data. |
| 5 | +#' Sometimes, however, you want to delay the mapping until later in the |
| 6 | +#' rendering process. ggplot2 has three stages of the data that you can map |
| 7 | +#' aesthetics from, and three functions to control at which stage aesthetics |
| 8 | +#' should be evaluated. |
| 9 | +#' |
| 10 | +#' @description |
| 11 | +#' `after_stat()` replaces the old approaches of using either `stat()`, e.g. |
| 12 | +#' `stat(density)`, or surrounding the variable names with `..`, e.g. |
| 13 | +#' `..density..`. |
| 14 | +#' |
| 15 | +#' @usage |
| 16 | +#' # These functions can be used inside the `aes()` function |
| 17 | +#' # used as the `mapping` argument in layers, for example: |
| 18 | +#' # geom_density(mapping = aes(y = after_stat(scaled))) |
| 19 | +#' |
| 20 | +#' @param x <[`data-masking`][rlang::topic-data-mask]> An aesthetic expression |
| 21 | +#' using variables calculated by the stat (`after_stat()`) or layer aesthetics |
| 22 | +#' (`after_scale()`). |
| 23 | +#' @param start <[`data-masking`][rlang::topic-data-mask]> An aesthetic |
| 24 | +#' expression using variables from the layer data. |
| 25 | +#' @param after_stat <[`data-masking`][rlang::topic-data-mask]> An aesthetic |
| 26 | +#' expression using variables calculated by the stat. |
| 27 | +#' @param after_scale <[`data-masking`][rlang::topic-data-mask]> An aesthetic |
| 28 | +#' expression using layer aesthetics. |
| 29 | +#' |
| 30 | +#' @details |
| 31 | +#' # Staging |
| 32 | +#' Below follows an overview of the three stages of evaluation and how aesthetic |
| 33 | +#' evaluation can be controlled. |
| 34 | +#' |
| 35 | +#' ## Stage 1: direct input |
| 36 | +#' The default is to map at the beginning, using the layer data provided by |
| 37 | +#' the user. If you want to map directly from the layer data you should not do |
| 38 | +#' anything special. This is the only stage where the original layer data can |
| 39 | +#' be accessed. |
| 40 | +#' |
| 41 | +#' ```r |
| 42 | +#' # 'x' and 'y' are mapped directly |
| 43 | +#' ggplot(mtcars) + geom_point(aes(x = mpg, y = disp)) |
| 44 | +#' ``` |
| 45 | +#' |
| 46 | +#' ## Stage 2: after stat transformation |
| 47 | +#' The second stage is after the data has been transformed by the layer |
| 48 | +#' stat. The most common example of mapping from stat transformed data is the |
| 49 | +#' height of bars in [geom_histogram()]: the height does not come from a |
| 50 | +#' variable in the underlying data, but is instead mapped to the `count` |
| 51 | +#' computed by [stat_bin()]. In order to map from stat transformed data you |
16 | 52 | #' should use the `after_stat()` function to flag that evaluation of the
|
17 | 53 | #' aesthetic mapping should be postponed until after stat transformation.
|
18 |
| -#' Similarly, you should use `after_scale()` to flag evaluation of mapping for |
19 |
| -#' after data has been scaled. If you want to map the same aesthetic multiple |
20 |
| -#' times, e.g. map `x` to a data column for the stat, but remap it for the geom, |
21 |
| -#' you can use the `stage()` function to collect multiple mappings. |
22 |
| -#' |
23 |
| -#' `after_stat()` replaces the old approaches of using either `stat()` or |
24 |
| -#' surrounding the variable names with `..`. |
25 |
| -#' |
26 |
| -#' @note Evaluation after stat transformation will have access to the |
27 |
| -#' variables calculated by the stat, not the original mapped values. Evaluation |
28 |
| -#' after scaling will only have access to the final aesthetics of the layer |
29 |
| -#' (including non-mapped, default aesthetics). The original layer data can only |
30 |
| -#' be accessed at the first stage. |
31 |
| -#' |
32 |
| -#' @param x An aesthetic expression using variables calculated by the stat |
33 |
| -#' (`after_stat()`) or layer aesthetics (`after_scale()`). |
34 |
| -#' @param start An aesthetic expression using variables from the layer data. |
35 |
| -#' @param after_stat An aesthetic expression using variables calculated by the |
36 |
| -#' stat. |
37 |
| -#' @param after_scale An aesthetic expression using layer aesthetics. |
| 54 | +#' Evaluation after stat transformation will have access to the variables |
| 55 | +#' calculated by the stat, not the original mapped values. The 'computed |
| 56 | +#' variables' section in each stat lists which variables are available to |
| 57 | +#' access. |
| 58 | +#' |
| 59 | +#' ```r |
| 60 | +#' # The 'y' values for the histogram are computed by the stat |
| 61 | +#' ggplot(faithful, aes(x = waiting)) + |
| 62 | +#' geom_histogram() |
| 63 | +#' |
| 64 | +#' # Choosing a different computed variable to display, matching up the |
| 65 | +#' # histogram with the density plot |
| 66 | +#' ggplot(faithful, aes(x = waiting)) + |
| 67 | +#' geom_histogram(aes(y = after_stat(density))) + |
| 68 | +#' geom_density() |
| 69 | +#' ``` |
| 70 | +#' |
| 71 | +#' ## Stage 3: after scale transformation |
| 72 | +#' The third and last stage is after the data has been transformed and |
| 73 | +#' mapped by the plot scales. An example of mapping from scaled data could |
| 74 | +#' be to use a desaturated version of the stroke colour for fill. You should |
| 75 | +#' use `after_scale()` to flag evaluation of mapping for after data has been |
| 76 | +#' scaled. Evaluation after scaling will only have access to the final |
| 77 | +#' aesthetics of the layer (including non-mapped, default aesthetics). |
| 78 | +#' |
| 79 | +#' ```r |
| 80 | +#' # The exact colour is known after scale transformation |
| 81 | +#' ggplot(mpg, aes(cty, colour = factor(cyl))) + |
| 82 | +#' geom_density() |
38 | 83 | #'
|
| 84 | +#' # We re-use colour properties for the fill without a separate fill scale |
| 85 | +#' ggplot(mpg, aes(cty, colour = factor(cyl))) + |
| 86 | +#' geom_density(aes(fill = after_scale(alpha(colour, 0.3)))) |
| 87 | +#' ``` |
| 88 | +#' |
| 89 | +#' ## Complex staging |
| 90 | +#' If you want to map the same aesthetic multiple times, e.g. map `x` to a |
| 91 | +#' data column for the stat, but remap it for the geom, you can use the |
| 92 | +#' `stage()` function to collect multiple mappings. |
| 93 | +#' |
| 94 | +#' ```r |
| 95 | +#' # Use stage to modify the scaled fill |
| 96 | +#' ggplot(mpg, aes(class, hwy)) + |
| 97 | +#' geom_boxplot(aes(fill = stage(class, after_scale = alpha(fill, 0.4)))) |
| 98 | +#' |
| 99 | +#' # Using data for computing summary, but placing label elsewhere. |
| 100 | +#' # Also, we're making our own computed variable to use for the label. |
| 101 | +#' ggplot(mpg, aes(class, displ)) + |
| 102 | +#' geom_violin() + |
| 103 | +#' stat_summary( |
| 104 | +#' aes( |
| 105 | +#' y = stage(displ, after_stat = 8), |
| 106 | +#' label = after_stat(paste(mean, "±", sd)) |
| 107 | +#' ), |
| 108 | +#' geom = "text", |
| 109 | +#' fun.data = ~ round(data.frame(mean = mean(.x), sd = sd(.x)), 2) |
| 110 | +#' ) |
| 111 | +#' ``` |
39 | 112 | #' @rdname aes_eval
|
40 | 113 | #' @name aes_eval
|
41 | 114 | #'
|
|
55 | 128 | #' # Use stage to modify the scaled fill
|
56 | 129 | #' ggplot(mpg, aes(class, hwy)) +
|
57 | 130 | #' geom_boxplot(aes(fill = stage(class, after_scale = alpha(fill, 0.4))))
|
| 131 | +#' |
| 132 | +#' # Making a proportional stacked density plot |
| 133 | +#' ggplot(mpg, aes(cty)) + |
| 134 | +#' geom_density( |
| 135 | +#' aes( |
| 136 | +#' colour = factor(cyl), |
| 137 | +#' fill = after_scale(alpha(colour, 0.3)), |
| 138 | +#' y = after_stat(count / sum(n[!duplicated(group)])) |
| 139 | +#' ), |
| 140 | +#' position = "stack", bw = 1 |
| 141 | +#' ) + |
| 142 | +#' geom_density(bw = 1) |
| 143 | +#' |
| 144 | +#' # Imitating a ridgeline plot |
| 145 | +#' ggplot(mpg, aes(cty, colour = factor(cyl))) + |
| 146 | +#' geom_ribbon( |
| 147 | +#' stat = "density", outline.type = "upper", |
| 148 | +#' aes( |
| 149 | +#' fill = after_scale(alpha(colour, 0.3)), |
| 150 | +#' ymin = after_stat(group), |
| 151 | +#' ymax = after_stat(group + ndensity) |
| 152 | +#' ) |
| 153 | +#' ) |
| 154 | +#' |
| 155 | +#' # Labelling a bar plot |
| 156 | +#' ggplot(mpg, aes(class)) + |
| 157 | +#' geom_bar() + |
| 158 | +#' geom_text( |
| 159 | +#' aes( |
| 160 | +#' y = after_stat(count + 2), |
| 161 | +#' label = after_stat(count) |
| 162 | +#' ), |
| 163 | +#' stat = "count" |
| 164 | +#' ) |
| 165 | +#' |
| 166 | +#' # Labelling the upper hinge of a boxplot, |
| 167 | +#' # inspired by June Choe |
| 168 | +#' ggplot(mpg, aes(displ, class)) + |
| 169 | +#' geom_boxplot(outlier.shape = NA) + |
| 170 | +#' geom_text( |
| 171 | +#' aes( |
| 172 | +#' label = after_stat(xmax), |
| 173 | +#' x = stage(displ, after_stat = xmax) |
| 174 | +#' ), |
| 175 | +#' stat = "boxplot", hjust = -0.5 |
| 176 | +#' ) |
58 | 177 | NULL
|
59 | 178 |
|
60 | 179 | #' @rdname aes_eval
|
|
0 commit comments