5

I am looking to flip the labels on a faceted panel of 1 row and 5 columns, so that the facet headers appear on bottom, and the x axis appears on top of facets.

The reason is that I want to reuse those headers for a table that will be directly below the graph.

So in this example...

library(ggplot2)

my.hist<-ggplot(diamonds, aes(clarity)) + geom_bar()

my.hist + facet_wrap( ~ cut, ncol=5) + coord_flip()

I would want the "cut" labels to show up below the chart. I was thinking that facet_grid might hold the key, but is only a guess.

Anyone know how to accomplish this?

wesmantooth
  • 625
  • 2
  • 11
  • 29
  • 1
    I'm not aware of the answer to this question having changed since [this](http://stackoverflow.com/q/3261597/324364) or [this](http://stackoverflow.com/q/10058839/324364). – joran Aug 05 '13 at 18:45
  • Looks like bad news... Probably off topic, but I am wondering if lattice offers this functionality. – wesmantooth Aug 05 '13 at 19:17

1 Answers1

7

Getting the facet strips below the plot is easy,

library(gtable)
g <- ggplotGrob(p)

strips <- gtable_filter(g, "strip_t", trim=FALSE)
grid.newpage()
grid.draw(rbind(g, strips[3,], size="first"))

the axes, however, require more care because one has to reverse the position of the tick marks and labels. You can maybe start with this,

tweak_axis <- function(a){
  inner <- a[["children"]]["axis"][[1]]
  inner[["grobs"]] <- rev(inner[["grobs"]])
  inner$grobs[[2]]$y <- inner$grobs[[2]]$y - unit(0.15, "cm")
  a[["children"]]["axis"][[1]] <- inner
  a
}

axes <- gtable_filter(g, "axis_b", trim=FALSE)
axes$grobs <- lapply(axes$grobs, tweak_axis)
grid.newpage()
grid.draw(axes)

Edit: based on the above, a "complete" solution might be

grid.newpage()
g2 <- g
new_axes <- lapply(g2$grobs[grepl("axis_b", g2$layout$name)], tweak_axis)
g$grobs[grepl("strip_t", g$layout$name)] <- new_axes 
g$grobs[grepl("axis_b", g$layout$name)] <- g2$grobs[grepl("strip_t", g2$layout$name)] 
# heights should be changed too, but it's kind of ok here
xlab <- 7; title <- 1:2
grid.draw(rbind(g[xlab,], g[-c(title, xlab), ], size="last"))

enter image description here

(with obvious caveats)

baptiste
  • 75,767
  • 19
  • 198
  • 294
  • 1
    kohske published some tricks for the axes: http://rpubs.com/kohske/dual_axis_in_ggplot2 – baptiste Aug 05 '13 at 18:55
  • If I use `"strip_t"` and then run `strips` I get the output `TableGrob (6 x 5) "layout": 0 grobs`. Is this the intended effect? I ask because I also get an error on the final output, `Error in mmm < each : comparison of these types is not implemented`. However, I am replacing `p` in your code with `my.plot` from mine. Is this a correct usage? – wesmantooth Aug 05 '13 at 19:16
  • 1
    you should have 5 grobs in that gtable, make sure `p` is your plot updated to include the second line (`facet_wrap`). I've updated the code to take care of the other error. – baptiste Aug 05 '13 at 19:20
  • Ok thank you for pointing that out. I had to reassign to the updated plot, which provided the expected output. I am now getting the expected output for facet labels, and I will try to chase down reversing the tick marks. Nice to have the gridExtra author answer my question. Thanks a bunch! – wesmantooth Aug 05 '13 at 19:34
  • This is brilliant! I appreciate you wrapping that functionality into a function as well. It definitely looks like some insider code there. I will have to experiment with this so I can understand the internal structures you are manipulating, and then parameterize this function. One question though, how does the function know `(a)` when no argument was passed in the code that uses this function? Thanks again! – wesmantooth Aug 06 '13 at 19:32