Add Text Annotations to ggplot2 Faceted Plot (an easier approach)
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") library(acc.ggplot2)
Here’s the code and a few examples:
library(ggplot2) qfacet_text <- function(ggplot2.object, x.coord = NULL, y.coord = NULL, labels = NULL, ...) { require(ggplot2) 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, ...) print(p) v <- list(original = ggplot2.object, new = p, dat = text.df) class(v) <- "qfacet" invisible(v) }
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) + theme_bw() 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:
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.