20.5 New scales

There are three ways one might want to extend ggplot2 with new scales. The simplest is the case where you would like to provide a convenient wrapper for a new palette to an existing scale (this would often mean a new color/fill palette). For this case it will be sufficient to provide a new scale constructor that passes the relevant palette into the relevant basic scale constructor. This is used throughout ggplot2 itself as in e.g. the viridis scale:

#> function (..., alpha = 1, begin = 0, end = 1, direction = 1, 
#>     option = "D", values = NULL, space = "Lab", na.value = "grey50", 
#>     guide = "colourbar", aesthetics = "fill") 
#> {
#>     continuous_scale(aesthetics, "viridis_c", gradient_n_pal(viridis_pal(alpha, 
#>         begin, end, direction, option)(6), values, space), na.value = na.value, 
#>         guide = guide, ...)
#> }
#> <bytecode: 0x5584873fdcc8>
#> <environment: namespace:ggplot2>

Another relatively simple case is where you provide a geom that takes a new type of aesthetic that needs to be scaled. Let’s say that you created a new line geom, and instead of the size aesthetic you decided on using a width aesthetic. In order to get width scaled in the same way as you’ve come to expect scaling of size you must provide a default scale for the aesthetic. Default scales are found based on their name and the data type provided to the aesthetic. If you assign continuous values to the width aesthetic ggplot2 will look for a scale_width_continuous() function and use this if no other width scale has been added to the plot. If such a function is not found (and no width scale was added explicitly), the aesthetic will not be scaled.

A last possibility worth mentioning, but outside the scope of this book, is the possibility of creating a new primary scale type. ggplot2 has historically had two primary scales: Continuous and discrete. Recently the binned scale type joined which allows for binning of continuous data into discrete bins. It is possible to develop further primary scales, by following the example of ScaleBinned. It requires subclassing Scale or one of the provided primary scales, and create new train() and map() methods, among others.