Add Text Annotations to ggplot2 Faceted Plot

August 31, 2012
By

(This article was first published on TRinker's R Blog » R, and kindly contributed to R-bloggers)


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) 

final


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                                                                     

initial
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)  

second

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) 

third
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)  

final

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 his blog: TRinker's R Blog » R.

R-bloggers.com offers daily e-mail updates about R news and tutorials on topics such as: visualization (ggplot2, Boxplots, maps, animation), programming (RStudio, Sweave, LaTeX, SQL, Eclipse, git, hadoop, Web Scraping) statistics (regression, PCA, time series, trading) and more...



If you got this far, why not subscribe for updates from the site? Choose your flavor: e-mail, twitter, RSS, or facebook...

Tags: , , , , , , ,

Comments are closed.