Создать параметрическую документацию R markdown?

Я хочу перебрать список результирующих наборов в файле R markdown. Когда я создаю вывод, я хочу включить некоторые текстовые заголовки с именем набора результатов.

Одно хакерское решение, которое я нашел, - это жестко кодировать вывод html непосредственно в документации, подобной этой

## 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)
}

Это не похоже на правильный способ сделать что-то, тем более, что я хочу создавать PDF-документы через pandoc вовремя и изменить жестко закодированные выражения. (У меня есть функции удобства, такие как h3 (текст, тип)).

Есть ли лучший способ сделать это?

Ответ 1

Для достижения этой цели я бы использовал комбинацию brew и knitr. Я бы создал шаблон brew с именем doc.brew, который выглядит как

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

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

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

<% } %>

Теперь вы можете запустить следующий код, чтобы получить желаемый результат

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')

Ответ 2

Возможность состоит в том, чтобы сделать ваш файл уценки порождать уценку вместо HTML. Например:

## 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")
}
```

Если вы примените функцию knit() к ней в R, вы получите следующий файл Markdown:

## All results

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

И вы должны иметь возможность использовать pandoc для создания HTML или LaTeX из этого файла?

Ответ 3

Следуя https://gist.github.com/yihui/3145751, вы можете написать дочерний шаблон для включения и перебрать его.

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')`

Блок кода в главном файле не производит никакого вывода, он просто отображает дочерние документы, по одному для каждого из ваших результатов, и сохраняет все в out (поэтому он имеет include=FALSE). Все отформатированные выходные данные собираются в переменной out и вставляются последней строкой.

Это немного неудобно, но оно поощряет модульность, но это не так просто, как в состоянии сделать:

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

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

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

который вы не можете.

Ответ 4

Альтернативное решение с pander:

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

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

И просто Pandoc.brew за один проход, чтобы получить то, что вы делали:

> Pandoc.brew('doc.brew')

### Results for: result1

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

### Results for: result2

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

Или сгенерировать HTML/docx/etc. за один проход:

> Pandoc.brew('doc.brew', output = tempfile(), convert = 'html')
> Pandoc.brew('doc.brew', output = tempfile(), convert = 'docx')