|
| 1 | +#' Tailoring plots to particular data types |
| 2 | +#' |
| 3 | +#' @description |
| 4 | +#' There are three functions to make plotting particular data types easier: |
| 5 | +#' `autoplot()`, `autolayer()` and `fortify()`. These are S3 generics for which |
| 6 | +#' other packages can write methods to display classes of data. The three |
| 7 | +#' functions are complementary and allow different levels of customisation. |
| 8 | +#' Below we'll explore implementing this series of methods to automate plotting |
| 9 | +#' of some class. |
| 10 | +#' |
| 11 | +#' Let's suppose we are writing a packages that has a class called 'my_heatmap', |
| 12 | +#' that wraps a matrix and we'd like users to easily plot this heatmap. |
| 13 | +#' |
| 14 | +#' ```r |
| 15 | +#' my_heatmap <- function(...) { |
| 16 | +#' m <- matrix(...) |
| 17 | +#' class(m) <- c("my_heatmap", class(m)) |
| 18 | +#' m |
| 19 | +#' } |
| 20 | +#' |
| 21 | +#' my_data <- my_heatmap(volcano) |
| 22 | +#' ``` |
| 23 | +#' |
| 24 | +#' # Automatic data shaping |
| 25 | +#' |
| 26 | +#' One of the things we have to do is ensure that the data is shaped in the long |
| 27 | +#' format so that it is compatible with ggplot2. This is the job of the |
| 28 | +#' `fortify()` function. Because 'my_heatmap' wraps a matrix, we can let the |
| 29 | +#' fortify method 'melt' the matrix to a long format. If your data is already |
| 30 | +#' based on a long-format `<data.frame>`, you can skip implementing a |
| 31 | +#' `fortify()` method. |
| 32 | +#' |
| 33 | +#' ```r |
| 34 | +#' fortify.my_heatmap <- function(model, ...) { |
| 35 | +#' data.frame( |
| 36 | +#' row = as.vector(row(model)), |
| 37 | +#' col = as.vector(col(model)), |
| 38 | +#' value = as.vector(model) |
| 39 | +#' ) |
| 40 | +#' } |
| 41 | +#' |
| 42 | +#' fortify(my_data) |
| 43 | +#' ``` |
| 44 | +#' |
| 45 | +#' When you have implemented the `fortify()` method, it should be easier to |
| 46 | +#' construct a plot with the data than with the matrix. |
| 47 | +#' |
| 48 | +#' ```r |
| 49 | +#' ggplot(my_data, aes(x = col, y = row, fill = value)) + |
| 50 | +#' geom_raster() |
| 51 | +#' ``` |
| 52 | +#' |
| 53 | +#' # Automatic layers |
| 54 | +#' |
| 55 | +#' A next step in automating plotting of your data type is to write an |
| 56 | +#' `autolayer()` method. These are typically wrappers around geoms or stats |
| 57 | +#' that automatically set aesthetics or other parameters. If you haven't |
| 58 | +#' implemented a `fortify()` method for your data type, you might have to |
| 59 | +#' reshape the data in `autolayer()`. |
| 60 | +#' |
| 61 | +#' If you require multiple layers to display your data type, you can use an |
| 62 | +#' `autolayer()` method that constructs a list of layers, which can be added |
| 63 | +#' to a plot. |
| 64 | +#' |
| 65 | +#' ```r |
| 66 | +#' autolayer.my_heatmap <- function(object, ...) { |
| 67 | +#' geom_raster( |
| 68 | +#' mapping = aes(x = col, y = row, fill = value), |
| 69 | +#' data = object, |
| 70 | +#' ..., |
| 71 | +#' inherit.aes = FALSE |
| 72 | +#' ) |
| 73 | +#' } |
| 74 | +#' |
| 75 | +#' ggplot() + autolayer(my_data) |
| 76 | +#' ``` |
| 77 | +#' |
| 78 | +#' As a quick tip: if you define a mapping in `autolayer()`, you might want |
| 79 | +#' to set `inherit.aes = FALSE` to not have aesthetics set in other layers |
| 80 | +#' interfere with your layer. |
| 81 | +#' |
| 82 | +#' # Automatic plots |
| 83 | +#' |
| 84 | +#' The last step in automating plotting is to write an `autoplot()` method |
| 85 | +#' for your data type. The expectation is that these return a complete plot. |
| 86 | +#' In the example below, we're exploiting the `autolayer()` method that we |
| 87 | +#' have already written to make a complete plot. |
| 88 | +#' |
| 89 | +#' ```r |
| 90 | +#' autoplot.my_heatmap <- function(object, ..., option = "magma") { |
| 91 | +#' ggplot() + |
| 92 | +#' autolayer(my_data) + |
| 93 | +#' scale_fill_viridis_c(option = option) + |
| 94 | +#' theme_void() |
| 95 | +#' } |
| 96 | +#' |
| 97 | +#' autoplot(my_data) |
| 98 | +#' ``` |
| 99 | +#' |
| 100 | +#' If you don't have a wish to implement a base R plotting method, you |
| 101 | +#' can set the plot method for your class to the autoplot method. |
| 102 | +#' |
| 103 | +#' ```r |
| 104 | +#' plot.my_heatmap <- autoplot.my_heatmap |
| 105 | +#' plot(my_data) |
| 106 | +#' ``` |
| 107 | +#' |
| 108 | +#' @family plotting automation topics |
| 109 | +#' |
| 110 | +#' @name automatic_plotting |
| 111 | +NULL |
| 112 | + |
1 | 113 | #' Create a complete ggplot appropriate to a particular data type
|
2 | 114 | #'
|
3 | 115 | #' `autoplot()` uses ggplot2 to draw a particular plot for an object of a
|
|
8 | 120 | #' @param ... other arguments passed to specific methods
|
9 | 121 | #' @return a ggplot object
|
10 | 122 | #' @export
|
11 |
| -#' @seealso [autolayer()], [ggplot()] and [fortify()] |
| 123 | +#' @family plotting automation topics |
12 | 124 | autoplot <- function(object, ...) {
|
13 | 125 | UseMethod("autoplot")
|
14 | 126 | }
|
|
0 commit comments