Site icon R-bloggers

Add Text Annotations to ggplot2 Faceted Plot

[This article was first published on TRinker's R Blog » R, and kindly contributed to R-bloggers]. (You can report issue about the content on this page here)
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.

In my experience with R learners there are two basic types. The “show me the code and what it does and let me play” type and the “please give me step by step directions” type. I’ve broken the following tutorial on plotting text on faceted ggplot2 plots into 2 sections:
  1. The Complete Code and Final Outcome
  2. A Bit of Explanation

Hopefully, whatever learner you are you’ll be plotting text on faceted graphics in no time.


Section 1: The Complete Code and Final Outcome

mtcars[, c("cyl", "vs", "gear")] <- lapply(mtcars[, c("cyl", "vs", "gear")], as.factor)

p <- ggplot(mtcars, aes(mpg, wt, group = cyl)) + 
    geom_line(aes(color=cyl)) +
    geom_point(aes(shape=cyl)) + 
    facet_grid(gear ~ am) +
    theme_bw()                                                                      
p                                                                     
 

len <- length(levels(mtcars$gear)) *  length(levels(mtcars$am))

vars <- data.frame(expand.grid(levels(mtcars$gear), levels(mtcars$am)))
colnames(vars) <- c("gear", "am")
dat <- data.frame(x = rep(15, len), y = rep(5, len), vars, labs=LETTERS[1:len])

p + geom_text(aes(x, y, label=labs, group=NULL),data=dat) 


dat[1, 1:2] <- c(30, 2)   #to change specific locations
p + geom_text(aes(x, y, label=labs, group=NULL), data=dat) 


p + geom_text(aes(x, y, label=paste("beta ==", labs), group=NULL), size = 4, 
    color = "grey50", data=dat, parse = T) 


Section 2: A Bit of Explanation

The following portion of the tutorial provides a bit more of a step by step procedure for plotting text to faceted plots as well as a visual to go with the code.

The initial non annotated plot
First Let’s make a faceted line plot with the mtcars data set. I reclassed a few variables to make factors.

mtcars[, c("cyl", "vs", "gear")] <- lapply(mtcars[, c("cyl", "vs", "gear")], as.factor)

p <- ggplot(mtcars, aes(mpg, wt, group = cyl)) + 
    geom_line(aes(color=cyl)) +
    geom_point(aes(shape=cyl)) + 
    facet_grid(gear ~ am) +
    theme_bw()                                                                      
p                                                                     


Add text to each facet
The key here is a new data frame with three pieces of information (ggplot2 seems to like information given in a data frame).

  1. Coordinates to plot the text
  2. The faceted variable levels
  3. The labels to be supplied

The first information piece is the coordinates (two columns x and y) to plot the text in each facet. Generally I find that one set of coordinates will work in most of the facet boxes and I just use rep to make these coordinates (I suppose the recycling rule could be used if you added it to an already existing data frame).

The second information piece is the faceted variable labels (in our case gear ~ am). There’s many ways to achieve this but I like a combination of levels and expand.grid. I renamed these columns to be exactly the same as the variable names (gear & am) I used in the original data frame (mtcars in this case).

Lastly, you must make a labels. I chose letters so you can track what piece of the data frame is plotted in which facet.

Your data should look something like this:

   x y gear am labs
1 30 2    3  0    A
2 15 5    4  0    B
3 15 5    5  0    C
4 15 5    3  1    D
5 15 5    4  1    E
6 15 5    5  1    F

Note that the , group=NULL is essential to let ggplot2 know you’re dealing with a new data set and the mapping from before can be forgotten (or at least this is how I understand it).

#long cut way to find number of facets
len <- length(levels(mtcars$gear)) *  length(levels(mtcars$am))

vars <- data.frame(expand.grid(levels(mtcars$gear), levels(mtcars$am)))
colnames(vars) <- c("gear", "am")
dat <- data.frame(x = rep(15, len), y = rep(5, len), vars, labs=LETTERS[1:len])

p + geom_text(aes(x, y, label=labs, group=NULL),data=dat)  

Moving just one text location
Generally I can usually find one spot that most every text plot will work except that one dog gone facet that just won’t match up with the other coordinates. In this case label A is that pesky label. The key here is to figure out what text labels you want to move and alter those coordinates appropriately.

dat[1, 1:2] <- c(30, 2)   #to change specific locations
p + geom_text(aes(x, y, label=labs, group=NULL), data=dat) 


Adding equation (Greek letters/math) and alter size/color
To annotate with math code use the parse = T argument in geom_text. For more on plotting math code see this ggplot wiki and this SO question. To alter the size just throw a size argument in geom_text. I also toned down the color of the text a bit to allow the line to pop the most visually.

p + geom_text(aes(x, y, label=paste("beta ==", labs), group=NULL), size = 4, 
    color = "grey50", data=dat, parse = T)  

If you have suggestions for improvement, links, or other thoughts please leave a comment.


To leave a comment for the author, please follow the link and comment on their blog: TRinker's R Blog » R.

R-bloggers.com offers daily e-mail updates about R news and tutorials about learning R and many other topics. Click here if you're looking to post or find an R/data-science job.
Want to share your content on R-bloggers? click here if you have a blog, or here if you don't.