Create parametric R markdown documentation?
Asked Answered
S

4

11

I want to iterate over a list of result-sets in my R markdown file. When I produce the output I want to include some text like headers with the name of the result set.

One hacky solution I have found is to hardcode the html output directly in the documentation like this

## All results

```{r loopResults, echo=FALSE, results='asis'}
results = list(result1 = data.frame(x=rnorm(3), y=rnorm(3)), result2=data.frame(x=rnorm(3), y=rnorm(3)))

for(res in names(results)) {
  cat(paste("<h3>Results for: ", res, "</h3>>"))

  plot(results[[res]]$x, results[[res]]$y)
}

This doesn't seem to be the right way to do things, especially since I want to create PDF documents via pandoc at time and would have to change the hard-coded expressions. (I have currently convenience functions like h3(text, type)).

Is there a better way of doing this?

Shyster answered 19/2, 2013 at 13:58 Comment(3)
Since you are using pandoc you might find the package pander useful. In particular the function ?pander::pandoc.header might be of interest.Trackandfield
This is the right way. The real problem here, I believe, is that you should not use <h3>; you should use the markdown syntax ### for h3 instead: en.wikipedia.org/wiki/Markdown#HeadingsAdmire
I believe the cleanest solution will depend on the content inside the loop. If you have a lot of code inside the loop, then implementing everything within your Rmd will be the cleanest. If you have a lot of markup inside the loop, then using a brew template as an intermediate will lead to a cleaner solution.Allveta
A
8

I would use a combination of brew and knitr to achieve this. I would create a brew template called doc.brew which looks like this

<% for (res in names(results)) { -%>

### Results for: <%= res %>

```{r}
plot(results[["<%= res %>"]]$x, results[["<%= res %>"]]$y)
```

<% } %>

You can now run the following code to get your desired output

results = list(
  result1 = data.frame(x=rnorm(3), y=rnorm(3)), 
  result2=data.frame(x=rnorm(3), y=rnorm(3))
)
brew::brew('doc.brew', 'doc.Rmd')
knit2html('doc.Rmd')
Allveta answered 19/2, 2013 at 21:51 Comment(1)
This is most consistent with what I want to do. Although the example code was short, the application I'm looking at is going to be longer. Too bad the templating is so verbose, the code looks very cluttered.Shyster
S
4

A possibility is to make your markdown file generate markdown instead of HTML. For example :

## All results

```{r loopResults, echo=FALSE, results='asis'}
results = list(result1 = data.frame(x=rnorm(3), y=rnorm(3)), result2=data.frame(x=rnorm(3), y=rnorm(3)))

for(res in names(results)) {
  cat(paste("Results for: ", res,"\n"))
  cat("=========================\n")
  plot(results[[res]]$x, results[[res]]$y)
  cat("\n")
}
```

If you apply the knit() function to it in R, you will get the following Markdown file :

## All results

Results for:  result1 
=========================
![plot of chunk loopResults](figure/loopResults1.png) 
Results for:  result2 
=========================
![plot of chunk loopResults](figure/loopResults2.png) 

And you should be able to use pandoc to produce HTML or LaTeX from this file ?

Satori answered 19/2, 2013 at 14:6 Comment(0)
B
4

Following https://gist.github.com/yihui/3145751 you can write a child template for inclusion and loop over that.

foosub.Rmd

Results for `r res`
---------------------------

```{r}
 plot(results[[res]]$x, results[[res]]$y)
```

foo.Rmd

```{r loopResults, include=FALSE}
results = list(result1 = data.frame(x=rnorm(3), y=rnorm(3)), result2=data.frame(x=rnorm(3), y=rnorm(3)))
out=NULL

for(i in 1:length(results)) {
res = names(results)[i]
out = c(out, knit_child('foosub.Rmd', sprintf('foosub-%d.txt', i)))
}
```

`r paste(out, collapse = '\n')`

The code chunk in the master file doesn't produce any output itself, it just renders the child documents, one for each of your results, and stores it all up in out (which is why it has include=FALSE). All the formatted output is collected in the out variable and inserted by the last line.

Its a bit awkward, but it does encourage modularity, but it doesn't seem as simple as being able to do:

```{r}
for(i in 1:10){
```

Plot `r i`
-----------

```{r}
plot(1:i)
}
```

which you cant.

Bant answered 19/2, 2013 at 14:21 Comment(0)
P
0

An alternative solution with pander:

<% for (res in names(results)) { %>
### Results for: <%= res %>

<%=
plot(results[[res]]$x, results[[res]]$y)
%>
<% } %>

And just Pandoc.brew this in one run to get what you were up to:

> Pandoc.brew('doc.brew')

### Results for: result1

![](/tmp/Rtmp4yQYfD/plots/568e18992923.png)

### Results for: result2

![](/tmp/Rtmp4yQYfD/plots/568e6008ed8f.png)

Or generate HTML/docx/etc. in one run:

> Pandoc.brew('doc.brew', output = tempfile(), convert = 'html')
> Pandoc.brew('doc.brew', output = tempfile(), convert = 'docx')
Prescind answered 9/3, 2013 at 10:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.