Alexander Alexander - 12 days ago 10
R Question

Combining `for loop` and ggplotGrob

I just wanted to plot multiple facets using

ggplot2
in combination with
for loop
and found the solution in this postggplot2-plots-over-multiple-pages.

However, I want to modify appearances of these facets with
ggplotGrop
for reducing the strip size of facets after this
for loop
.

I am providing here reproducible example of previous question for only plotting
facets


library(ggplot2)
library(vcd) # For the Baseball data
data(Baseball)

pdf("baseball.pdf", 7, 5)

aa<- for (i in seq(1, length(unique(Baseball$team87)), 6)) {
print(ggplot(Baseball[Baseball$team87 %in% levels(Baseball$team87)[i:(i+5)], ],
aes(hits86, sal87)) +
geom_point() +
facet_wrap(~ team87) +
scale_y_continuous(limits=c(0, max(Baseball$sal87, na.rm=TRUE))) +
scale_x_continuous(limits=c(0, max(Baseball$hits86))) +
theme_bw())
}
dev.off()


want to implement
ggplotGrob
to reduce the strip size.

library(gridExtra)
library(grid)
g = ggplotGrob(aa)

pos = c(unique(subset(g$layout, grepl("panel", g$layout$name), select = t)))
for(i in pos) g$heights[i-1] = unit(0.4,"cm")

grobs = which(grepl("strip", g$layout$name))
for(i in grobs) g$grobs[[i]]$heights <- unit(1, "npc")

grid.draw(g)
dev.off()



Error in plot_clone(plot) : attempt to apply non-function


I just wonder how to implement
ggplotGrop
to that for loop.

Answer

The main probleme is that you're using ggplotGrob on an the wrong object. You have to use it inside each loop. Then you must grid.arrange to make the multipage pdf

First method: with a trick as ggplotGrob create a blank page

pdf("baseball.pdf", 7, 5)

for (i in seq(1, length(unique(Baseball$team87)), 6)) {
  temp <- ggplot(Baseball[Baseball$team87 %in% levels(Baseball$team87)[i:(i+5)], ], 
               aes(hits86, sal87)) + 
          geom_point(na.rm=TRUE) + ## to avoid warnings
          facet_wrap(~ team87) +
          scale_y_continuous(limits=c(0, max(Baseball$sal87, na.rm=TRUE))) +
          scale_x_continuous(limits=c(0, max(Baseball$hits86))) +
          theme_bw()
  pdf(file=NULL) ## because ggplotGrob will create a blank page
  g <- ggplotGrob(temp)
  pos =  c(unique(subset(g$layout, grepl("panel", g$layout$name), select = t)))
  for(i in pos) g$heights[i-1] = unit(0.4,"cm")

  grobs = which(grepl("strip", g$layout$name))
  for(i in grobs) g$grobs[[i]]$heights <-  unit(1, "npc") 
  dev.off() ## to close the fake device
  grid.arrange(g)



}

dev.off()

Second method: to avoid using fake device

plotlist <- list()
j <- 1

for (i in seq(1, length(unique(Baseball$team87)), 6)) {
  temp <- ggplot(Baseball[Baseball$team87 %in% levels(Baseball$team87)[i:(i+5)], ], 
               aes(hits86, sal87)) + 
          geom_point(na.rm=TRUE) +
          facet_wrap(~ team87) +
          scale_y_continuous(limits=c(0, max(Baseball$sal87, na.rm=TRUE))) +
          scale_x_continuous(limits=c(0, max(Baseball$hits86))) +
          theme_bw()
  g <- ggplotGrob(temp)
  pos =  c(unique(subset(g$layout, grepl("panel", g$layout$name), select = t)))
  for(i in pos) g$heights[i-1] = unit(0.4,"cm")

  grobs = which(grepl("strip", g$layout$name))
  for(i in grobs) g$grobs[[i]]$heights <-  unit(1, "npc") 

  plotlist[[j]] <- g
  j <- j+1


}
pdf("baseball.pdf", 7, 5)

for (i in (1:length(plotlist))) {
  grid.arrange(plotlist[[i]])
}

dev.off()

Actually, you can even use grid.arrange and ggplotGrob, without using facet to make all more customisable.

Comments