MultiRMDの簡単なサンプル

T. Yoshiizumi

2017/03/11


 当ページは MultiRMD利用の予備知識 につぐ シリーズ第2回です。

 統計ソフトRとmarkdownの組合せによってレポートを生成することが主題です。

 サイコロを10回ふった結果を表示する例を取り上げます。

 サンプルのファイルは mtest01.zip に同梱されています。

    

<目 次>


1. 表示したい画面

 下のような表示を得るためのプログラムを作ります。

 番号付きの箇条書きが10行、
 番号なしの箇条書きが2行です。

−−−− 表示ここから
さいころを10回ふった結果は下のとおり。

  1. 奇数: 3
  2. 奇数: 5
  3. 偶数: 4
  4. 偶数: 6
  5. 奇数: 1
  6. 奇数: 5
  7. 偶数: 2
  8. 偶数: 2
  9. 偶数: 2
  10. 偶数: 2
----------------
  ・ 奇数の回数: 4
  ・ 偶数の回数: 6
−−−− 表示ここまで

 サイコロの目は、乱数発生により取得します。

dice.value <- as.integer(runif(10, min=1, max=7))

 上のようにすると、一様性の乱数が得られます。

 1〜6の整数が10個発生します。

目次に戻る


2. 用意する三つのmarkdownテンプレート

 一つのサイコロの目を表示するのに二種類のmarkdownテンプレートを用意します。

 奇数の場合のものと偶数の場合のものです。

 それぞれ1行だけからなります。次のとおり。

−−−− ここから
1.  奇数: %n%
1.  偶数: %n%
−−−− ここまで

 %n% は、具体的なサイコロの目の数に置き換える必要があります。

 先頭の 1. は、2, 3, 4 …… のような連続する番号にする必要はありません。
rmarkdownとブラウザに任せておけば大丈夫です。

 あと、奇数の回数と偶数の回数を表示するためのmarkdownテンプレートが必要です。次のようなものです。

−−−− ここから
- 奇数の回数: %o%
- 偶数の回数: %e%
−−−− ここまで

 %o%%e% は、やはり具体的な数に置き換える必要があります。

 Rプログラムの実行結果をみながらこれらテンプレートを組み合わせて、
最終的な一つのmarkdownの原稿に仕上げ、
rmarkdownによりhtmlなどに変換するという手順になります。

目次に戻る


3. Rプログラムによるテンプレートの結合

 前述のmarkdownテンプレートが、変数 template に代入されているものとします。

 奇数表示用が template[1], 偶数表示用が template[2],
最後の回数表示用が template[3] に入っている状態です。

 このとき、diceというchunkに書かれているRプログラムは下のとおりです。

−−−− Rプログラムここから
odd.count <- 0   # 奇数の回数
even.count <- 0  # 偶数の回数
dice.value <- as.integer(runif(10, min=1, max=7))
for (n in dice.value) {
    if ((n %% 2) != 0) {  # 奇数の場合
        tpl <- template[1]
        odd.count <- odd.count + 1
    } else {  # 偶数の場合
        tpl <- template[2]
        even.count <- even.count + 1
    }
    tpl <- sub("%n%", n, tpl)
    append.mrmd(tpl)
}
tpl <- template[3]
tpl <- sub("%o%", odd.count, tpl)
tpl <- sub("%e%", even.count, tpl)
append.mrmd(tpl)
−−−− Rプログラムここまで

 append.mrmd() という関数は、multirmd.r の中で定義されています。

 append.mrmd(tpl) は、最終的なmarkdownの原稿に、変数tplの中身を追加・結合するものです。

 内部で定義されている変数 mrmd.buf に蓄積します。

 mrmd.buf に記録された文字列は、最後の方で $$MrmdTmp.rmd というファイルに書き出して、それを取り込んで処理を完成させることになります。

目次に戻る


4. chunk定義ファイルの内容

 これまで述べてきた markdownテンプレート、Rプログラムの両方を一つのchunk定義ファイルに書き込みます。

 mtest01.r というファイルです。

 markdownテンプレートは、#' の2文字から始まる行として書き込みます。

 Rプログラムは、素直にそのまま記入する形です。

−−−− ここから
## @knitr dice
#' 1.  奇数: %n%
    
#' 1.  偶数: %n%
    
#'
#' --------
#'
#' - 奇数の回数: %o%
#' - 偶数の回数: %e%
#'
eval(set.template)
    
odd.count <- 0   # 奇数の回数
even.count <- 0  # 偶数の回数
dice.value <- as.integer(runif(10, min=1, max=7))  # 1〜6の数を10個発生
(中略)
append.mrmd(tpl)
−−−− ここまで

 #' で始まる行が連続すると、それが一つのテンプレートになります。

 空白行など 行頭が #' でないものがあると、そこでテンプレートが区切られます。

 再度 #' で始まる行が現れると、それは別のテンプレートということになります。

    

 テンプレート部分の取り込みは、multirmd.r の中で定義されている set.mrmd() という関数で行います。ライブ来 rmarkdown, knitr の機能は利用しません。

 eval(set.template) は、三つのテンプレートを変数 template にセットするための記述です。

 これを書かないときは、テンプレートを参照するのにちょっと長い記述が必要になります。

 chunk名 dice にかかわるテンプレートは下のとおり。

 どのchunkでも使える汎用的な記述にするなら下のように書きます。

mrmd.template[[opts_current$get('label')]][1]  # 奇数表示用

 こうした長い記述をRプログラムに書くのは大変なので、変数 template にセットできるようにしたものです。

目次に戻る


5. rmdファイルの例

 chunk定義ファイルを読み込んで、それを実行・処理するrmdファイル mtest01.rmd を掲げます。

−−−− ここから
---
title: "Test Document"
author: "Black Lady"
date: "2017/03/11"
output: html_document
---
さいころを10回ふった結果は下のとおり。
    
```{r include=FALSE}
# source("multirmd.r")
chunk.def <- "mtest01.r"
set.mrmd(chunk.def)
read_chunk(chunk.def)
```
```{r child="$$final.rmd"}
```
```{r include=FALSE}
file.remove("$$final.rmd")
```
−−−− ここまで

 上が multirmd.r を利用する典型例です。

    

(1) multirmd.r の読み込み

 # source("multirmd.r") というのはコメントなので実行されません。

 rptパッケージのバッチコマンドで mtest01.rmd を処理する場合は、
multirmd.r が自動的に読み込まれます。なのでコメントにしてあります。

 rptのバッチを使わないときは、行頭の ‘#’ を削除して、multirmd.r を読み込むようにします。

 なお、rptの2種類のバッチ i386_rmarkdown.bat, i386_RmdRuby.bat のどちらでも、mtest01.rmdを処理することができます。

 64bit版なら x64_rmarkdown.bat, x64_RmdRuby.bat のどちらでもOKです。

    

(2) 関数 set.mrmd の役割

 set.mrmd("mtest01.r") とすると、おおよそ下の処理が行われます。

 $$final.rmd の中に書き込まれる処理は次のとおり。

 $$final.rmd の中身は次のようなものになります。

−−−− ここから
```{r dice, include=FALSE}
```
```{r echo=FALSE, results='asis', include=TRUE}
if (mrmd.buf != '') {
cat(mrmd.buf, file=mrmd.tmp)
cat(knit_child(mrmd.tmp, quiet=TRUE), sep='')
mrmd.buf <- ''
dummy <- file.remove(mrmd.tmp)}
```
−−−− ここまで

    

(3) 処理を完成させるための手続き

 関数 set.mrmd() は、あくまで最終的な処理の準備をするものです。

 処理を貫徹するには次の手続きが必要です。

 mtest01.rmd の最後の方でそれを行っています。


 以上が「MultiRMDの簡単なサンプル」です。

 議会は MultiRMDにおけるテンプレートの反復利用 です。

 最後にこんなことを書くのは何ですが、
 今回の例は簡単なので、multirmd.r を使わなくても同じ表示を得るのは容易です。

 わざわざchunk定義ファイルを別に設けて、それを読み込んだりする手間がかからないぶん、より簡単といえます。

 zipファイルに mtest01_2.rmd を同梱しておきます。よかったら覗いてみて下さい。