Can Sweave Produce Many PDFs Automatically

Can Sweave produce many pdfs automatically?

You can use something like a for loop with a global variable changing, which controls which city you want to weave into the report; see the other post Run Sweave or knitr with objects from existing R session

The code will be like (suppose cities is a character vector, and I use the knitr package as an example because you can specify the filename of the output):

for (city in cities) {
knit('city_template.Rnw', output = paste('report_', city, '.tex', sep = ''))
}

Inside city_template.Rnw, you have a chunk like

<<do-my-job>>=
make_plot(city, ...)
whatever(city, ...)
@

Then you will get a series of tex files named by the cities, and the rest of your job is to compile them to PDF (not possible for RStudio to compile multiple tex files, AFAIK, but it is trivial to do it in command line or in R with texi2dvi()).

There is one thing you need to be careful -- you have to use a different figure prefix (the option fig.path) for each output file, otherwise different cities can override each other's figure output. In knitr, this can be done by like this:

<<setup, echo=FALSE>>=
opts_chunk$set(fig.path = paste('my-prefix-', city, sep = ''))
@

I believe this should be safe to produce many reports with a loop.

BTW, you can certainly achieve the same goal with Sweave; perhaps you will know why I developed knitr later (this is off-topic, so I won't expand here).

Using loops with knitr to produce multiple pdf reports... need a little help to get me over the hump

You don't need to re-define the data in the .Rnw file and I think the warning is coming from the fact that you are putting the output name together with Hospital (the full vector of hospitals) rather than hosp (the loop index).

Following your example, testingloops.Rnw would be

\documentclass[10pt]{article}
\usepackage[margin=1.15 in]{geometry}
<<loaddata, echo=FALSE, message=FALSE>>=
subgroup <- df[ df$Hospital == hosp,]
@

\begin{document}
<<setup, echo=FALSE >>=
opts_chunk$set(fig.path = paste("test", hosp , sep=""))
@

Some infomative text about hospital \Sexpr{hosp}

<<plots, echo=FALSE >>=
for(ward in unique(subgroup$Ward)){
subgroup2 <- subgroup[subgroup$Ward == ward,]
# subgroup2 <- subgroup2[ order(subgroup2$Month),]
savename <- paste(hosp, ward)
plot(subgroup2$Month, subgroup2$Outcomes, type="o", main=paste("Trend plot for", savename))
}
@
\end{document}

and the driver R file would be just

##  make my data
Hospital <- c(rep("A", 20), rep("B", 20))
Ward <- rep(c(rep("ICU", 10), rep("Medicine", 10)), 2)
Month <- rep(seq(1:10), 4)
Outcomes <- rnorm(40, 20, 5)
df <- data.frame(Hospital, Ward, Month, Outcomes)

## knitr loop
library("knitr")
for (hosp in unique(df$Hospital)){
knit2pdf("testingloops.Rnw", output=paste0('report_', hosp, '.tex'))
}

How to create multiple PDFs with different content from a single data frame?

From the question, I'm not entirely sure about the expected output, but there concept is clear. And although the task itself is quite simple, surprisingly many things can go wrong.

Code:

code.R

library(knitr)
library(ggplot2)

dir.create(path = "output/")
opts_knit$set(base.dir = "output/")

for(i in 1:nrow(mtcars)) {
filename <- rownames(mtcars)[i]
knit(input = "template.Rnw", output = paste0("output/", filename, ".tex"))
tools::texi2pdf(paste0("output/", filename, ".tex"), clean = TRUE)
file.copy(from = paste0(filename, ".pdf"), to = paste0("output/", filename, ".pdf"))
# file.remove(paste0(filename, ".pdf")) # this will DELETE filename.pdf from the current working directory (should be safe because we just created this file)
}

template.Rnw

\documentclass{article}
\begin{document}
<<>>=
ggplot(mtcars[i,], aes(x = cyl, y = disp) ) + geom_point()
@
\end{document}
  • We need to set base.dir because the current working directory is one level above the directory where the document is created. This would lead to wrong figure paths: knitr produces the plots in figure/ but they should be in output/figure/. Consequently, compilation will fail.
  • For some reason knit2pdf cannot compile the generated intermediate TEX file. Therefore I use knit to produce a TEX file and then tools::texi2pdf to compile this file to PDF.

Note how variables from code.R are visible to the code in the template document. That's why i can be used in template.Rnw.

Figure numbers generated by Sweave/R and why only (PDF)LaTeX

Your example is not reproducible because we don't have the file apples.d, so we can only guess why the plot goes wrong. Please see:

How to make a great R reproducible example?

on how to make a reproducible example.

Please note that Sweave is not a functionality of Rstudio or Tinn-R, it is an R function (Sweave()) that can be run from command line or with arguments from the R executable. This might be helpful to know if you are searching for information.

As for your questions:

  1. The names of plots always have the form FILENAME-CHUNKLABEL.pdf or eps, where the chunk label can be set as option to the Sweave chunk (it's the first argument). If you don't set a chunk name the plots will be enumerated.
  2. You can use eps with the option eps=true. I am pretty sure that by default both eps and pdf are produced though. As for compiling, Sweave does not compile by itself, it creates a .tex file that you can use in whatever way you want. In R 2.14 there is an option to run pdfLaTeX on the produced .tex file automatically,. The way Rstudio and Tinn-R compile is probably by using an pdfLaTeX call after Sweave. You can do it manually if you want to do it differently.
  3. Without a reproducible example we can only guess. What is going wrong? You could set the limits of the plot with the xlim and ylim arguments but that shouldn't be what is going wrong here.

Edit:

In response to edited question with data. First just a tip. This way of giving the data isn't the most useful way of doing it. We can of course reproduce this but it is much easier if you give the data in a way we can run immediately. e.g.:

test.frame<-data.frame(year=8:11, value= c(12050,15292,23907,33991))

As for the plot, you mean the labels on the y axis? This can be changed by omiting axes in the plot call and setting them manually with the axis() function:

with(test.frame,plot(year,value,axes=FALSE))
axis(1)
axis(2,test.frame$value,las=1)

This does look a bit weird if the ticks aren't constantly distributed over the axis though. Better would be:

with(test.frame,plot(year,value,axes=FALSE))
axis(1)
axis(2,seq(10000,35000,by=5000),las=1)

sweave and ggplot2: no pdfs generated at all

qplot() produces objects, not a graphic output. It might seem like it does when you run it, but that's because without assignment, R is automatically printing the output of qplot(). To integrate it into Sweave, either wrap print() around qplot(), or assign the output of qplot() to something, then wrap that in print().

...
<<fig = T, echo = F>>=
library(ggplot2)
x=rnorm(100)
p <- qplot(x)
print(p)
@
...

That should work. I use ggplot2 graphics in my sweave docs all the time.



Related Topics



Leave a reply



Submit