ggplot2: Using gtable to move strip labels to top of panel for facet_grid AND creating multiple facet_grid plots, by 'class', into one grid

409 views Asked by At

As you can see by the title, my question is actually related to this question.

The solution to this question works great, but now I would like to take this plot and produce multiple facet_grid plots by 'class' (still keeping the labels up top) into one grid plot arrangement. I am using a for loop to produce the multiple facet_grid plots.

This is what I have so far, where the comments in the code describe what is happening (or what I think is happening at least), but my issues seem to be towards the end of the code. I tried to assign a list of these indexed facet_grid plots to output into one grid arrangement, but it is not working.

The R code:

library(ggplot2)
library(gtable)
library(grid)
library(gridExtra)

# looping to create multiple graphs by vehicle class.
for (j in 1:length(unique(mpg$class))){

# as it loops, mpg is subsetted by each class into mpg2.
mpg2 <- mpg[mpg$class==as.character(unique(mpg$class)[j]),]

#this line was put in, because indexing mt[[j]] won't work unless the object mt has been
#created first. Without this line I get this error:
# Error in mt[[j]] <- ggplot(mpg2, aes(x = cty, y = model)) + geom_point() +  : 
#   object 'mt' not found
mt <- ggplot(mpg2, aes(x = cty, y = model)) + geom_point()

#with the creation of the object 'mt', in the one line above, these ggplots can now be assigned to 'mt[[j]]'
mt[[j]] <- ggplot(mpg2, aes(x = cty, y = model)) + geom_point() +
  facet_grid(manufacturer ~ ., scales = 'free', space = 'free') +
  theme(panel.margin = unit(0.5, 'lines'), 
        strip.text.y = element_text(angle = 0))

# Get the gtable of each ggplot in mt[[j]]
gt <- ggplotGrob(mt[[j]])

# Get the position of the panels in the layout
panels <-c(subset(gt$layout, name=="panel"))

# Add a row above each panel
for(i in rev(panels$t-1)) gt = gtable_add_rows(gt, unit(.5, "lines"), i)

# Get the positions of the panels and the strips in the revised layout
panels <-c(subset(gt$layout, name=="panel", se=t:r))
strips <- c(subset(gt$layout, name=="strip-right", se=t:r))

# Get the strip grobs
stripText = gtable_filter(gt, "strip-right")

# Insert the strip grobs into the new rows
for(i in 1:length(strips$t)) gt = gtable_add_grob(gt, stripText$grobs[[i]],  t=panels$t[i]-1, l=4, r=4)

# Remove the old strips
gt = gt[,-5]

# For this plot - adjust the heights of the strips and the empty row above the strips
for(i in panels$t) {
  gt$heights[i-1] = list(unit(0.8, "lines"))
  gt$heights[i-2] = list(unit(0.2, "lines"))
}

# Draw it - this line of code, below, has been commented out, because grid.draw(gt) wouldn't assign to plots[[j]]
#plots[[j]] <- grid.draw(gt)

#this line was put in, because indexing plots[[j]] won't work unless the object 'plots' has been
#created first. Without this line I get this error:
# Error in plots[[j]] <- arrangeGrob(gt) : object 'plots' not found
plots <- arrangeGrob(gt)

# here i want each arrageGrob(gt) plot created in this loop to then be saved to plots[[j]]
# so i can then call the plots later in a list and output them using grid.arrange.
plots[[j]] <- arrangeGrob(gt)

}
# running the code up to here, works without any error, but the code below where I am
# trying to create the grid of plots, does not work.  


# here i am trying to place all the plots into a list.
allplots <- plots[j-j+1:j]

# I now want to gather all of the 'class' facet_grid plots into one grid.
graph <- do.call("grid.arrange", c(allplots, ncol=2))
graph
0

There are 0 answers