R
Markdown
Knitr

R Markdownによるレポート生成


はじめに

システムの稼働状況とかミドルウェアの統計情報とかを手っ取り早く可視化するためにRを使ってみようということで書き始めた連載企画です。今回はレポート生成編です。

R Markdownというパッケージを使用すると、Word, PDF, HTML等の形式のレポート生成を自動化できます。Rでデータを集計してグラフを作ったとしても、それをExcelやWordにコピペしてレポートを作っていたのでは非常に効率が悪いです。そこをサクッとスマートにやりましょうという話です。

レポート生成の自動化の意義や、R Markdownの使い方等については、以下にすばらしい連載記事がありますので是非一読されることをお勧めします。

R Markdownで楽々レポートづくり

詳細は上の記事見ていただくのがよいと思うので、ここでは一通りレポート生成させてみる所を中心にまとめます。


関連記事

インフラ屋さんのためのR言語: 環境構築編

オフラインでのR環境構築 on RHEL

z/OSにRを導入してみた

インフラ屋さんのためのR言語: プログラミング編

R Markdownによるレポート生成 <= 当記事

R MarkdownのHTMLレポートをブラッシュアップ

R - ShinyによるWebアプリケーション作成: 基礎編

R - ShinyによるWebアプリケーション作成: shinydashboard編

R - ShinyによるWebアプリケーション作成Tips: shinydashboardでの画面遷移制御

R - ShinyによるWebアプリケーション作成Tips: UIオブジェクトの動的制御

R - Shinyアプリ/管理サーバー テンプレート


R Markdown概要

Rのコードで集計した結果(計算結果、グラフ、表など)を含めたレポートをMarkdown形式で作成するためのパッケージです。

生成できるレポートの形式は、Word, PDF, HTMLなどで、その他にも色々応用ができるようです。Word, HTMLしか試してみていませんが、個人的にはHTMLがかなり使えると思います。HTMLのレポートだと、インタラクティブに操作できるグラフなどが使えて、かなり使い勝手のよいレポートが作成できます。

参考: R Markdown


環境構築

R Markdownを使用するためには、R本体に加えて以下のモノが必要になります。

(1) rmarkdownパッケージ

(2) knitrパッケージ

(3) pandoc

rmarkdown, knitrは、Rのパッケージとして提供されているものですが、pandocはRとは独立したツールとして提供されているものです。knitrはRの処理結果を含むレポートを生成するために内部的に使用されます。

pandocというのは各種文書のフォーマット変換をしてくれる強力なツール(GPL: GNU General Public License として提供される)で、knitrは内部的にこの機能を利用します。

RStudioを使っていれば、これらのものは含まれていると思いますが、実行しようとしたときにpandocのバージョンが古いよと言われたことがあったので、パッケージのアップグレードと、最新版のpandocを個別にインストールしておくことをお勧めします。

参考:Pandoc

Pandocインストーラーのダウンロードは、上のサイトのInstallingのメニューから辿れます。

最終的に生成するレポート形式によっては、追加で別のパッケージ等が必要になる場合もあります(例えばPDF化にはLaTexのパッケージとか必要になるっぽい)。

ここでは、基本的にHTML形式のレポート生成を前提に話を進めます。


Markdownによるコーディング

xxx.Rmdというファイルを作成し、Markdown形式によりコーディングを行います。簡単なサンプルから見ていきましょう。

sample01.Rmd

---

title: "サンプル・レポート"
author: "Taguchi"
date: '`r format(Sys.time(), "%y/%m/%d %H:%M")`'
output:
html_document:
toc: yes
word_document:
toc: yes
---
```{r setup, include=FALSE}
library(ggplot2) # Graphic package
```

#Markdownサンプル
##本文

行内へのRコード埋め込み

今日は `r format(Sys.Date(), "%Y/%m/%d")` です

箇条書き

* 箇条書き1
* 箇条書き2

## グラフ
サンプルデータ(diamond)の箱ひげ図を表示

```{r}
graph_data <- ggplot(diamonds, aes(y=carat,x=cut, fill=cut))+geom_boxplot()
plot(graph_data)
```

##リンク
[R Markdown](http://rmarkdown.rstudio.com/)

上のようなコードを書いて、えいやっとレポート生成させると、以下のようなレポートが作成されます(レポート生成のやり方は後述)。

HTML文書生成例

image01.JPG

Word文書生成例

image02.JPG

便利ですねぇ。

Markdownによる書き方ついて少し補足します。

先ほどのサンプルの構造を見てみます。

image03.JPG

基本的にはこのような構造になります。

先頭にYAMLフロントマターと呼ばれる「---」で囲まれた領域があり、ここでタイトルや出力形式に関する設定を行います。ここでは、Word用(word_document)、HTML用(html_document)の2つのオプションを指定しています。(レポート生成時に何の形式でレポート生成させるかを選択します。)

その後、Markdown形式で記載する本文と、Rのコードを含むコードチャンク(バッククォートx3で囲まれた領域) が入り混じったコードが続きます。

インラインでRのコードを埋め込む場合は`r <Rコード>`という形で記述します。

レポートの本文や体裁はMarkdown形式で作成していき、グラフ描画やRによる集計結果など動的に変更される部分はコードチャンクやインラインコードなどを駆使して本文内に埋め込んでいくことになります。

デフォルトのままでは、Rのコード(コードチャンクの内容)がレポート上に出力されてしまうのでそれを消したいとか、章番号を付けたいとか色々手を加えたくなることが出てきます。

YAMLフロントマター、セットアップチャンク部分にもう少し手を加えてみましょう。

sample02.Rmd

---

title: "サンプル・レポート"
author: "Taguchi"
date: '`r format(Sys.time(), "%Y/%m/%d %H:%M")`'
output:
word_document:
fig_caption: yes
reference_docx: default
toc: yes
html_document:
fig_caption: yes
number_sections: yes
pandoc_args:
- --from
- markdown+autolink_bare_uris+tex_math_single_backslash-implicit_figures
theme: default
toc: yes
toc_depth: 3
---
```{r setup, include=FALSE}
library(ggplot2) # Graphic package
library(knitr) # markdown

options(scipen=100)

knitr::opts_chunk$set(echo = FALSE)
knitr::opts_chunk$set(eval = TRUE)
knitr::opts_chunk$set(tidy = TRUE)
knitr::opts_chunk$set(warning = TRUE)
knitr::opts_chunk$set(error = FALSE)
knitr::opts_chunk$set(message = FALSE)

Sys.setenv(tz="asia/tokyo")

```

#Markdownサンプル
##本文

行内へのRコード埋め込み

今日は `r format(Sys.Date(), "%Y/%m/%d")` です

箇条書き

* 箇条書き1
* 箇条書き2

## グラフ
サンプルデータ(diamond)の箱ひげ図を表示

```{r}
graph_data <- ggplot(diamonds, aes(y=carat,x=cut, fill=cut))+geom_boxplot()
plot(graph_data)

```

##リンク
[R Markdown](http://rmarkdown.rstudio.com/)

よく使いそうなオプションについて補足します。

YAMLフロントマター

number_sections :章に番号を付ける

toc_depth :目次に使用する章レベル(3を指定するとx.x.xまでを目次として追加)

pandoc_args... : HTML形式のレポートを生成すると、目次がハイパーリンクになっていてクリックすると該当の章に飛ぶようになっていますが、日本語の章タイトルだとうまくリンクが機能しません。このおまじないをしておくと、日本語でもリンクが機能するようになります。

R Markdownで楽々レポートづくり - 第4回 レポつく自由自在 ~R Markdownにまつわるエトセトラ~ によると...


pandocにはascii_identifiersというパースオプションがあり,これが有効にされていると識別子に非ascii文字を使えなくなります。pandocではヘッダ要素の文字列からHTMLのアンカー用の識別子を自動生成しますが,ここが非asciiだと識別子が生成されないというわけです。R Markdownではこのパースオプションがデフォルトで有効になっているので,この問題を回避するには,フロントマターで...


ということで、このようなおまじないをする必要があるらしいです。

※このおまじないについては、コメントで教えて頂きましたが、html_documentの場合pandoc_args...の代わりにmd_extensions: -ascii_identifiersという指定でOKのようです。こちらの方がシンプルでよいですね! 後述のsample04.Rmdに具体例を示してますのでご参照ください。

Rオプション

Markdownに限った話ではないですが、セットアップチャンクで必要なオプションを指定しておくとよいでしょう。Rのオプションはoptions()関数で指定できます。

scipen=100 :桁数が大きい数字があった場合に指数表記になるのを回避します。数字の意味を正確にとらえるのは面倒なので、まぁ大概100を指定しておけばOKとして指定する人が多いようですが、StatsBeginner: 初学者の統計学習ノート にある、以下の解説が分かりやすいです。


指数表示にした時に必要な文字列長と指数でない表示にした時に必要な文字列長の差がscipenで指定した数値を超えると指数表示になります。


knitrチャンクオプション

コードチャンクの先頭で、それぞれ ```{r echo=FALSE} というようにオプション指定することもできますが、毎回書くのも面倒なので先頭でデフォルト設定をしておくと楽です。knitrのopts_chunk$setで指定できます。

echo=FALSE :コードチャンクの内容をレポートに出力するかどうか。(デフォルトTRUEになってるのでFALSE指定しないとコードチャンクも一緒にレポートに表示される)

warning/error :Rのコードで発生したwarningやerrorを表示させるかどうか。


その他詳細はヘルプや以下のリンクが参考になると思います。

参考:

YAMLフロントマター(HTML document)

HTML Documents

Rオプション

関数options()

knitrチャンクオプション

knitr ではじめるデータ分析レポート作成 ~基礎編~

R markdown(knitr)パッケージのchunk optionまとめ


RStudioによるレポート生成

RStudioを使用している場合、レポート生成方法はいたって簡単です。

先に示した通り、xxx.Rmdというファイルを作成し、RStudioで開きます。

Knitボタンから生成したいレポート形式を選択すればOKです。

image04.JPG

HTMLのレポートを生成させる場合、ソースと同じ場所に、xxx.htmlというファイルが作成されます(sample02.Rmd => sample02.html)。


コマンド(バッチ)によるレポート生成

Rmdソースの開発中など、色々ロジックを変えながらレポート生成を繰り返す場合にはRStudioを使うと楽にレポートが生成できますが、ソースができあがって定期的にレポート生成を実行したり、日次や週次などで決まったレポートを生成させようと思うと、一々RStudio起動するのも手間になります。そこで、WindowsバッチからRScript.exeコマンドを使ってレポート生成する方法を記載します。

また、コマンド(バッチ)でレポートを生成する際に、何らかのパラメーターを外部から渡したいということはよくあると思います。ただ、引数によるパラメーター渡しは出来なさそうなので、代替として環境変数を利用する方法についても合わせて記載します。

(※コメントで引数渡しができることをご指摘頂きましたので、追記しました)

まず、レポートの元となるxxx.Rmdファイルを用意します。

先ほどのサンプルに少し追加して、環境変数を受け取るコードを追加してみます。

sample03.Rmd

---

title: "サンプル・レポート"
author: "Taguchi"
date: '`r format(Sys.time(), "%Y/%m/%d %H:%M")`'
output:
html_document:
fig_caption: yes
number_sections: yes
theme: default
toc: true
toc_depth: 3
pandoc_args: [
"--from", "markdown+autolink_bare_uris+tex_math_single_backslash-implicit_figures"
]
word_document:
fig_caption: yes
reference_docx: default
toc: yes
---
```{r setup, include=FALSE}
library(ggplot2) # Graphic package
library(knitr) # markdown
library(stringr)

options(scipen=100)

knitr::opts_chunk$set(echo = FALSE)
knitr::opts_chunk$set(eval = TRUE)
knitr::opts_chunk$set(tidy = TRUE)
knitr::opts_chunk$set(warning = TRUE)
knitr::opts_chunk$set(error = FALSE)
knitr::opts_chunk$set(message = FALSE)

Sys.setenv(tz="asia/tokyo")

env_Arg01 <- Sys.getenv("R_Arg01")
env_Arg02 <- Sys.getenv("R_Arg02")

```

#Markdownサンプル
##本文

行内へのRコード埋め込み

今日は `r format(Sys.Date(), "%Y/%m/%d")` です

箇条書き

* 変数1: `r env_Arg01`
* 変数2: `r env_Arg02`

## グラフ
サンプルデータ(diamond)の箱ひげ図を表示

```{r}
graph_data <- ggplot(diamonds, aes(y=carat,x=cut, fill=cut))+geom_boxplot()
plot(graph_data)

```

##リンク
[R Markdown](http://rmarkdown.rstudio.com/)

Sys.getenv()関数で、環境変数を受け取り、レポート中でその値を表示させるようにしています。

レポート生成はrender()というRの関数を使用して行いますので、render()を使ってレポートを生成する汎用的なRスクリプトファイルを用意します。

render.R


render.R

library(rmarkdown)

inputFile <- commandArgs(trailingOnly = TRUE)[1]
outputFile <- commandArgs(trailingOnly = TRUE)[2]

render(inputFile, output_format = "html_document", output_file = outputFile)


これは、引数として入力ファイル(xxx.Rmd)、出力ファイル(xxx.html)を想定し、html形式でレポートを生成するRスクリプトです。

そして、最後にこのRスクリプトを実行するためのバッチファイルを作成します。

render.bat


render.bat

@echo off

setlocal enabledelayedexpansion
cd %~dp0

rem ################# Usage
rem render.bat <inputFile> <outputFile> <Arg01> <Arg02>

rem ################# set parameters
set R_Inst_Dir=C:\x\R\R-3.3.1\bin
set logFile=RScript.log

set inputFile=%1
set outputFile=%2

set R_Arg01=%3
set R_Arg02=%4

rem ################# render
%R_Inst_Dir%\\Rscript.exe render.R %inputFile% %outputFile% >> %logFile% 2>&1


このバッチでは、引数として、入力ファイル(xxx.Rmd)、出力ファイル(xxx.html)、受け渡す環境変数(Arg01/Arg02)を想定し、スクリプト実行時のログはRScript.logファイルに出力するようにしています。

これらを使って、sample03.Rmdを元に、sample03_out.htmlを生成させてみましょう。


実行例

c:\y\RTest\Markdown01>render.bat sample03.Rmd sample03_out.html aaa 111

c:\y\RTest\Markdown01>cat RScript.log

processing file: sample03.Rmd
|............. | 20%
inline R code fragments

|.......................... | 40%
label: setup (with options)
List of 1
$ include: logi FALSE

|....................................... | 60%
inline R code fragments

|.................................................... | 80%
label: unnamed-chunk-1
|.................................................................| 100%
ordinary text without R code

output file: sample03.knit.md

"C:/PROGRA~2/Pandoc/pandoc" +RTS -K512m -RTS sample03.utf8.md --to html --from markdown+autolink_bare_uris+ascii_identif
iers+tex_math_single_backslash --output sample03_out.html --smart --email-obfuscation none --self-contained --from markd
own+autolink_bare_uris+tex_math_single_backslash-implicit_figures --standalone --section-divs --table-of-contents --toc-
depth 3 --template "C:\x\R\R-3.3.1\library\rmarkdown\rmd\h\default.html" --number-sections --variable "theme:bootstrap"
--include-in-header "C:\Users\IBM_AD~1\AppData\Local\Temp\RtmpyMBiXH\rmarkdown-str21a851886e96.html" --mathjax --variabl
e "mathjax-url:https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML" --no-highlight --variable
"highlightjs=C:\x\R\R-3.3.1\library\rmarkdown\rmd\h\highlight" --variable "navigationjs=C:\x\R\R-3.3.1\library\rmarkdow
n\rmd\h\navigation-1.1"

Output created: sample03_out.html

c:\y\RTest\Markdown01>dir | find "sample03"
2016/11/05 15:39 1,318 sample03.Rmd
2016/11/05 16:06 731,226 sample03_out.html


生成されたレポート(sample03_out.html)

image05.JPG

変数もうまく渡せていますね!


※追記: render()の引数の使用

上の例では、環境変数により外部からパラメータを渡す方法を示しましたが、コメントにてrender()で引数渡しができることを教えていて頂いたのでそちらの方法も追記します。

まず、Rmdファイルでは、YAMLフロントマター部分で変数の定義、デフォルト値指定を行います。変数を参照する際は、params$<変数名> という形式で参照できます。

sample04.Rmd

---

title: "サンプル・レポート"
author: "Taguchi"
date: '`r format(Sys.time(), "%Y/%m/%d %H:%M")`'
output:
html_document:
fig_caption: yes
number_sections: yes
theme: default
toc: true
toc_depth: 3
md_extensions: -ascii_identifiers
word_document:
fig_caption: yes
reference_docx: default
toc: yes
params:
arg01: AAA
arg02: 111
arg03: !r format(Sys.Date(), "%Y/%m/%d")
---
```{r setup, include=FALSE}
library(ggplot2) # Graphic package
library(rmarkdown)
library(knitr)
library(stringr)

options(scipen=100)

knitr::opts_chunk$set(echo = FALSE)
knitr::opts_chunk$set(eval = TRUE)
knitr::opts_chunk$set(tidy = TRUE)
knitr::opts_chunk$set(warning = TRUE)
knitr::opts_chunk$set(error = FALSE)
knitr::opts_chunk$set(message = FALSE)

Sys.setenv(tz="asia/tokyo")

```

#Markdownサンプル
##本文

行内へのRコード埋め込み

今日は`r params$arg03` です

箇条書き

* 変数1: `r params$arg01`
* 変数2: `r params$arg02`

## グラフ
サンプルデータ(diamond)の箱ひげ図を表示

```{r}
graph_data <- ggplot(diamonds, aes(y=carat,x=cut, fill=cut))+geom_boxplot()
plot(graph_data)

```

##リンク
[R Markdown](http://rmarkdown.rstudio.com/)

YAMLフロントマターの以下の部分で変数宣言をしています。

params:

arg01: AAA
arg02: 111
arg03: !r format(Sys.Date(), "%Y/%m/%d")

arg01, arg02, arg03 という変数を定義し、それぞれ初期値を指定しています。arg03に示しているように!rを指定することでRのコードを埋め込むことができます。外部から上書きしなければこれらの値が使用されます。

params$arg01 という部分が変数を参照している箇所です。


RStudioによるレポート生成

RStudioで上のRmdファイルを開いて、knitrのプルダウンメニューから、「knitr with Parameters...」を選択します。

image09.JPG

すると、定義されたパラメーターに応じて以下のようなパラメーター入力画面が開きます。

image10.JPG

ここでパラメーターを上書きしてKnitボタンを押せばOKです。


コマンド(バッチ)によるレポート生成

引数渡しのパターンでのコマンド(バッチ)によるレポート生成方法です。

render用のRスクリプトファイルと、バッチファイルを少し改編します。

render_arg.R


render_arg.R

library(rmarkdown)

inputFile <- commandArgs(trailingOnly = TRUE)[1]
outputFile <- commandArgs(trailingOnly = TRUE)[2]
override_arg01 <- commandArgs(trailingOnly = TRUE)[3]
override_arg02 <- commandArgs(trailingOnly = TRUE)[4]
override_arg03 <- commandArgs(trailingOnly = TRUE)[5]

render(inputFile, output_format = "html_document", output_file = outputFile,
params = list(arg01=override_arg01,
arg02=override_arg02,
arg03=override_arg03))


render_arg.bat


render_arg.bat

@echo off

setlocal enabledelayedexpansion
cd %~dp0

rem ################# Usage
rem render_arg.bat <inputFile> <outputFile> <Arg01> <Arg02> <Arg03>

rem ################# set parameters
set R_Inst_Dir=C:\x\R\R-3.3.1\bin
set logFile=RScript.log

set inputFile=%1
set outputFile=%2

set R_Arg01=%3
set R_Arg02=%4
set R_Arg03=%5

rem ################# render
%R_Inst_Dir%\\Rscript.exe render_arg.R %inputFile% %outputFile% %R_Arg01% %R_Arg02% %R_Arg03% >> %logFile% 2>&1



実行例

c:\y\RTest\Markdown01>render_arg.bat sample04.Rmd sample04_out.html BBB 222 2016/01/01

c:\y\RTest\Markdown01>dir | find "sample04"
2016/11/07 09:02 1,242 sample04.Rmd
2016/11/08 09:13 731,225 sample04_out.html

c:\y\RTest\Markdown01>cat RScript.log

processing file: sample04.Rmd
|............. | 20%
inline R code fragments

|.......................... | 40%
label: setup (with options)
List of 1
$ include: logi FALSE

|....................................... | 60%
inline R code fragments

|.................................................... | 80%
label: unnamed-chunk-1
|.................................................................| 100%
ordinary text without R code

output file: sample04.knit.md

"C:/PROGRA~2/Pandoc/pandoc" +RTS -K512m -RTS sample04.utf8.md --to html --from markdown+autolink_bare_uris+tex_math_sing
le_backslash-ascii_identifiers --output sample04_out.html --smart --email-obfuscation none --self-contained --standalone
--section-divs --table-of-contents --toc-depth 3 --template "C:\x\R\R-3.3.1\library\rmarkdown\rmd\h\default.html" --num
ber-sections --variable "theme:bootstrap" --include-in-header "C:\Users\IBM_AD~1\AppData\Local\Temp\RtmpG0omSr\rmarkdown
-str1df03fea75e9.html" --mathjax --variable "mathjax-url:https://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AM
S-MML_HTMLorMML" --no-highlight --variable "highlightjs=C:\x\R\R-3.3.1\library\rmarkdown\rmd\h\highlight" --variable "na
vigationjs=C:\x\R\R-3.3.1\library\rmarkdown\rmd\h\navigation-1.1"

Output created: sample04_out.html


変数宣言が明確に行われますし、初期値設定などもできるので、こちらの方式の方が分かりやすくてよさそうですね!

(パラメーターの入力インターフェースとしてshinyを使ったインタラクティブな画面を生成させることができたり、他にも色々と使い出がありそうです。)

参考:

Parameterized Reports


HTMLレポート生成時にお勧めのインタラクティブなオブジェクト生成パッケージ

Rを使う場合のメリットの1つとして集計結果をグラフなどで可視化しやすいということもあると思います。

HTML形式でレポートを生成する場合、WordやPDFと違って、JavaScriptを利用したインタラクティブな操作が行えるグラフや表を埋め込むことができる、という大きなメリットがあります。以下の2つのパッケージは超お勧めです!


dygraphs

きれいな折れ線グラフが描けます。

マウスをポイントした所がハイライトされたり具体的な値が表示されたりします。

必要な範囲をドラッグすると、その部分を拡大表示してくれたりします。

インフラ屋さんとしては、CPUやメモリの使用率なんかを折れ線グラフにする場合にこれを使うとなかなかよいです。

参考:

dygraphs for R


DT

Excelのようなイメージで色々操作ができる表を埋め込むことができます。フィルターかけたり列でソートしたり、閾値こえたものの色を変えたりなどなど。

かなりいろんな機能が盛り込まれた相当強力なツールだと思います。

参考:

DT: An R interface to the DataTables library


dygraphsやDTは、HTMLで使えるオブジェクトを提供するものなので、HTML形式の静的レポートだけでなく、Webアプリのような動的コンテンツでも利用できます。

これらの具体的な使い方やTipsなどはまた別途紹介しようと思います。

※これらのインタラクティブなオブジェクトを使用する場合、グラフや表で扱うデータ量が多いとレポートのファイルサイズが大きくなってしまう点に注意が必要です。グラフや表を単なる画像として保持しているのではなく、インタラクティブな操作を行うためにデータそのものを保持しておく必要があるためです。