Modifying Plot Layouts Through `gtable` Manipulation - brodieG/ggplot2 GitHub Wiki
Before ggplot objects are output to a device, they are represented as gtable objects. These objects provide some structure around grobs to facilitate their arrangement and manipulation in table like structures. gtable objects purportedly inherit from grob, but it seems in reality they are a custom gTree like object that shares some attributes with grid objects but really isn't one of them. gtable objects contain a list with grobs and layout information, among other things.
Generating gtable Objects
As mentioned previously, gtable objets are generated by print.ggplot, though if you want to manipulate them directly you can use ggplotGrob:
library(ggplot2)
p <- ggplot(data=data.frame(a=1:10, b=sample(1:10))) + geom_point(aes(x=a, y=b, color=b))
library(gtable)
p.grob <- ggplotGrob(p)
p.grob # we will re-use this later
produces
TableGrob (6 x 6) "layout": 9 grobs
z cells name grob
1 0 (1-6,1-6) background rect[plot.background.rect.2603]
2 3 (3-3,3-3) axis-l absoluteGrob[GRID.absoluteGrob.2587]
3 1 (4-4,3-3) spacer zeroGrob[NULL]
4 2 (3-3,4-4) panel gTree[GRID.gTree.2575]
5 4 (4-4,4-4) axis-b absoluteGrob[GRID.absoluteGrob.2581]
6 5 (5-5,4-4) xlab text[axis.title.x.text.2589]
7 6 (3-3,2-2) ylab text[axis.title.y.text.2591]
8 7 (3-3,5-5) guide-box gtable[guide-box]
9 8 (2-2,4-4) title text[plot.title.text.2601]
This gtable object contains all the graphical information required to render the plots (i.e. all the computations for converting the original data into plots has already been carried out, the step missing is the actual plotting to screen).
Navigating gtable Objects
Navigating is relatively straightforward. Printing the gtable directly tells you most of what you need to know. The rest you get by comparing the gtable to the output of gtable_show_layout(p.grob) (do this!!). If you want additional detail on the grobs, you can try using grid.ls on grid objects (note gtables are not grid objects, so it won't work on those; borrowed from Editing Raw Grobs, though that post may pre-date the introduction of gtable):
grid.ls(p.grob$grobs[4](/brodieG/ggplot2/wiki/4), print=nestedListing) # picked `gTree` from `gtable`
produces:
GRID.gTree.267
grill.gTree.266
panel.background.rect.257
panel.grid.minor.y.polyline.259
panel.grid.minor.x.polyline.261
panel.grid.major.y.polyline.263
panel.grid.major.x.polyline.265
geom_point.points.252
GRID.segments.253
panel.border.zeroGrob.254
Combining Two Plots With a Similar X-axis
In order to bind two plots of similar layout together, you can use rbind.gtable, provided you set the size parameter to "first" (it seems that the plots have some complex measures that can't be easily compared before binding, but if you just take the widths of the first plot's gtable columns as given it seems to work fine).
# Make plots
library(ggplot2)
s <- scale_color_continuous(limits=c(0, 110))
p <- p + s
q <- ggplot(data=data.frame(a=1:10, b=sample(100:109))) + geom_line(aes(x=a, y=b, color=b)) + s
q.grob <- ggplotGrob(q)
# Combine plots by removing bottom rows from top plot
pq.grob <- rbind(p.grob[c(1:3),], q.grob, size="first") # size="first" side steps an apparent bug (?)
# Remove bottom guide, and recenter top guide
pq.grob[1](/brodieG/ggplot2/wiki/1)[13](/brodieG/ggplot2/wiki/13) <- NULL
pq.grob$layout <- pq.grob$layout[-13, ]
pq.grob$layout[4, "b"] <- 6
# Draw
grid.newpage()
grid.draw(pq.grob)
Other Notes
- Note
axis-bandaxis-lmean axis bottom and left respectively. gtableobjects are converted togtreebygtable:::grid.draw.gtablebefore a final call togrid.draw