Reputation: 3073
I want to append a plot to an existing pdf long after dev.off()
has been called*. After reading the pdf()
help file and after reading the Q & A here and here, I'm pretty sure it can't be done in R. But, maybe some of you smarter people have a solution that I wasn't able to find.
pdf("Append to me.%03d.pdf",onefile=T)
plot(1:10,10:1) #First plot (page 1)
dev.off()
pdf("Append to me.%03d.pdf",onefile=T)
plot(1:10,rep(5,10)) #Want this one on page 2
dev.off()
*This not a duplicate of the questions linked above because I want to append to a pdf file after the pdf device has been closed.
Upvotes: 33
Views: 22410
Reputation: 177
I found this excellent work recently (not attempting to claim it as my own)
https://jonkimanalyze.wordpress.com/2014/07/24/r-compile-png-files-into-pdf/
It's not quite what the OP was asking for, but the reason I like it is that I often have quite dense scatterplots and other plots that don't respond particularly well to window resizing etc. within a pdf. However I need to produce multi page output. So if the plots are data-dense I render them as .pngs and then use the above function to recombine at the end.
merge.png.pdf <- function(pdfFile, pngFiles, deletePngFiles=FALSE) {
pdf(pdfFile)
n <- length(pngFiles)
for( i in 1:n) {
pngFile <- pngFiles[i]
pngRaster <- readPNG(pngFile)
grid.raster(pngRaster, width=unit(0.8, "npc"), height= unit(0.8, "npc"))
if (i < n) plot.new()
}
dev.off()
if (deletePngFiles) {
unlink(pngFiles)
}
}
Upvotes: 3
Reputation: 162461
If you are willing to install the small, free, platform-independent pdftk utililty, you could use a system call from R to have it stitch all of your figures together:
## A couple of example pdf docs
pdf("Append to me.1.pdf")
plot(1:10,10:1)
dev.off()
pdf("Append to me.2.pdf")
plot(1:10,rep(5,10))
dev.off()
## Collect the names of the figures to be glued together
ff <- dir(pattern="Append to me")
## The name of the pdf doc that will contain all the figures
outFileName <- "AllFigs.pdf"
## Make a system call to pdftk
system2(command = "pdftk",
args = c(shQuote(ff), "cat output", shQuote(outFileName)))
## The command above is equiv. to typing the following at the system command line
## pdftk "Append to me.1.pdf" "Append to me.2.pdf" cat output "AllFigs.pdf"
Upvotes: 19
Reputation: 44634
You could use recordPlot
to store each plot in a list
, then write them all to a pdf file at the end with replayPlot
. Here's an example:
num.plots <- 5
my.plots <- vector(num.plots, mode='list')
for (i in 1:num.plots) {
plot(i)
my.plots[[i]] <- recordPlot()
}
graphics.off()
pdf('myplots.pdf', onefile=TRUE)
for (my.plot in my.plots) {
replayPlot(my.plot)
}
graphics.off()
Upvotes: 23
Reputation: 174948
This is horribly hacky and probably belies my limited UNIX shell fu, but it works for me on a Fedora 17 box with the pdfjam package installed (not an R package, but from the YUM repos)
pdf("pdf1.pdf")
plot(1:10)
dev.off()
pdf("| pdfjoin --outfile \"pdf2.pdf\" && pdfjoin pdf1.pdf pdf2.pdf --outfile pdf1.pdf && rm pdf2.pdf")
plot(10:1)
dev.off()
The output in R is:
> pdf("| pdfjoin --outfile \"pdf2.pdf\" && pdfjoin pdf1.pdf pdf2.pdf --outfile pdf1.pdf && rm pdf2.pdf")## && pdfunite joined.pdf tmp.pdf joined.pdf && rm tmp.pdf")
> plot(10:1)
> dev.off()
----
pdfjam: This is pdfjam version 2.08.
pdfjam: Reading any site-wide or user-specific defaults...
(none found)
pdfjam: No PDF/JPG/PNG source specified: input is from stdin.
pdfjam: Effective call for this run of pdfjam:
/usr/bin/pdfjam --fitpaper 'true' --rotateoversize 'true' --suffix joined --outfile pdf2.pdf -- /dev/stdin -
pdfjam: Calling pdflatex...
pdfjam: Finished. Output was to 'pdf2.pdf'.
----
pdfjam: This is pdfjam version 2.08.
pdfjam: Reading any site-wide or user-specific defaults...
(none found)
pdfjam: Effective call for this run of pdfjam:
/usr/bin/pdfjam --fitpaper 'true' --rotateoversize 'true' --suffix joined --outfile pdf1.pdf -- pdf1.pdf - pdf2.pdf -
pdfjam: Calling pdflatex...
pdfjam: Finished. Output was to 'pdf1.pdf'.
null device
1
Basically, pdfjoin
will take input from stdin
if it is the only input file so I pipe the output from pdf()
to the pdfjoin
program and specify the output file using the --outfile
argument. Then using &&
is join the original pdf1.pdf
with the pdf2.pdf
just created, specifying that the output PDF is pdf1.pdf
, the name of the original PDF.
Upvotes: 6