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()
}
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.
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()
}
Related
I know that
pdf("myOut.pdf")
will print to a PDF in R. What if I want to
Make a loop that prints subsequent graphs on new pages of a PDF file (appending to the end)?
Make a loop that prints subsequent graphs to new PDF files (one graph per file)?
Did you look at help(pdf) ?
Usage:
pdf(file = ifelse(onefile, "Rplots.pdf", "Rplot%03d.pdf"),
width, height, onefile, family, title, fonts, version,
paper, encoding, bg, fg, pointsize, pagecentre, colormodel,
useDingbats, useKerning)
Arguments:
file: a character string giving the name of the file. For use with
'onefile=FALSE' give a C integer format such as
'"Rplot%03d.pdf"' (the default in that case). (See
'postscript' for further details.)
For 1), you keep onefile at the default value of TRUE. Several plots go into the same file.
For 2), you set onefile to FALSE and choose a filename with the C integer format and R will create a set of files.
Not sure I understand.
Appending to same file (one plot per page):
pdf("myOut.pdf")
for (i in 1:10){
plot(...)
}
dev.off()
New file for each loop:
for (i in 1:10){
pdf(paste("myOut",i,".pdf",sep=""))
plot(...)
dev.off()
}
pdf(file = "Location_where_you_want_the_file/name_of_file.pdf", title="if you want any")
plot() # Or other graphics you want to have printed in your pdf
dev.off()
You can plot as many things as you want in the pdf, the plots will be added to the pdf in different pages.
dev.off() closes the connection to the file and the pdf will be created and you will se something like
> dev.off()
null device 1
I know that
pdf("myOut.pdf")
will print to a PDF in R. What if I want to
Make a loop that prints subsequent graphs on new pages of a PDF file (appending to the end)?
Make a loop that prints subsequent graphs to new PDF files (one graph per file)?
Did you look at help(pdf) ?
Usage:
pdf(file = ifelse(onefile, "Rplots.pdf", "Rplot%03d.pdf"),
width, height, onefile, family, title, fonts, version,
paper, encoding, bg, fg, pointsize, pagecentre, colormodel,
useDingbats, useKerning)
Arguments:
file: a character string giving the name of the file. For use with
'onefile=FALSE' give a C integer format such as
'"Rplot%03d.pdf"' (the default in that case). (See
'postscript' for further details.)
For 1), you keep onefile at the default value of TRUE. Several plots go into the same file.
For 2), you set onefile to FALSE and choose a filename with the C integer format and R will create a set of files.
Not sure I understand.
Appending to same file (one plot per page):
pdf("myOut.pdf")
for (i in 1:10){
plot(...)
}
dev.off()
New file for each loop:
for (i in 1:10){
pdf(paste("myOut",i,".pdf",sep=""))
plot(...)
dev.off()
}
pdf(file = "Location_where_you_want_the_file/name_of_file.pdf", title="if you want any")
plot() # Or other graphics you want to have printed in your pdf
dev.off()
You can plot as many things as you want in the pdf, the plots will be added to the pdf in different pages.
dev.off() closes the connection to the file and the pdf will be created and you will se something like
> dev.off()
null device 1
My chunk in Sweave:
<<fig=TRUE,echo=FALSE>>=
for(i in 1:10) {
plot(rep(i,10))
dev.new()
}
#
In the resulting pdf I get only one plot (from the first iteration). I would like to have all of the 10 plots printed. What am I doing wrong? I tried replacing dev.new() with frame() and plot.new() but nothing happened.
As #rawr suggests the easiest solution is to switch to knitr (there's really no reason at all not to!) and put fig.keep="all" in your code chunk options (if you switch to knitr you don't need fig=TRUE any more ... including figures works automatically, fig.keep="none" is the analogue of fig=FALSE)
Alternatively, if you want to stick with vanilla Sweave, check the Sweave manual p. 17:
A.9 Creating several figures from one figure chunk does not work
Consider that you want to create several graphs in a loop similar to
<<fig=TRUE>>
for (i in 1:4) plot(rnorm(100)+i)
#
This will currently not work, because Sweave allows only one graph per figure chunk. The simple reason is that Sweave opens a postscript device before executing the code and closes it
afterwards. If you need to plot in a loop, you have to program it along the lines of
<<results=tex,echo=FALSE>>=
for(i in 1:4){
file=paste("myfile", i, ".eps", sep="")
postscript(file=file, paper="special", width=6, height=6)
plot(rnorm(100)+i)
dev.off()
cat("\\includegraphics{", file, "}\n\n", sep="")
}
#
I have ~10,000 png images saved neatly in different files on my PC. I want to write a function that does something like go to a particular folder and iteratively copy-pastes all the png files in that folder to a word document. Is this possible in R?
I've looked at package R2wd but it sadly only has a function that takes RData and outputs its plot to a word document (function wdPlot).
I also have the RData saved for each and every plot, so reason would dictate that I should be able to simply load the RData associated with a particular plot and then use wdPlot . The problem is that when I generated my png's the plots were grobs and I did something as follows:
png("rp.png",width=w,height=h)
plot(rp)
#Increase size of title
grid.edit(gridTitle_Ref, gp=gpar(fontsize=20))
#Other grid.edit alterations
dev.off()
save(rp)
Now, when I try to get that rp onto a word document by first loading it into R I naively do the following and it does not output a plot to MS Word with the title enlarged or any of the other grid.editalterations.
load("rp.Rdata")
png("rp.png",width=w,height=h)
wdPlot(rp)
#Increase size of title
grid.edit(gridTitle_Ref, gp=gpar(fontsize=20))
#Other grid.edit alterations
dev.off()
So, to reiterate: I have all these png files. At various times I have to copy-paste a subset of them into a word document. I'm too lazy to do that manually each time and want a program to do it for me.
EDIT 1
So, as per suggestions below, I've read up on Markdown. Following this post How to set size for local image using knitr for markdown?
I wrote something along the lines of:
```{r,echo=FALSE,fig.width=100, fig.height=100}
# Generate word documents of reports
# Clear all
rm(list=ls())
library(png)
library(grid)
library(knitr)
dir<-"location\of\file"
setwd(dir)
# Output only directories:
folders<-dir()[file.info(dir())$isdir]
for(folder in folders){
currentDir<-paste(dir,folder,"\\",sep="")
setwd(currentDir)
#All files in current folder
files<-list.files()
imgs<-[A list of all the png images in this particular file that I want in the word document - the png names]
for(img in imgs){
imgRaster<-readPNG(img)
grid.raster(imgRaster)
}
}
```
The following is a screenshot of what's in the resulting word document. How might I fix this? I want the images to appear one after the other in the document as the for loop above runs.
Do note that this is the first time I've ever used Markdown so any relevant tutorials linked in the comments could also be of great help.
EDIT 2
I followed the second answer's example below. Here is the output that I obtained
As you can see there are no images, only the html tags. How do I fix this?
If you have the png's saved you can just use a little html and a for loop to save them to a .doc file.
edit 2 for windows
# Start empty word doc
cat("<body>", file="exOut.doc", sep="\n")
# select all png files in working directory
for(i in list.files(pattern="*.png"))
{
temp <- paste('<img src=', i, '>')
cat(temp, file="exOut.doc", sep="\n", append=TRUE)
}
cat("</body>", file="exOut.doc", sep="\n", append=TRUE)
# Some example plots
for(i in 1:5)
{
png(paste0("ex", i, ".png"))
plot(1:5)
title(paste("plot", i))
dev.off()
}
# Start empty word doc
cat(file="exOut.doc")
# select all png files in working directory
for(i in list.files(pattern="*.png"))
{
temp <- paste('<img src=', i, '>')
cat(temp, file="exOut.doc", sep="\n", append=TRUE)
}
You will then need to embed the figures, either using the drop down menus or by writing a small macro that you can call with system
EDIT : small update to show explicit paths to output and figures
cat("<body>", file="/home/daff/Desktop/exOut.doc", sep="\n")
for(i in list.files(pattern="*.png"))
{
temp <- paste0('<img src=/home/daff/', i, '>')
cat(temp, file="/home/daff/Desktop/exOut.doc", sep="\n", append=TRUE)
}
Note that i used paste0 to remove the space between the path /home/daff/ and ex*.png.
Have you tried Rstudio and Markdown? You could put your code into chunks that load the files and save as word document. http://rmarkdown.rstudio.com/word_document_format.html
My chunk in Sweave:
<<fig=TRUE,echo=FALSE>>=
for(i in 1:10) {
plot(rep(i,10))
dev.new()
}
#
In the resulting pdf I get only one plot (from the first iteration). I would like to have all of the 10 plots printed. What am I doing wrong? I tried replacing dev.new() with frame() and plot.new() but nothing happened.
As #rawr suggests the easiest solution is to switch to knitr (there's really no reason at all not to!) and put fig.keep="all" in your code chunk options (if you switch to knitr you don't need fig=TRUE any more ... including figures works automatically, fig.keep="none" is the analogue of fig=FALSE)
Alternatively, if you want to stick with vanilla Sweave, check the Sweave manual p. 17:
A.9 Creating several figures from one figure chunk does not work
Consider that you want to create several graphs in a loop similar to
<<fig=TRUE>>
for (i in 1:4) plot(rnorm(100)+i)
#
This will currently not work, because Sweave allows only one graph per figure chunk. The simple reason is that Sweave opens a postscript device before executing the code and closes it
afterwards. If you need to plot in a loop, you have to program it along the lines of
<<results=tex,echo=FALSE>>=
for(i in 1:4){
file=paste("myfile", i, ".eps", sep="")
postscript(file=file, paper="special", width=6, height=6)
plot(rnorm(100)+i)
dev.off()
cat("\\includegraphics{", file, "}\n\n", sep="")
}
#