11

I am doing an exploratory analysis of my data and need to plot multiple graphics using ggplot. The amount of graphics is really huge (206 Stations), and I wanted to plot them in 1 column vs. 8 rows per page over the so many pages needed. I am aware of functions like viewport or grid.arrange, but I am not managing to make them work in this case. I have already noticed that layout() nor par(mfrow=c(8,1)) do not work with ggplot, but I send the part of the code where I am stuck bellow. Any help would be much appreciated!

pdf('test.pdf', width=21, height=27)
par(mfrow=c(8,1))
for(i in levels(tab$Station))
{

print(ggplot(tab[tab$Station==i], aes(x=Date)) +
  geom_line(aes(y=Tmin), col="blue", size=0.1) + 
  geom_line(aes(y=Tmax), col="red", size=0.1) + 
  geom_text(aes(x=as.Date('2010-01-01'), y=45), label=i) +
  ylim(0, 45) + 
  scale_x_date(labels = date_format("%Y")) +
  theme_bw() +
  theme(
    plot.background = element_blank()
    ,panel.grid.major = element_blank()
    ,panel.grid.minor = element_blank()
    ,panel.border = element_rect(color = 'black')
    ,panel.background = element_blank()

  )
)

}

dev.off()
José Monteiro
  • 111
  • 1
  • 1
  • 3
  • 3
    Hi Jose, would you mind making this a reproducible examples? That commonly means providing toy data so that we can just grab the code and run it. Most often, people use the `data()` function to do this. For example `data(mtcars)` loads that `mtcars` data.frame into memory. – Statwonk Sep 27 '13 at 20:59
  • 1
    Did the answer by @baptiste work? – Gerome Bochmann Apr 07 '14 at 10:00
  • 3
    I know it's an old question - but try using the facet_wrap_paginate function in the ggforce package. See help here https://cran.r-project.org/web/packages/ggforce/ggforce.pdf that's how I solved my similar problem. – Alison Bennett Feb 21 '17 at 03:00

4 Answers4

11
library(plyr)
library(gridExtra)

p = ggplot(tab, aes(x=Date)) +
       geom_line(aes(y=Tmin), col="blue", size=0.1)

plots = dlply(tab , "Station", `%+%`, e1 = p)
ml = do.call(marrangeGrob, c(plots, list(nrow=8, ncol=1)))
ggsave("multipage.pdf", ml)

untested.

baptiste
  • 75,767
  • 19
  • 198
  • 294
  • could you explain what you did to create the `plots` object above? What does ``%+%`` do? – llewmills Mar 14 '17 at 20:47
  • 1
    `%+%` overrides the data in a ggplot – baptiste Mar 14 '17 at 20:53
  • 1
    I'm still an r green-belt so need help from a 4th-Dan black-belt such as yourself. Also I'm only just now getting familiar with using `plyr` and `dplyr` instead of the `apply` family. So I'm guessing here, but does this mean you've passed the subsetted `tab` object (subsetted by Station) into the ggplot `p`, using the `%+%` function to override the place the `tab` argument held in the original? If so that's fantastic. – llewmills Mar 14 '17 at 21:15
  • than you @baptiste. Excuse the follow-up but what does the `e1 =` do in the `dlply` function? When I remove it and just put `p` in its place the `plots` function still works but suddenly calling the `plots` object results in no graphs appearing. – llewmills Mar 17 '17 at 18:25
  • 1
    `%+%` is an infix operator, with two arguments named `e1` and `e2`. It's defined rather awkwardly, with the case of interest here considering `e1` a ggplot, and `e2` a data.frame (or other things, actually). The dlply loop (equiv. lapply) would feed the function with data.frames as first parameter by default, unless one passes explicitly a plot as named first argument (dlply then jumps to the next one). – baptiste Mar 17 '17 at 19:56
  • So I tried this method and it did not work. I got this error: Error in gList(data = list(wrapvp = list(x = 0.5, y = 0.5, width = 1, : only 'grobs' allowed in "gList" - Does this method still work? – Marinka Jul 29 '21 at 15:50
1

You should simplify your plot since once you get the right order with a simple plot you just replace it with your complicated one. ggplot2 are based on grid package so you need to use gridExtra to arrange your plots. Then you loop through , for each 8 plots, you store them in a list and you call grid.arrange over it, and you repeat this until the end of your plots...

library(gridExtra)
library(ggplot2)
pdf('test.pdf', width=21, height=27)
i = 1
plot = list() 
for (n in unique(tab$Station)){
  ### process data for plotting here ####
  plot[[i]] = ggplot(tab[tab$Station==n], aes(x=Date)) +...
  if (i %% 8 == 0) { ## print 8 plots on a page
    print (do.call(grid.arrange,  plot))
    plot = list() # reset plot 
    i = 0 # reset index
  }
  i = i + 1
}
if (length(plot) != 0) { 
  print (do.call(grid.arrange,  plot))
}
dev.off()
agstudy
  • 119,832
  • 17
  • 199
  • 261
1

Faceting might be the way to go. Decide how many faceted mini-plots you want per page, then loop through the required number of times, generating a png or a pdf as you go. So if you have 200 data items and you want 50 per page, in facets of 5 across and 10 down, just loop through 200/50 = 4 iterations. Crude, but should work.

facets

library(ggplot2)

ii <- 7
nn <- 49

mydf <- data.frame(date = rep(seq(as.Date('2013-03-01'),
                       by = 'day', length.out = ii), nn),
                   value = rep(runif(nn, 100, 200)))

mydf$facet.variable <- rep(1:nn, each = ii)

p <- ggplot(mydf, aes(x = date, y = value)) +
    geom_line() +
    facet_wrap(~ facet.variable, ncol = ii)

print(p)
SlowLearner
  • 7,907
  • 11
  • 49
  • 80
0

Unfortunately, mfrow doesn't work with ggplot2. You have to use other methods like this one or this one or use the native plot function.

Maybe you can use faceting to get the 8 plots onto one page, then the second link to put it into multiple documents...

Community
  • 1
  • 1
beroe
  • 11,784
  • 5
  • 34
  • 79