50

knitrを使用して、データセットの異なるサブセットに対して同じ分析セットを実行するレポートを生成しようとしています。プロジェクトには2つのRmdファイルが含まれています。最初のファイルはワークスペースとドキュメントを設定するマスタードキュメントであり、2番目のファイルには分析を実行して関連する図を生成するチャンクのみが含まれています。

私がやりたいのは、マスターファイルを編成することです。マスターファイルは、データサブセットごとに2番目のファイルを呼び出し、結果を1つのドキュメントに含めます。以下は簡単な例です。

マスタードキュメント:

# My report

```{r}
library(iterators)
data(mtcars)
```

```{r create-iterator}
cyl.i <- iter(unique(mtcars$cyl))
```

## Generate report for each level of cylinder variable
```{r cyl4-report, child='analysis-template.Rmd'}
```

```{r cyl6-report, child='analysis-template.Rmd'}
```

```{r cyl8-report, child='analysis-template.Rmd'}
```

analysis-template.Rmd:

```{r, results='asis'}
cur.cyl <- nextElem(cyl.i)
cat("###", cur.cyl)
```

```{r mpg-histogram}
hist(mtcars$mpg[mtcars$cyl == cur.cyl], main = paste(cur.cyl, "cylinders"))
```

```{r weight-histogam}
hist(mtcars$wt[mtcars$cyl == cur.cyl], main = paste(cur.cyl, "cylinders"))
```

問題は、knitrが一意でないチャンクラベルを許可しないためanalysis-template.Rmd、2回目に呼び出されたときに編み物が失敗することです。一意のラベルが自動的に生成されるため、チャンクに名前を付けないでおくと、この問題を回避できます。ただし、これは理想的ではありません。チャンクラベルを使用して、エクスポートされたプロットの有益なファイル名を作成したいからです。


考えられる解決策は、現在のシリンダーをチャンクラベルに追加する単純な関数を使用することです。

```r{paste('cur-label', cyl, sep = "-")}
```

しかし、knitrがチャンクラベルの位置で式を評価するようには見えません。


また、現在のチャンクのラベルを変更するカスタムチャンクフックを使用してみました。

knit_hooks$set(cyl.suffix = function(before, options, envir) {
    if (before) options$label <- "new-label"
})

しかし、チャンクラベルを変更しても、生成されたプロットのファイル名には影響しなかったため、knitrが新しいラベルを利用しているとは思いませんでした。


同じ子ドキュメントを複数回呼び出すことができるようにチャンクラベルを変更する方法についてのアイデアはありますか?それとも、これを達成するための代替戦略ですか?

4

3 に答える 3

47

この投稿に出くわした他の人のために、@ Yihuiが関数の導入により、knitr1.0でこの質問に対する正式な解決策knit_expand()を提供したことを指摘したいと思います。それはうまく機能し、私のワークフローを本当に単純化しました。

たとえば、以下は、のすべてのレベルについて以下のテンプレートスクリプトを処理し、そのたびに(テンプレート内の)のすべてのインスタンスを現在の値にmtcars$cyl置き換えます。{{ncyl}}

# My report

```{r}
data(mtcars)
cyl.levels <- unique(mtcars$cyl)
```

## Generate report for each level of cylinder variable
```{r, include=FALSE}
src <- lapply(cyl.levels, function(ncyl) knit_expand(file = "template.Rmd"))
```

`r knit(text = unlist(src))`

レンプレート:

```{r, results='asis'}
cat("### {{ncyl}} cylinders")
```

```{r mpg-histogram-{{ncyl}}cyl}
hist(mtcars$mpg[mtcars$cyl == {{ncyl}}], 
  main = paste({{ncyl}}, "cylinders"))
```

```{r weight-histogam-{{ncyl}}cyl}
hist(mtcars$wt[mtcars$cyl == {{ncyl}}], 
  main = paste({{ncyl}}, "cylinders"))
```
于 2013-01-16T21:26:59.563 に答える
15

**のすべてのチャンクを無名にすると、つまり```{r}機能します。もちろん、これはあまりエレガントではありませんが、現在のチャンクのラベルを変更できないという2つの問題があります。

  1. コードブロックが実行される前に、ファイルが解析されます。コードが実行される前、またはカスタムフックが呼び出される前に、パーサーはすでに重複ラベルを検出しています。
  2. チャンクオプション(ラベルを含む)はフックが呼び出される前に処理されるため(論理:フックをトリガーするオプションです)、フックはラベルを変更できなくなります。

名前のないブロックが機能するという事実は、内部的にラベルunnamed-chunk-+チャンク番号を取得することです。

内部でknitrがラベルによってブロックを参照するため、ブロックに重複する名前を付けることはできません。修正は、knitrに重複した名前を持つすべてのチャンクにチャンク番号を追加させることである可能性があります。または、ラベルではなくチャンク番号でそれらを参照しますが、それは私にははるかに大きな変更のようです。

于 2012-08-23T18:27:41.713 に答える
1

ここで提起された同様の質問があります。プログラムでrチャンクを作成し、knit_expand(text =)とr paste(knitr::knit(text = paste(out, collapse = '\n')))メソッドを使用して、入力プロットの任意のリストに基づいてフレックスダッシュボード(非常に便利)で使用する出力を編成することができました。

于 2019-04-09T00:58:27.920 に答える