RMarkdownでの出力結果をアウトプットの種類に応じて変更させる

この記事はドキュメンテーションツールAdvent Calendar (http://www.adventar.org/calendars/1196) の12日目です。

@kazutan さんがちまちまとやっている[RMarkdown Advent Calendar](http://qiita.com/advent-calendar/2015/rmarkdown) に[こんな記事](http://qiita.com/kazutan/items/7e19323dae46e523adc5)がありました。この記事ではワード形式での出力の話がされているのですが、これを読んで、そういえばこんな記事があったねというのを、既にみなさんご存知かもしれませんが検証がてら紹介します（元記事は１年以上も前に書かれています）。

元記事: [rmarkdown: Alter Action Depending on Document | TRinker's R Blog](https://trinkerrstuff.wordpress.com/2014/11/18/rmarkdown-alter-action-depending-on-document/)

みなさん、**`{ggvis}`**を利用したインタラクティブな可視化もいいですが、PDFとしてファイルは保存しておきたいし印刷する図は**`{ggplot2}`**で描画したかったりしますよね。**しますよね**。

### 💡 要約

ちょっと書きなぐりのようになっているのではじめにこの記事の内容をまとめます。

-   RMarkdownでの出力形式は、必要に応じて切り替えることが可能（いちいち書き換えなくてもよい）
-   チャンク内で実行するRコードは`knitr::opts_knit()`と`switch()`で自由自在に切り替えられる

**この記事もRMarkdownで書いているので、ダウンロードしてお試しできるよう、[gistにあげてあります](https://gist.github.com/uribo/d0e5e403bf8cc92af208)。**

🔜 複数の形式でのアウトプット
----------------------------

RMarkdownでは、YAMLに記載された形式でアウトプットの種類を決めているわけですが、この時に記述する**outputの項目は何も特定の何か（markdown, html, word, latex）に限っていなくても良い**、という話です。**RStudioのKnit HTMLボタンを押した時はYAML outputの第一項目に従ってoutput**されますが、実際にRMarkdownファイルを各種の異なるファイルに変換する**`render()`を利用して、YAMLヘッダー部に記載されているアウトプットの種類すべてを出力することが可能**です。YAMLヘッダーで宣言したアウトプットの種類すべてでの出力を一度に行う場合は、**`render()`出力形式を決める*output_format*にallを指定すれば良い**だけです。

``` yaml
output: 
  html_document:
    toc: false
  md_document:
    variant: markdown
  pdf_document:
    toc: false
  word_document:
    toc: false 
```

上の例では、HTML、markdown、PDF(LaTeX)、ワードのファイルを出力することを宣言しています。先に述べましたが、この状態でRStudioのKnitボタンを押すとHTMLの出力を行います。ではYAMLで宣言したすべてのファイルの種類を出力しましょう。次のコードを実行するするだけです。

``` r
rmarkdown::render("input-output.Rmd", "all")
```

YAMLで宣言したアウトプット形式すべてのファイルを出力するにはLaTeXのプリアンブル設定は、header-includesで行うか、別途styファイルを用意してください（日本語のPDFを出力するのに必要かも）。


### 👻 アウトプットの種類に応じて出力を変更させる

さて本題です。複数の形式でのアウトプットができるのは素晴らしいですが、RMarkdown (Pandoc) で出力するフォーマットすべてで図などの出力を行う際の互換性を取るのが難しかったりします。

例えば `DT::datatable()`はHTMLの出力で実行されますが、markdownやPDFなどでは出力できません。

``` r
DT::datatable(trees)
```

を実行すると

> Error: Functions that produce HTML output found in document targeting markdown_github output. Please change the output type of this document to HTML.

と怒られます。同様に**`{ggvis}`**はHTMLでおk。PDFでNGだったります。

そこで、アウトプットの形式に応じて実行する結果や処理する内容を変更させれたら良いよね、という話になります。やり方は以外と簡単で、あらかじめアウトプットの形式を取得しておいて、結果を変えたい処理を行う際に`switch()`で条件分岐を行う、というだけです。このようにします。

上の例では、出力されたファイルごとに異なる結果を出力します。

関数の処理内容を分岐させることも可能です。

``` r
switch(out_type,
       markdown_github = trees %>% head(),
       html = DT::datatable(trees),
       docx = trees %>% head() %>% formattable::formattable(),
       latex = trees %>% xtable::xtable())
```


アウトプットの種類に応じて、データフレームの内容を表示する関数を変えた例です。次は図の変更を行いましょう。

``` r
library(ggvis)
pressure %>% ggvis(~temperature, ~pressure, fill = ~temperature) %>% layer_points()
```

> Error: Functions that produce HTML output found in document targeting markdown_github output. Please change the output type of this document to HTML.

実行した**`{ggvis}`**の図を埋め込むにも、HTML以外だと怒られます。そこで、HTML以外の出力では **`{ggplot2}`**を利用することにします。

``` r
library(ggvis)
library(ggplot2)
p_ggplot2 <- mtcars %>% ggplot(aes(mpg, wt, colour = factor(cyl))) + geom_point()
p_ggvis   <- mtcars %>% ggvis(~mpg, ~wt, fill = ~factor(cyl)) %>% layer_points()

switch(out_type,
       markdown_github = p_ggplot2,
       html            = p_ggvis,
       docx            = p_ggplot2,
       latex           = p_ggplot2)
```



### 🌱 devオプションの活用

ちょうどSVG形式での図の出力を紹介した記事があったので、需要のなさそうな話ですが、**HTMLでSVGを、PDFではSVGの埋め込みが面倒なのでPDFを埋め込みたい**という場合の対応例を紹介します。この場合も`switch()`を使います。

[svglite 1.0.0を使ってみる - Technically, technophobic.](http://notchained.hatenablog.com/entry/2015/12/11/103354)

YAMLはこのように宣言します。

``` yaml
output: 
  html_document:
    dev: svg
  pdf_document:
    dev: cairo_pdf
```

実行するRコードは下記のように。

``` r
library(svglite)
switch(out_type,
       html = knitr::opts_chunk$set(dev     = "svglite",
                                    fig.ext = "svg"))
```

``` r
plot(pressure)
```

コウモリのように生きていきましょう。
Enjoy! :+1: