10

I have a dataset from which I would like to plot small multiples, specifically in a 2-by-2 array, like this:

mydf <- data.frame(letter = factor(rep(c("A", "B", "C", "D"), each = 20)), x = rnorm(80), y = rnorm(80))
ggplot(mydf, aes(x = x, y = y)) + geom_smooth(method = "lm") + geom_point() + facet_wrap(~ letter, ncol = 2)

However, I want each facet label to include an expression, such as

expression(paste("A or ", alpha))

I can make this happen using facet_grid() via

f_names <- list('A' = expression(paste("A or ", alpha)), 'B' = expression(paste("B or ", beta)), 'C' = expression(paste("C or ", gamma)), 'D' = expression(paste("D or ", delta)))
f_labeller <- function(variable, value){return(f_names[value])}
ggplot(mydf, aes(x = x, y = y)) + geom_smooth(method = "lm") + geom_point() + facet_grid(~ letter, labeller = f_labeller)

But then I lose the 2-by-2 array. How can I rename the facet_wrap() facet labels with an expression? Or, how can I solve this by recreating the 2-by-2 array using facet_grid(), but only faceting by a single variable?

(This question builds off of the parenthetical note in @baptiste's answer to this previous question.)

Thanks!

Community
  • 1
  • 1
RTM
  • 579
  • 5
  • 16
  • Does this help: http://stackoverflow.com/questions/10151123/how-to-specify-columns-in-facet-grid-or-how-to-change-labels-in-facet-wrap – Ricardo Saporta Oct 09 '13 at 21:31
  • @baptiste: Yes! Thank you, the `facet_wrap_labeller()` function in the Q&A to which you linked works great. @Ricardo: Thanks for that link -- I had found that answer, and it pushed me toward the question originally. Thanks to you both. – RTM Oct 10 '13 at 14:09

1 Answers1

8

In order to do what I asked, first load this labeller function from @Roland first appearing here:

facet_wrap_labeller <- function(gg.plot,labels=NULL) {
  #works with R 3.0.1 and ggplot2 0.9.3.1
  require(gridExtra)

  g <- ggplotGrob(gg.plot)
  gg <- g$grobs      
  strips <- grep("strip_t", names(gg))

  for(ii in seq_along(labels))  {
    modgrob <- getGrob(gg[[strips[ii]]], "strip.text", 
                       grep=TRUE, global=TRUE)
    gg[[strips[ii]]]$children[[modgrob$name]] <- editGrob(modgrob,label=labels[ii])
  }

  g$grobs <- gg
  class(g) = c("arrange", "ggplot",class(g)) 
  g
}

Then save the original ggplot() object:

myplot <- ggplot(mydf, aes(x = x, y = y)) + geom_smooth(method = "lm") + geom_point() + facet_wrap(~ letter, ncol = 2)

Then call facet_wrap_labeller() and feed the expression labels as an argument:

facet_wrap_labeller(myplot, labels = c(expression(paste("A or ", alpha)), expression(beta), expression(gamma), expression(delta)))

The expressions should now appear as the facet_wrap() labels.

Community
  • 1
  • 1
RTM
  • 579
  • 5
  • 16
  • Simpler way to use it, not needed to pass an expression on every field of the labels, neither the "labels": facet_wrap_labeller(myplot, expression(paste("A or ", alpha), beta, gamma, delta)) – Eduardo Oct 27 '14 at 14:43
  • 2
    For anyone attempting this more currently, a solution within ggplot has now been implemented. There is a nice example at the bottom of the [ggplot index](http://docs.ggplot2.org/current/labellers.html) that shows how to do this very handily with facet_wrap. – Nova Apr 13 '16 at 17:41