15

As explained here, it is easy to embed a plot into an existing one thanks to gridBase, even though both plots use the base graphics system of R. However, when saving the whole figure into a pdf, the first page is always blank. How to prevent this?

Here is an example:

require(gridBase)

## generate dummy data
set.seed(1859)
x <- 1:100
y <- x + rnorm(100, sd=5)
ols <- lm(y ~ x)

pdf("test.pdf")

## draw the first plot
plot.new() # blank page also happens when using grid.newpage()
pushViewport(viewport())
plot(x, y)

## draw the second plot, embedded into the first one
pushViewport(viewport(x=.75,y=.35,width=.2,height=.2,just=c("center","center")))
par(plt=gridPLT(), new=TRUE)
hist(ols$residuals, main="", xlab="", ylab="")
popViewport(2)

dev.off()
Community
  • 1
  • 1
tflutre
  • 3,354
  • 9
  • 39
  • 53

2 Answers2

32

I think it's a bit of a hack but setting onefile=FALSE worked on my machine:

pdf("test.pdf", onefile=FALSE)

In searching for an answer (which I didn't really find so much as stumbled upon in the forest) I came across this post to Rhelp from Paul Murrell who admits that mixing grid and base graphics is confusing even to the Master.

IRTFM
  • 258,963
  • 21
  • 364
  • 487
  • 1
    I guess `onefile=FALSE` solve it because it force it to be only single page. since it will create the blank page regardless and then will be overwritten by the plot you wanted to have. (you can try it by having a for loop after the `pdf` function and before `dev.off()` ) do you have any suggestion on how to create pages one by one and avoid over-writing for multi page pdf? – Mehrad Mahmoudian Jan 27 '17 at 10:31
  • When `onefile=FALSE`, the pages file names are supposed to be sequentially numbered. (See the Usage section of `?pdf`.) Do you have a specific example where that is not occurring? if so, then post a new question. – IRTFM Jan 27 '17 at 16:21
  • it will not be sequentially numbered and writing an example is easy (I'm posting it here since it's not a question and is related to this topic): `pdf(file = "test.pdf", onefile = F); for(i in 1:5){plot(rnorm(50, i, i), main = i)};dev.off()` – Mehrad Mahmoudian Jan 30 '17 at 05:56
  • Is there a way to fix this problem totally? – Shixiang Wang May 13 '19 at 05:39
  • The "fix" is to put the `pdf()` and `dev.off()` calls inside the for loop and to make the names index-specific. `for(i in 1:5){pdf(file = paste("test", i, ".pdf"), onefile = F);plot(rnorm(50, i, i), main = i);dev.off()}` . I admit that the docs do seem a bit off on this point. – IRTFM Feb 09 '22 at 00:48
  • Or you can use the method of James Silva: (corrected his minor lapse in R syntax: `for(i in 1:5){ if (i == 1) pdf(file = "test.pdf"); plot(rnorm(50, i, i), main = i)} ; dev.off()` – IRTFM Feb 09 '22 at 15:59
1

A work around solution I found was to initiate the pdf file inside the for loop; then insert an if clause to assess whether the first iteration is being run. When the current iteration is the first one, go ahead and create the output device using pdf(). Put the dev.off() after closing the for loop. An quick example follows:

for(i in 1:5){
  if (i == 1) pdf(file = "test.pdf")
  plot(rnorm(50, i, i), main = i)}
dev.off()
IRTFM
  • 258,963
  • 21
  • 364
  • 487