27

I want to loop over a plot and put the result of the plot in a PDF.

The following code is used to do this:

What this does is loop 3 times and plot 3 different plots from the iris dataset. Then it should save it to the C:/ drive. The PDF files are created, but are corrupted.

for(i in 1:3){
  pdf(paste("c:/", i, ".pdf", sep=""))
  plot(cbind(iris[1], iris[i]))
  dev.off()
}
zx8754
  • 52,746
  • 12
  • 114
  • 209
Sir Ksilem
  • 1,195
  • 2
  • 12
  • 27
  • 5
    This works for me on Linux. (Well when using a proper path on that system, anyway). Is the example you give really what you are doing or are you using a different plotting system? Lattice or ggplot2 perchance? If you are, then you need to wrap the plotting calls in `print()` as auto-printing is turned off in loops and you need to print lattice or ggplot objects to get them to draw something. – Gavin Simpson May 04 '11 at 10:55
  • yes, they are in lattice, but this one doesn't work either... – Sir Ksilem May 04 '11 at 10:59
  • Any errors? I mean, as @Chase mentions in his answer, is the path valid on your system? How about just saving to the working directory if you have write permissions there, then just drop the path as shown by @Chase. – Gavin Simpson May 04 '11 at 11:01
  • it worked before, when I didn't use a loop I could make pdf's on my C:/ path – Sir Ksilem May 04 '11 at 11:03
  • Before what? You've shown us a bit of code that you claim doesn't work, but haven't told us what the error was if anything, the code doesn't actually correspond to the real problem (plotting lattice graphics in a loop). Break this down into simple steps. Can you create a single plot at `"C:/plot_1.pdf"` (does `C` need to be uppercase on Windows?)? If you can, try the loop but without the `pdf()` and `dev.off()` bits and see if you can produce the three lattice plots. Finally, if both these work, put them together. See my Answer for code that you should be able to just run for Lattice. – Gavin Simpson May 04 '11 at 11:10
  • like i said, they are created, but there's nothing in them. when i open them the error is that they are corrupted – Sir Ksilem May 04 '11 at 11:26
  • try graphics.off() to close all open graphical devices – Henrik May 04 '11 at 11:34

2 Answers2

69

To drawn lattice plots on the device, one needs to print the object produced by a call to one of the lattice graphics functions. Normally, in interactive use, R auto prints objects if not assigned. In loops however, auto printing does not work, so one must arrange for the object to be printed, usually by wrapping it in print().

Here is an example (please excuse my abuse of the formula notation ;-):

require(lattice)
for(i in 1:3) {
    pdf(paste("plot", i, ".pdf", sep = ""))
    print(xyplot(iris[,1] ~ iris[,i], data = iris))
    dev.off()
}

This produces the three plots on a pdf device.

Gavin Simpson
  • 170,508
  • 25
  • 396
  • 453
  • 3
    This is a special case of http://cran.r-project.org/doc/FAQ/R-FAQ.html#Why-do-lattice_002ftrellis-graphics-not-work_003f (it's a bit harder to figure out since the original poster gave us what is probably not the real code they were trying to run) – Ben Bolker May 04 '11 at 15:43
4

Is a file name that contains "c:/" a valid file name on your OS? That looks like part of the working directory that you'd want to set before calling pdf. I get an error telling me it can't open that file:

Error in pdf(paste("c:/", i, ".pdf", sep = "")) : 
  cannot open file 'c:/1.pdf'

If I drop the "c:/" bit from the file name, three PDFs are generated properly. Also, if you move the dev.off() outside of the for loop, you'll get a single PDF with three pages instead of three PDFs. May or may not be what you want...

for(i in 1:3){
  pdf(paste("plot", i,".pdf",sep=""))
  plot(cbind(iris[1],iris[i]))
  dev.off()
}
Chase
  • 67,710
  • 18
  • 144
  • 161
  • 2
    `setwd()`, e.g.: `setwd("d:/my.dir")`. – Roman Luštrik May 04 '11 at 11:01
  • 2
    @Sir Ksilem - to find out where the current working directory is, use `getwd()`. To navigate to a different directory, use `setwd('c:/path/to/new/directory')`. I believe `setwd()` can work with both absolute and relative directories, but that is probably OS dependent. The help pages should have more details. – Chase May 04 '11 at 11:02