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.
gtable
Objects
Generating 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).
gtable
Objects
Navigating 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-b
andaxis-l
mean axis bottom and left respectively. gtable
objects are converted togtree
bygtable:::grid.draw.gtable
before a final call togrid.draw