Creating publication quality graphics
Table of Contents
Plotting our data is one of the best ways to quickly explore it and the various relationships between variables.
There are three main plotting systems in R, the base plotting system, the lattice package, and the ggplot2 package.
Today we'll be learning about the ggplot2 package, because it is the most effective for creating publication quality graphics.
ggplot2 is built on the grammar of graphics, the idea that any plot can be expressed from the same set of components: a data set, a coordinate system, and a set of geoms--the visual representation of data points.
The key to understanding ggplot2 is thinking about a figure in layers: just like you might do in an image editing program like Photoshop, Illustrator, or Inkscape.
Let's start off with an example:
library("ggplot2")
ggplot(data = titanic, aes(x = Age, y = Fare)) +
geom_point()
So the first thing we do is call the ggplot
function. This function lets R
know that we're creating a new plot, and any of the arguments we give the
ggplot
function are the global options for the plot: they apply to all
layers on the plot.
We've passed in two arguments to ggplot
. First, we tell ggplot
what data we
want to show on our figure, in this example the titanic data we read in
earlier. For the second argument we passed in the aes
function, which
tells ggplot
how variables in the data map to aesthetic properties of
the figure, in this case the x and y locations. Here we told ggplot
we
want to plot the "Age" column of the titanic data frame on the x-axis, and
the "Fare" column on the y-axis. Notice that we didn't need to explicitly
pass aes
these columns (e.g. x = titanic[, "Age"]
), this is because
ggplot
is smart enough to know to look in the data for that column!
By itself, the call to ggplot
isn't enough to draw a figure:
ggplot(titanic,aes(x = Age, y = Fare))
We need to tell ggplot
how we want to visually represent the data, which we
do by adding a new geom layer. In our example, we used geom_point
, which
tells ggplot
we want to visually represent the relationship between x and
y as a scatterplot of points:
ggplot(titanic,aes(x = Age, y = Fare)) +
geom_point()
In the previous examples and challenge we've used the aes
function to tell the scatterplot geom about the x and y locations of each point.
Another aesthetic property we can modify is the point color. Modify the
code from the previous challenge to color the points by the "Survived"
column.
HINT: transform the Survived column to a factor using the as.factor()
function.
What trends do you see in the data? Are they what you expected?
Layers
We could also make a line plot.
Instead, let's tell ggplot
to visualise the data as a line plot:
ggplot(titanic, aes(x = Age, y = Fare, col = as.factor(Pclass)))+
geom_line()
Instead of adding a geom_point
layer, we've added a geom_line
layer.
But what if we want to visualise both lines and points on the plot? We can simply add another layer to the plot:
ggplot(titanic, aes(x = Age, y = Fare, col = as.factor(Pclass)))+
geom_point() + geom_line()
It's important to note that each layer is drawn on top of the previous layer. In this example, the points have been drawn on top of the lines. Here's a demonstration:
ggplot(titanic, aes(x = Age, y = Fare ))+
geom_point() + geom_line(aes(col = as.factor(Pclass)))
In this example, the aesthetic mapping of color has been moved from the
global plot options in ggplot
to the geom_line
layer so it no longer applies
to the points. Now we can clearly see that the points are drawn on top of the
lines.
Transformations and statistics
Ggplot also makes it easy to overlay statistical models over the data. To demonstrate we'll go back to our first example:
ggplot(titanic, aes(x = Age, y = Fare, col = as.factor(Pclass)))+
geom_point()
We can fit a simple relationship to the data by adding another layer,
geom_smooth
:
ggplot(titanic, aes(x = Age, y = Fare, col = as.factor(Pclass)))+
geom_point() + geom_smooth(method = "lm")
We can make the line thicker by setting the size and se aesthetic in the
geom_smooth
layer. We can change the scale of units on the y axis using the scale functions. These control the mapping between the data values and visual values of an aesthetic.
ggplot(titanic, aes(x = Age, y = Fare, col = as.factor(Pclass)))+
geom_point() + geom_smooth(method = "lm", size =1.5, se = F) + scale_y_log10()
There are two ways an aesthetic can be specified. Here we set the size
aesthetic by passing it as an argument to geom_smooth
. Previously in the
lesson we've used the aes
function to define a mapping between data
variables and their visual representation.
Multi-panel figures
Earlier we visualised the change in Fare across Age levels in one plot. Alternatively, we can split out different groups in the data into multiple panels by adding a layer of facet panels:
ggplot(titanic, aes(x = Sex, fill=as.factor(Survived))) +
geom_bar(position = 'dodge')
ggplot(titanic, aes(x = Sex, fill=as.factor(Survived))) +
geom_bar(position = 'dodge') +
facet_grid(~ Pclass)
The facet_grid
layer took a "formula" as its argument, denoted by the tilde
(~). This tells R to draw a panel for each unique value in the Pclass column
of the titanic dataset.
Modifying text
To clean this figure up for a publication we need to change some of the text elements.
We can do this by adding a couple of different layers. The theme layer controls the axis text, and overall text size, and there are special layers for changing the axis labels. To change the legend title, we need to use the scales layer.
ggplot(titanic, aes(x = Sex, fill=as.factor(Survived))) +
geom_bar(position = 'dodge') +
facet_grid(~ Pclass, labeller = labeller(Pclass = c(`1` = "first class",
`2` = "second class",
`3` = "third class"))) +
xlab("gender") + ggtitle("Figure 1") +
scale_fill_discrete(name="survival", label=c("died", "survived")) +
theme_bw() + theme(panel.grid = element_blank())
This is just a taste of what you can do with ggplot2
. RStudio provides a
really useful cheat sheet of the different layers available, and more
extensive documentation is available on the ggplot2 website.
Finally, if you have no idea how to change something, a quick google search will
usually send you to a relevant question and answer on Stack Overflow with reusable
code to modify!