YefR
YefR

Reputation: 369

How to add titles between plots

For the sake of simplicity, let's assume I have four graphs:

data("midwest", package = "ggplot2")
p1<-ggplot(midwest, aes(x=area, y=poptotal)) + geom_point()
p2<-ggplot(midwest, aes(x=area, y=poptotal)) + geom_point()
p3<-ggplot(midwest, aes(x=area, y=poptotal)) + geom_point()
p4<-ggplot(midwest, aes(x=area, y=poptotal)) + geom_point()
grid.arrange(p1,p2,p3,p4,ncol=2) 

Now, I want to create a title (TITLE 1, TITLE 2) between each two titles,, as presented below: enter image description here

Any ideas how to do it?

Upvotes: 0

Views: 472

Answers (1)

teunbrand
teunbrand

Reputation: 37913

Here is a gtable solution to your problem. There might be easier solutions out there, but this should work.

First we'll bake in some titles in the leftmost plots

library(grid) # needed later for plotting

data("midwest", package = "ggplot2")
p1<-ggplot(midwest, aes(x=area, y=poptotal)) + geom_point() + ggtitle("Title 1")
p2<-ggplot(midwest, aes(x=area, y=poptotal)) + geom_point()
p3<-ggplot(midwest, aes(x=area, y=poptotal)) + geom_point() + ggtitle("Title 2")
p4<-ggplot(midwest, aes(x=area, y=poptotal)) + geom_point()

Then we can cbind and rbind the plots together as we see fit.

p12 <- cbind(ggplotGrob(p1), ggplotGrob(p2), size = "first")
p34 <- cbind(ggplotGrob(p3), ggplotGrob(p4), size = "first")

all <- rbind(p12, p34, size = "first")

grid.newpage(); grid.draw(all)

Note that we'd have to work with grid.newpage() and grid.draw() to get our plots, since we've left the ggplot sphere and are now in the realm of gtables and grid. Anyway, resulting plot looks like the following:

enter image description here

From your example I expect that you want these titles to be centered. This will be a bit more finicky:

# Decide what is a title
is_title <- grep("^title$", all$layout$name)
# Grab all titles
titles <- all$grobs[is_title]
# Exclude empty titles
is_title <- is_title[!sapply(titles, inherits, "zeroGrob")]

# Center title
all$grobs[is_title] <- lapply(all$grobs[is_title], function(title) {
  title$children[[1]]$hjust <- 0.5
  title$children[[1]]$x <- unit(0.5, "npc")
  title
})

# Spread title over all panels
# You can see the number you'd need from the l/r coordinates of the 'panel' grobs
# which you can find by printing `all` or `all$layout`.
all$layout[is_title, "r"] <- 14 


grid.newpage(); grid.draw(all)

enter image description here

EDIT: added example for adding extra titles

You can add extra titles, but you would need the gtable package for this.

library(gtable)

# First make extra titles
left <- textGrob("Left Title", gp = gpar(fontsize = 13.2, col = "black",
                                         lineheight = 0.9, font = 1))
right <- textGrob("Right Title", gp = gpar(fontsize = 13.2, col = "black",
                                           lineheight = 0.9, font = 1))

# Find a height that was 0, assign new height based on extra title
all$heights[[2]] <- unit(1, "grobheight", left)
# Add the titles (t = top position, l = left position)
all <- gtable_add_grob(all, left, t = 2, l = 5, clip = "off")
all <- gtable_add_grob(all, right, t = 2, l = 14, clip = "off")

grid.newpage(); grid.draw(all)

enter image description here

Upvotes: 1

Related Questions