Add Text Annotations to ggplot2 Faceted Plot


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", "am", "gear")] <- lapply(mtcars[, c("cyl", "am", "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", "am", "gear")] <- lapply(mtcars[, c("cyl", "am", "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’re 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 the 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.

About these ads

About tylerrinker

I am Literacy PhD student with a bent for the quantitative and a passion for R.
This entry was posted in annotate, ggplot2 and tagged , , , , , , . Bookmark the permalink.

11 Responses to Add Text Annotations to ggplot2 Faceted Plot

  1. Luca Fenu says:

    Great post, thank you for sharing.

    I’ll keep it in mind in case I need to label faceted plots…

  2. tylerrinker says:

    Thanks for the feedback Luca :)

  3. Andrew says:

    I found i needed to enclose the mtcars$am with as.factor to get it to work:

    len <- length(levels(mtcars$gear)) * length(levels(as.factor(mtcars$am)))
    vars <- data.frame(expand.grid(levels(mtcars$gear), levels(as.factor(mtcars$am)))

    I am on R2.15.1 so not sure what everyone's thoughts on this were.

  4. tylerrinker says:

    @Andrew Thanks for the feedback. You are correct, I made a last minute switch that I didn’t transfer in the code. My apologies. The very first line I changed to am and not vs but didn’t change that in the blog post. It’s updated and should run without wrapping in as.factor.

    • Andrew says:

      thanks for the confirm. Great example – I have been looking for something like this for a while now, but was a bit lazy on experimenting with the geom_text function.

  5. Pingback: Add Text Annotations to ggplot2 Faceted Plot (an easier approach) | TRinker's R Blog

  6. Justin says:

    Nice workaround! Individually annotating facets is such a pain.

  7. Excellent tutorial. I like the detailed walk-through. I’m new to ggplot2, so this was great. Just wish I’d found it yesterday :)

  8. singlecoated says:

    This is, basically, superb. You saved me several hours and no less headaches. Thanks for sharing !

  9. I’ve been looking for something like this for days! Thank you so much :)

  10. Justine M says:

    Thank you! Very clear instructions – worked a treat!

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s