Create parametric R markdown documentation?

2019-01-14 08:22发布

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?

4条回答
可以哭但决不认输i
2楼-- · 2019-01-14 08:54

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 ?

查看更多
【Aperson】
3楼-- · 2019-01-14 08:55

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.

查看更多
We Are One
4楼-- · 2019-01-14 09:05

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')
查看更多
仙女界的扛把子
5楼-- · 2019-01-14 09:13

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')
查看更多
登录 后发表回答