0

A previous post on StackOverflow had a very useful guide on how to use a template .Rnw file to produce multiple reports. I'd like to duplicate this, except I'd have 4 loops rather than just the one used in the example.

In my case, these are the loops that I'm using to produce the reports:

  • outermost loop: looping through a vector that contains the names of the variables I want to analyze

  • inner 3 loops: looping through different seasons/geographic locations

Here is a sample of the template code, which works without any issues when I supply all of the necessary variables that would be provided in the loops:

\begin{document}
This is a test in which the \texttt{\Sexpr{varname}} variable is used in this report. If successful, further reports can be generated using a loop with this same script!

First, a plot of the CDFs, with Kolmogorov-Smirnov statistics:
\begin{figure}[h]
\centering
<<cdf-plots,dev='png',out.width='0.5\\linewidth',echo=FALSE,warning=FALSE,fig.align='centering'>>=
 chart_stats(varname,data_vec,labs,season,s,h,colvec=colvec,cdf_plot=TRUE)
 cap1=paste('Cumulative distribution functions for the counts,',season,s,h)
@
\caption{\Sexpr{cap1}}
\end{figure}
<<ks_calc,warning=FALSE,results='asis',echo=FALSE>>=
library(xtable)
ks=chart_stats(varname,data_vec,labs,season,s,h,ks_test=TRUE,dval=TRUE)
cap=paste('D-values for',season,h,s)
print(xtable(ks,caption=cap))
@

For the sake of being able to see my output, each file is currently generated as a separate .tex file as shown:

library(knitr)
setwd("~/data_netcdf")
load("loaded_data.Rdata")
source("~/tempestextremes/test/chart_stats.R")

data_vec<-c("ERA", "climo", "2xCO2","SSTplus2","SSTplus2_2xCO2")

seasons_vec<-c("DJF","JJA","MAM","SON")
sec=c("ATL","PAC")
hemi=c("NH","SH")
var=c('centlat','centlon','area')

for (varname in var){
  }
  for (season in seasons_vec){
    for (h in hemi){
      for (s in sec){
        output_name=paste(varname,'_',season,'_',h,'_',s,'_report.tex',sep="")
        knit2pdf("~/data_netcdf/report_test.Rnw",output=output_name)
      }
    }   
  }
}

There is a knitr example that makes use of child files to combine outputs into one document, which sounds similar to what I'd like to do, and here's what I've tried:

<<test-main,include=FALSE>>= 
[removed for length]

#testing on just one variable name
var=c('centlat')
for (varname in var){
  out=NULL
  for (season in seasons_vec){
    for (h in hemi){
      for (s in sec){
        out=c(out,knit_child("~/data_netcdf/report_test.Rnw"))
      }
    }
  }
}
@

\Sexpr(paste(out,collapse='\n'))

but I'm getting the following error, probably due to the fact that I have multiple levels of loops which are all using the same chunk label names as references for the figures:

Error in parse_block(g[-1], g[1], params.src) : 
  duplicate label 'cdf-plots'
Calls: knit ... process_file -> split_file -> lapply -> FUN -> parse_block

Can someone please explain this error message? Do I need to somehow alter the label names so that it differentiates between each time it loops? Or should I implement the 3 inner loops within the template file? Or, perhaps combining all of the .tex files after the fact?

I would appreciate help in figuring out the best workflow for this.

Community
  • 1
  • 1
  • 1
    You do need to differentiate the label names so that they are different every time it loops. Is this helping you http://stackoverflow.com/questions/12095113/r-knitr-possible-to-programmatically-modify-chunk-labels ? – Tutuchan Aug 16 '16 at 09:11
  • I've used `knit_expand` to successfully evaluate a `prefix` variable that I set within the loop, but I can't figure out how I'd combine that with `knit_child` (or if I should be even using `knit_child`). Any thoughts? – pianoplunkster Aug 17 '16 at 20:02
  • 1
    Looks like you found the solution! So as you saw, you don't need `knit_child` if you use `knit_expand`. – Tutuchan Aug 18 '16 at 08:00

1 Answers1

1

I have come up with a solution! Some notes:

1) the template file cannot have the \begin{document}...\end{document} tags or anything in the preamble, this must be in the main .Rnw file.

2) As of this moment, it only works for a single variable (rather than looping over the vector of variables), but it's a trivial matter to scale this up.

So here is an example of the template:

<<{{prefix}}-setup>>=
varname='{{varname}}'
season='{{season}}'
h='{{h}}'
s='{{s}}'
@

First, a plot of the CDFs, with Kolmogorov-Smirnov statistics:
\begin{figure}[h]
\centering
<<'{{prefix}}-cdf-plots',dev='png',fig.lp='{{prefix}}',out.width='0.5\\linewidth',echo=FALSE,warning=FALSE,fig.align='centering'>>=
colvec=c("blue","red","green","purple","pink")
chart_stats(varname,data_vec,labs,season,s,h,colvec=colvec,cdf_plot=TRUE)
cap1=paste('Cumulative distribution functions for the counts,',season,s,h)
@
\caption{\Sexpr{cap1}}
\end{figure}

And then the main document:

\documentclass{article}
\usepackage[margin=0.5in]{geometry}
\begin{document}

<<test-main,include=FALSE>>=
library(knitr)
setwd("~/data_netcdf")
load("loaded_data.Rdata")
source("~/tempestextremes/test/charts_stats.R")
[other stuff]
@
...
<<generate-code,echo=FALSE>>=
  varname='centlat'
  out=NULL
  for (season in seasons_vec){
    for (h in hemi){
      for (s in sec){
        prefix=paste(season,h,s,sep="_")
        out=c(out,knit_expand("~/data_netcdf/report_test_1.Rnw"))
      }
    }
  }
@

\Sexpr{paste(knit(text=out),collapse='\n')}
\end{document}

I should note that the inspiration came from the knitr-examples section, specifically this one.