Add Text Annotations to ggplot2 Faceted Plot (an easier approach)

[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.

I recently posted a blog about adding text to a ggplot2 faceted plot (LINK).

I was unhappy with the amount of time it takes to create the text data frame to then label the plot. And then yesterday when the new version of ggplot2 0.9.2 was announced I got to reading about how ggplot2 objects are stored and I decided that I could extract a great deal of the information for plotting the text directly from the ggplot2 object.

After I did it I decided to wrap the function up into a package that I can add more ggplot2 extension functions to in the future.

install_github("acc.ggplot2", "trinker")

Here’s the code and a few examples:


qfacet_text <- function(ggplot2.object, x.coord = NULL, y.coord = NULL, 
    labels = NULL, ...) {
    dat <- ggplot2.object$data
    rows <- ggplot2.object$facet[[1]][[1]]
    cols <- ggplot2.object$facet[[2]][[1]]
    fcol <- dat[, as.character(cols)]
    frow <- dat[, as.character(rows)]
    len <- length(levels(fcol)) *  length(levels(frow))
    vars <- data.frame(expand.grid(levels(frow), levels(fcol)))
    colnames(vars) <- c(as.character(rows), as.character(cols))
    if (any(class(ggplot2.object) %in% c("ggplot", "gg"))) {
        if (is.null(labels)) {
            labels <- LETTERS[1:len]
        if (length(x.coord) == 1) {
           x.coord <- rep(x.coord, len)
        if (length(y.coord) == 1) {
           y.coord <- rep(y.coord, len)
        text.df <- data.frame(x = x.coord, y = y.coord, vars, labs=labels)
    } else {
        if (class(ggplot2.object) == "qfacet") {
            text.df <- ggplot2.object$dat
            if (!is.null(x.coord)) {
                text.df$x.coord <- x.coord
            if (!is.null(y.coord)) {
                text.df$y.coord <- y.coord
            if (!is.null(labels)) {
                text.df$labs <- labels
            ggplot2.object <- ggplot2.object$original
    p <- ggplot2.object + geom_text(aes(x, y, label=labs, group=NULL), 
        data=text.df, ...)
    v <- list(original = ggplot2.object, new = p, dat = text.df)
    class(v) <- "qfacet"

Examples (using the same basic examples as my previous blog post):

#alter mtcars to make some variables 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) +

z <- qfacet_text(ggplot2.object = p, x.coor = 33, y.coor = 2.2, labels = 1:6, color="red")
str(z); names(z)  #look at what's returned

#approach 1 (alter the text data frame and pass the qfacet object)
z$dat[5, 1:2] <- c(15, 5)
qfacet_text(z, color="red")

#approach 2 (alter the original ggplot object)
qfacet_text(p, x = c(33, 33, 33, 33, 15, 33), 
    y = c(2.2, 2.2, 2.2, 2.2, 5, 2.2), 1:6, color="red")

#all the same things you can pass to geom_text qfacet_text takes
qfacet_text(z, labels = paste("beta ==", 1:6), 
    size = 3, color = "grey50", parse = TRUE)

Notice at the end you can pass qfacet_text a ggplot object or an object from qfacet_text. The qfacet_text function invisibly returns a list with the original ggplot2 object, the new ggplot2 object and the text data frame. This enables the user to alter the coordinates of the data frame and return the the qfacet_text object back to qfacet_text, thus altering the text position. There’s actual documentation for this package and function so ?qfacet_text should get you a help file with the same example.

PS this gave me a chance to actually run roxygen2 for the first time to create documentation. Also a pretty slick Hadley Wickham package.

The Plot:
ggplot facet with text

To leave a comment for the author, please follow the link and comment on their blog: TRinker's R Blog » R. 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.

Never miss an update!
Subscribe to R-bloggers to receive
e-mails with the latest R posts.
(You will not see this message again.)

Click here to close (This popup will not appear again)