splitting or removing graphs after arrangeGrob

462 views Asked by At

I created a graph with ggplot and later I used arrangeGrob to combine those graphs. Is there a way to remove parts a graph from this combined plot? Or maybe extract?

Here is a minimal example:

library(ggplot2)
library(gridExtra)
df <- data.frame(x=rnorm(20), y=rnorm(20), y2=rnorm(20))
g1 <- ggplot(df, aes(x, y)) + geom_point()
g2 <- ggplot(df, aes(x, y2)) + geom_point()
g <- arrangeGrob(g1,g2, widths=c(3.5,7.5), ncol=2)
print(g)

I would like to remove one of the two plots.

3

There are 3 answers

6
Josh O'Brien On BEST ANSWER

First, use grid.ls() to see a listing of the grobs that make up the plot. Here, you'll be looking for the names of the two gTree objects that encode the individual plots. (Compared to lattice, ggplot2's naming of component grobs is relatively unhelpful, although in this case, it's not too hard to see which pieces you'll want to extract.)

grid.ls()
# GRID.arrange.90
#   GRID.frame.84
#     GRID.cellGrob.85
#       GRID.frame.5
#         GRID.cellGrob.44
#           GRID.gTree.42
#             GRID.clip.43
#             layout
#         GRID.cellGrob.83
#           GRID.gTree.81
#             GRID.clip.82
#             layout
#     GRID.cellGrob.86
#       GRID.null.1
#     GRID.cellGrob.87
#       GRID.null.2
#     GRID.cellGrob.88
#       GRID.null.4
#     GRID.cellGrob.89
#       GRID.null.3

Then, you can extract and plot them like this:

gg1 <- getGrob(g, ("GRID.gTree.42"))
grid.draw(gg1)

gg2 <- getGrob(g, ("GRID.gTree.81"))
grid.draw(gg2)
0
Spacedman On

grid graphics are complicated nested trees of things. A bit (okay, a lot) of trial and error managed to get your two plots out like this:

 > plot(g$children[[1]]$children[[1]]$children[[1]]$children[[1]]$children[[1]]$children[[2]])
 > plot(g$children[[1]]$children[[1]]$children[[1]]$children[[2]]$children[[1]]$children[[2]])

There's probably an easier way...

1
Sandy Muspratt On

If you don't have to use arrangeGrob: It is possible to extract grobs from a gtable layout. It takes longer to set up the layout, but the extracting of the required element is straightforward.

library(gtable)
library(grid)
gt = gtable(unit(c(3.5, 7.5), "null"), unit(1, "null"))
gt = gtable_add_grob(gt, ggplotGrob(g1), l = 1, t = 1)
gt = gtable_add_grob(gt, ggplotGrob(g2), l = 2, t = 1)

plot(gt)
plot(gt[, 1])
plot(gt[, 2])

If you want to keep the size and positioning of the extracted plot the same as its size and positioning in the combined plot:

EDIT: Using Baptiste's suggestion:

gt = gtable(unit(c(3.5, 7.5), "null"), unit(1, "null"))
gt = gtable_add_grob(gt, ggplotGrob(g1), name = "g1", l = 1, t = 1)
gt = gtable_add_grob(gt, ggplotGrob(g2), name = "g2", l = 2, t = 1)

grid.newpage()
grid.draw(gtable_filter(gt, "g2", trim = FALSE))

grid.newpage()
grid.draw(gtable_filter(gt, "g1", trim = FALSE))

Original:

# Keep g2
p2 = gt
p2$layout = gt$layout[-1, ]
p2$grobs = gt$grobs[-1]
grid.newpage()
grid.draw(p2)

# Keep g1
p1 = gt
p1$layout = gt$layout[-2, ]
p1$grobs = gt$grobs[-2]
grid.newpage()
grid.draw(p1)