2012-08-23 15 views
36

私は、データセットのさまざまなサブセットで同じ分析セットを実行するレポートを生成するために、knitrを使用しようとしています。プロジェクトには2つのRmdファイルが含まれています。最初のファイルはワークスペースとドキュメントを設定するマスタードキュメントで、2番目のファイルは解析を実行し、関連する図を生成するチャンクのみを含んでいます。R knitr:プログラムでチャンクラベルを変更することはできますか?

マスターファイルを編成して、各データサブセットの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'} 
``` 

分析-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失敗時間。この問題は、ユニークなラベルが自動的に生成されるため、チャンクの名前を残しておくことで回避できます。しかし、これは理想的ではありません。なぜなら、チャンクラベルを使用して、エクスポートされたプロットの有益なファイル名を作成したいからです。


潜在的な解決策は、チャンクのラベルに現在のシリンダーを追加し、簡単な関数で使用して次のようになります。

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

をしかし、それknitrがチャンクのラベル位置に式を評価します表示されません。 。


私はまた、現在のチャンクのラベルを変更するカスタムchunk hookを使用してみました:

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

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


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

答えて

35

この投稿に出会う他の誰かのために、@Yihuiは関数の導入によってknitr 1.0でこの質問にformal solutionを提供したことを指摘したいと思います。それは素晴らしい作品と私​​のワークフローを本当に簡素化しています。例えば

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")) 
``` 
+0

このアプローチを使用しましたが、テンプレートで 'echo = FALSE'を使用するとコードが処理されません。あなたは同じ行動に気付いたことがありますか? –

+0

**編集**:このアプローチを** bookdown **パッケージとともに使用し、テンプレートで 'results = 'asis''と' echo = FALSE'を使用するとコードが処理されないことに気付きました。ソリューションは、それぞれの出力を別々のコード・チャンクに入れることです。 –

14

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

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

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

ブロックは内部的には名前で重複する名前を持つことはできません。修正は、knitrに重複名を持つすべてのチャンクにチャンク番号を追加させることです。ラベルの代わりにチャンク番号で参照することもできますが、それは私にとってははるかに大きな変更に見えます。

+7

あなたの理解は絶対に正しいです。これはニットがいくつかの変更を必要とする説得力のあるケースです。私は今あなたのプルの要求を見ています。ありがとう! –

+0

@Rolo、knitrの内部の働きについてのあなたの説明は非常に役に立ちました。そして、あなたの[ソリューションを実装するコード](https://github.com/yihui/knitr/issues/368)を書く時間をとって本当にありがたいです。 @Yihui、あなたはこの変更を含めると思いますか?これは私が達成しようとしていたものの90%を扱い、修正されたチャンクラベルを除いて同一のRmdファイルのコピーを維持する必要がなくなります。理想的な解決法は、そうであれば 'for(i in unique(mtcars $ cyl))knit_child(" analysis-template.Rmd "、label.suffix = i)'のようなものを許します。 – aaronwolen

+1

はい、私はプルリクエストを受け入れる傾向があると思います。私はまだいくつかの代替ソリューションを持っているので、私はもう少し分を私に与えてください。この問題を解決するのは簡単ですが、使用するソリューションを決めることは難しいです。 –

関連する問題