Chapter 19 Internals of ggplot2
Learning Objectives
- What is the difference between user-facing code and internal code?
- What is the distinction between
ggplot_build()
andggplot_gtable()
? - What the division of labor between
{ggplot2}
and{grid}
? - What is the basic structure of/motivation for ggproto?
library(ggplot2)
library(ggtrace) # remotes::install_github("yjunechoe/ggtrace")
library(purrr)
library(dplyr)
19.0.0.1 Introduction (the existence of internals)
The user-facing code that defines a ggplot on the surface is not the same as the internal code that creates a ggplot under the hood. In this chapter, we’ll learn about how the internal code operates and develop some intuitions about thinking about the internals, starting with these two simple examples of mismatches between surface and underlying form:
19.0.0.2 Case 1: Order
You can change the order of some “layers” without change to the graphical output.
For example, scale_*()
can be added anywhere and always ends up applying for the whole plot:
ggplot(mtcars, aes(mpg, hp, color = as.factor(am))) +
scale_x_log10() + #< scale first
geom_point() +
geom_smooth()
ggplot(mtcars, aes(mpg, hp, color = as.factor(am))) +
geom_point() +
scale_x_log10() + #< scale middle
geom_smooth()
Though the order of geom_*()
and stat_*()
matters for order of drawing:
19.0.0.3 Case 2: Modularity
We know that user-facing “layer” code that we add to a ggplot with +
are stand-alone functions:
geom_smooth: na.rm = FALSE, orientation = NA, se = TRUE
stat_smooth: na.rm = FALSE, orientation = NA, se = TRUE, method = lm, formula = y ~ x
position_identity
When we add this object to different ggplots, it materializes in different ways: