minsky_iww
minsky_iww

Reputation: 3

Put legend under each facet using facet_grid; adding one title and one caption to plot

I'm working with a plot analogous to the following:

ggplot(data=mtcars, aes(x=wt, y=mpg, color=carb)) +
geom_line() + facet_grid(gear ~ .) + 
ggtitle(expression("Title")) +
labs(caption = "Sources: Compustat, Author's Calculations") + 
theme(plot.title = element_text(size = 20, hjust = 0.5), 
plot.caption=element_text(size=8, hjust=.5),
strip.background = element_blank(), 
strip.text = element_blank(), 
legend.title = element_blank())

I'm trying to do the following:

I was able to reproduce this example on assigning a legend to each facet. However, the plot title was placed above and the caption below each facet. Also, this example uses facet_wrap and not facet_grid.

Thank you in advance.

Upvotes: 0

Views: 747

Answers (1)

Brian
Brian

Reputation: 8305

library(dplyr)
library(ggplot2)

tempgg <- mtcars %>% 
  group_by(gear) %>% 
  do(gg = {ggplot(data=., aes(x=wt, y=mpg, color=carb)) +
      geom_point() + 
      labs(x = NULL) +
      guides(color = guide_colorbar(title.position = "left")) +
      theme(plot.title = element_text(size = 20, hjust = 0.5), 
            plot.caption=element_text(size=8, hjust=.5),
            legend.position = "bottom")}) 

tempgg$gg[1][[1]] <- tempgg$gg[1][[1]] + labs(title = "Top title")
tempgg$gg[3][[1]] <- tempgg$gg[3][[1]] + labs(x = "Axis label", caption = "Bottom caption")

tempgg %>% gridExtra::grid.arrange(grobs = .$gg)

enter image description here

This isn't the most elegant way to do it. Each of the three grobs gets an equal space when you grid.arrange them, so the first and last ones are squished from the title and caption taking up space. You could add something like heights = c(3,2,3) inside the grid.arrange call, but you'd have to fiddle with each of the heights to get it to look right, and even then it would be a visual approximation, not exact.

To do it the more precise way, you'd need to look at the underlying gtables in each of the grobs. https://stackoverflow.com/users/471093/baptiste is the expert on that.


Update:

I used a @baptiste solution, which is still not particularly elegant, but gives you the same plot space for each panel. Use this snippet in place of the last line above.

tempggt <- tempgg %>% do(ggt = ggplot_gtable(ggplot_build(.$gg))) %>% .$ggt
gg1 <- tempggt[[1]]
gg2 <- tempggt[[2]]
gg3 <- tempggt[[3]]

gridExtra::grid.arrange(gridExtra::rbind.gtable(gg1, gg2, gg3))

Upvotes: 1

Related Questions