Rmarkdownでレポート作成する利点はhtmlによるインタラクティブな操作の幅に加えて、word形式でknitした場合でも有利である。
多くの場合wordを用いてレポート作成を行おうとすると
1.データ収集 -> 2.解析(アドホック)-> 3.wordにコピペ
というプロセスで進行するが、これではレポートの作成過程が記録として残らない(再現性が低い)。そのうえ、データに修正が入った場合の手直しやコピペエラー、厳しい突っ込みに脆弱で、過程を明示したオートメーションのほうが有利なケースもある。
#knitはwordに行えばよいので視覚的サポートはwordで後ほどフォローできる。第一、レポートの良し悪しは芸術性の高さではなく説明能力の高さであることを留意しなければならない。
生Rを使用するならrmarkdownパッケージとpandocパッケージ(文書形式変換)をインストールする必要が出てくるが、Rstudioであれば標準搭載であるので特に問題ない。
書き始めではまず先頭にYAMLフロントマターを挿す。このフロントマターはメタ情報や出力フォーマットを指示する文書そのものに関わる要素を記述する。YAMLフロントマターは「—」で囲むことで生成され、title:
““, author:”“, date: ’’, output: , params:
etc…の順に記述するのが一般的。とりあえず前三つは有用である。
YAMLフロントマターを使用する際に、「:」(コロン)の後ろに半角スペースを入れ忘れないこと。これを忘れるとニット失敗もしくはフロントマターが水平線になる。
dateに関しては直接文字を打つなら”“で事足りるが、Sys.time()などの関数を用いる場合にはバッククォート(チャンクで{r}の前に三つ打ってあるやつ)で囲まれた領域にコマンドを記述する。記述の際には「r
<コード>」という形式で行う。
一重引用符は二重引用符と同様の働きをなすが、R言語では二重引用符内の区切りとして利用することが慣習となっている。一方、バッククォートはインラインでのコード埋め込みの他に非標準変数の指定(例えば空白を含む変数a bを指定したい場合)に使う。
#文字列の扱いに関してはこちらを参照されたい。このハイパーリンクの生成は[リンク名](URL)の形を半角で実行する。
YAMLフロントマターにはoutputとparamsなどが存在するが、これらについては後述。実際問題、これらのオプションをすべて記載することは非合理的であるのでクックブックがひとまずの答えになるだろう。それよりも先にRmarkdown方言について扱うことにする。
正式にはR MarkdownであるRmdパッケージは御多分に漏れず方言(独自の記法)がある。wordをはじめとした文書作成ツールに慣れている場合段落分けや見出しの付け方が異なるため厄介に感じるため、細かいツールは省いて頻繁に遭遇する操作に絞って見ていく。
段落・・・普通の改行はknit時にスペースに変換されてしまう。そのため強制的に改行したい場合は改行したい文末に半角スペースを二つ打ってから改行する。
見出し・・・見出しのレベルに合わせて#を打つ。要するに「見出し3」であれば###から始める。こちらも#のあとに半角スペースを入れる。
リスト・・・普通の文書作成ソフトにおける「〇」(箇条書き)が「*」、順序付きリストが「1.」である。この順序付きリストが厄介で、「1.(改行)1.(改行)」とRmd上で記述した場合、knitすると「1.(改行)2.(改行)」となる。リストを入れ子にするには内側のリストを半角4スペース開けてから始める。これも半角スペースが必要。
水平線・・・「-」を三つで引ける。水平線を上下に引いてある。
テキスト修飾・・・強調(イタリック)は「*」で挟み、太字にするには強調を二度重ね掛けする。取り消し線は「~~」、上付きは「^」、下付きは「~」で挟む。ほかにもコードをそのまま文字で出力したいケースでバックスラッシュ(インラインと同じ)を使うことができる。アンダーラインは<u></u>
で挟むが、これはHTMLタグ。
HTMLタグが許されるならもはや何でもあり
#やや複雑だが分かち書きが要請されるケースもあるため注意。また、バージョンによって変わるので随時確認することをお勧めする。
実際に実行してみると
kyoutyou 太字 取り消し
上付き 下付き そのまま
画像・・・ハイパーリンクの前に!をつける。あとはハイパーリンクと同じ。
引用ブロック・・・「>」を行頭に置く。
セットアップチャンクはRmarkdownで全体の構成を決めるチャンクで必須ではない。しかし見通しは良くなるので基本的にここにパッケージ、読み込みデータなどの処理を行う。チャンクオプションはセットアップチャンクに限った話では無いが、例えばecho=F(knitした際に実行結果は文書に残すが、コードは残さないオプション)を全部のチャンクにかけたいときにいちいちecho=Fとするのは面倒なので、セットアップチャンクで knitr::opts_chunk$set()の括弧内で指定することで以降のチャンクは全部その指定に従う。以下、基本的なものも含め便利なチャンクオプションをまとめる。
1.child
Rmarkdownでレポート作成を行っていると、時として解析コードが長くなりすぎてしまいさかのぼることが難しい。それを防止するために解析コードを別のRmarkdownに記述して必要に応じて呼び出すことでメイン文章の視認性が向上する。このchildオプションはコンセプトとして親マークダウンに子マークダウンを組み込むというもので、ある子マークダウン「child.Rmd」を作成したとすると親マークダウンのチャンクオプションで
{r child=“child.Rmd”}
と指定すれば太字の部分のマークダウンの内容がチャンクに反映される。
2.opts.label
チャンクオプションに対するマクロで、特に後述する描画縮尺の指定が多い解析では便利である。形としてはテンプレート作成で、
opts_template$set()
の括弧内に「オプション名」=
list(~)によって指定したオプションテンプレートをopts.label=““で呼び出す。
3.warning,error,message
基本同時使用しない三人。warningは警告、messageはメッセージを表示するか否かである。ggplotなどでgeom_smoothすると出る選択メソッドなどは正直邪魔なケースが多いのでこれで消す。errorはエラー検知で勝手に止まるknitをエラー箇所を無視したうえで無理やり進めるオプション。こちらはデバッグくらいにしか使わない。はず。
4.fig.width/fig.height/out.width/out.height
出力する図のサイズを指定するチャンクオプション。アスペクト比でもいいが、グラフの画質を気にするならR上の画像生成とknit先の画像生成で起こる拡大縮小を考慮する必要がある。出力フォーマットによって異なるので一概に単位は言えない。
5.cache
Rstudioにおけるキャッシュ。逆にデフォルトでFALSEで、同一のコードもrenderする際にはすべて再試行されるため扱うデータが大きければ大きいほど処理に時間がかかってしまう。これをTRUEにすれば処理情報はキャッシュとして保存されるため時間短縮、マシンにも優しいのだが外部読み込みデータに変更を入れて同一コードを再試行したいときは困るのでキャッシュについては後ほど別項目として扱うことにする。
6.echo
コード不要FALSE以上。
7.include
knitに何も残さないが、しっかり実行するチャンクオプション。実際のレポート作成であればこれを多用することになるだろう。
本題に入る前に大事なこと(時として「読み飛ばしてもよい」と形容したほうが適切なこと)を言っておく必要がある。Wordは、できる限りオブラートに包んだ表現をするのであれば、 よろしくない 。少なくともRmarkdownからWord文書にknitするのは実行可能であるものの便利とはいいがたい。それは我々がWordの機能によって美しく整えられた文章を作成することに慣れすぎた余り、RからknitされたWordが筆舌に尽くしがたい様相をしていると感じられるからである。あるいは私が日本人であるがゆえに国際的にサポートされていない言語を母語としているからなのかもしれないが、私の知ったことではない。
Rmarkdown側は最善を尽くした。β版ではあるもののWordとRmarkdown上での操作をインタラクティブに実行可能にするためのパッケージを開発していたが、2021年にそのプロジェクトは未完のまま終わっている。(それでも動作保証が作成者によってなされないだけであって、パッケージ自体は使用可能な形で残されている。詳しくは先述のクックブックを参照のこと。)
しかしRmarkdownはパッケージが豊富であることに定評があり、ユーザーの快適を保証するための努力を怠りはしないことが
install.packages("officedown")
によって確かめられる。このパッケージはRのofficerパッケージをRmarkdownでも使用可能にしたもので、とても素晴らしい♠。私が四の五の説明するよりかは実際にリンク先で機能を見てもらったほうが早いだろう。外部Word文書をRmarkdownに取り込みたい場合もこれを使う。Rmd文書をパワポにも出力できる。
しかしそこまで多くの機能を求めないユーザーにとってもWordのカスタムスタイルテンプレートをknitした際に自動的に適用してほしいと感じる局面は多いはずだ。勝手にMS明朝やらなにやらにされ、それをWordで逐一編集するのは面倒極まりない。そこでYAMLフロントマター上でカスタムテンプレートを指定する方法を紹介する。まず、適当なRmdファイル(スタイル変更をしたい文字要素を含んでいる文章が好ましい。)を作成したあとWordでknit、「RmdtoWordTemp01.docx」など何でもよいがテンプレート用文書だとわかるような名前を付けてRstudioの参照ディレクトリに保存する。その後、作成したWordファイルを開いてスタイル編集をして上書き保存する。こうしておくことで、今後RmdでWord文書を作成するときには
output: word_document: reference_docx: RmdtoWordTemp01.docx
というオプションを指定することで新規knitされたWordでも同様のスタイリングが適用されたものになる。
#注意!細かい話は割愛するが、文書フォーマット変換ツールのPandoc(Rmarkdownなら特定のバージョンのものが組み込まれている。)によって作成されたWord文書でなければならないためスタイルテンプレートは必ず RmdからknitしたWord文書 で作ること。一度作成してしまえば以降はそのWordファイル上でスタイル変更を上書きしてもきちんと認識される。
さて、そろそろ本題に入ろう。
いい加減にしてくれと感じるかもしれないが、そもそもWordのオプションをわざわざ別項目で話した理由はknit
to pdfもしくはknit to htmlのほうが圧倒的にサポートされており、Wordは(
Word側のエンジニアは優秀な働きをしていることは認めるが、内部でどのような処理を行っているのかを明示的に公開していないのでいわばWorld
of Wordのような状況になってしまっており
)独自性が高いので必ずしも意図した動きをしない。なので以降の話はHTMLでの動作を前提にしていると考えてほしい。
#ちなみに、HTMLタグはWord上では反映されない。また、PDFはLaTeX文書を作成したいときに使うツールであると考えたほうが良いだろう。
Rstudioで作業するのであれば(少なくともアプリケーション版では)title,author,dateの項目はRmdファイル作成時に指定するための空欄が用意されているので、基本事項以外入力する予定がないのであればYAMLフロントマターをいじる必要は無い。しかし文書タイトルにシステムから取得したknit日時を残したい場合など、特殊な指定をするためにはYAMLフロントマターを作成or修正することになる。
YAMLフロントマターの基本は「(メタ情報): (指定)」の形であり、必ずコロンの後に半角スペースを開けて書くことを忘れてはならない(Tabによるインデントもできないので手入力)。ほかにも慣れないうちはTRUE,FALSEではなくyes,noによる指定であったり混乱することも多いが、慎重に型に従って記述することが求められる。以下に指定できるオプションをこのサイトより引用する。
---の一番最後に差し込む内容。htmlファイルを指定。通常はfooter的な要素など
# 拡張関連
extra_dependencies: NULL
#新たに追加したいような要素や,拡張要素を指定。
lib_dir: NULL
#jqueryとか依存するHTMLライブラリをコピーするディレクトリを指定。デフォは(ファイル名)_filesってディレクトリへ。
# 出力制御関連
md_extentions: NULL #Pandoc
Markdown拡張で追加するand/or削除する要素を指定
pandoc_args: NULL #Pandocに送る引数を指定。
keep_md: FALSE #.mdファイルを残すかどうかを指定。論理値
self_contained: TRUE
#jsやcss,画像データなどをbase64でhtmlファイルに埋め込み,単一ファイルにするかどうかを指定。論理値
---
この資料に関してもtoc, toc_depthとtemplateそしてtitle, author, dateの基本三要素は指定している。当然outputも含まれる。むしろtocやfigをお好みで入れるにしても、他はなくても支障はないものが多い。特に後半のpandoc_argsは日本語リンクが正常に作動しない際につかったりするもので、普通の文書であれば非ascii文字どうこうは問題にならないはずである。(何より、困ったら半角文字も入れればいい話である)必要に応じて参照されたい。
YAMLフロントマターとは直接関連しないが、先も述べたようにknitオプションにはhtml以外にもWordやpdfがある。pdfはLaTeXを記述の際に使用してknitするのに最適であるが、RmdはMarkdownである以上Tex記法とMarkdown記法を混同するケースがある。それを防ぐにはLaTeXを使用する部分には{=LaTeX}としてチャンクを作成する。必須な操作ではないため、knitした結果エラーが見られた場合にのみ使用すればよい。ほかにもoutput先としてbeamerやioslidesなどがある。
長いYAMLフロントマターの下りがやっと終わり、再びオプションの話に戻る。「すでにチャンクオプションは扱ったのでは」と思われるかもしれないが、ここではknit処理を行うパッケージの{knitr}のオプションについて紹介する。
knitrのパッケージオプションはコードチャンクでも登場したoptsを使う。
opts_knit$set(オプション名=~)
以下、具体的なオプション。
aliases
チャンクオプション名をベクトル形式で指定し、圧縮。
以降のチャンクオプションでは圧縮後のキャラクターでオプション指定ができるようになるため記載ミスが減らしやすい。
eval.after
チャンクオプション評価をチャンク評価後に行いたいオプションをChrベクトルで指定する。
通常、チャンクのオプションはコードチャンクの前に書かれているため先に評価される。しかしチャンク評価(実行)後に得られる値をチャンクオプションの値に使用したい場合、チャンクオプションが先に評価されるのは都合が悪い。そこで有効になるパッケージオプションである。
例としては散布図のキャプションにその相関係数を利用したいが、相関係数を計算するコードがチャンク内にあった場合などである。
require(knitr)
## 要求されたパッケージ knitr をロード中です
opts_knit$set(aliases=c(fic="fig.cap"))
opts_knit$set(eval.after = c("fig.cap"))
x1sampLe <- c(1:10)
y1sampLe <- c(1:10)
corr <- cor(x1sampLe, y1sampLe)
plot(x1sampLe, y1sampLe)
(キャプション)相関係数 = 1
上の例ではaliassesによってfig.capのオプション名を「fic」に短縮している。実際、二個目のチャンクのオプションは
{r, fic = paste0('(キャプション)相関係数 = ', corr)}
になっており、ficがeval.afterによってチャンク処理後に実行されていることが確認できる。
※なお、knitrはknitに付随するオプションである以上Rstudio内の実行では再現されない。そのためfig.capはレポート生成を行う上で図の通し番号を考慮するときに用いるのが良いと思われる。
global.par
Rmdにおいてグラフィカルパラメーターを引き継ぐようにする。T,Fで指定。
フック
knit_hooks$set(フック関数名=フック関数)で指定する。要するにknitrパッケージはknitのためのコードチャンクオプション関数を自分で作成できるということ。レポート作成のオートメーション化に際して強力であるが、具体的な処理はUseful
Rシリーズ(共立出版)が詳しい。R関連書籍は電子化がなされるケースが多いので本学の図書館電子ブックサービスから落として読むことも可能である。
Rはデフォルトではキャッシュ保存をしない、つまりすべてのコードはcache=TRUEにしない限り再評価される。分析レポートによってはコード処理に時間がかかるため再knitのたびに処理をしていては不便である。そのためキャッシュを保存しておけばコード内容に書き換えがない限り再試行をスキップして保存データを持ってくるわけだが、以下のようなケースを考えてみる。
chunk1
oppekepee <- read.csv("~")
chunk2
table(oppekepee)
このレベル(?)のコード処理でキャッシュを保存するか否かはさておき、仮に「おっぺけぺー」のデータ元csvファイルを別物に置き換えた場合chunk1の書き換えは生じるがchunk2のコードは文字上変化は見られない 。こうなったら一度保存したキャッシュを削除しないと「おっぺけぺー」データの置き換えが反映されない。
一般にRstudioでキャッシュを削除するには.Rmdファイル名_cacheファイルを削除すればよい。ほかにもチャンクオプション変更が生じた際には自動的にキャッシュ削除が行われる。そのためセットアップチャンクにおいてopts_chunk$set(cache.extra=Sys.Date())
とすれば日付が変更された場合にコード再評価が可能になる。Sys.Date()でなくともRが取得可能な変動する要素を値にすれば任意のインターバルでキャッシュ削除が可能になる。
実は「おっぺけぺー」の例はかなり重要な話で、ファイルサイズが大きいものを処理するのが一番時間コストのかかる作業である。そして、読み込むファイル名の変更に限らず、ファイルを外部で修正して上書きした場合もキャッシュ削除が必要になる。そこでファイルを読み込むチャンクに
cache.e = tools::md5sum("ファイル名.csv")
を書き込むことでファイル変更に伴うmd5sumハッシュ値変化を認識してキャッシュ消去が実行される。(md5ハッシュはここで深入りしないでおくが、ファイル内容に対してほぼ一対一で計算されるので例えばファイル内容に悪意のある改変が仕組まれたとしてもmd5ハッシュ値変化により検知することができる。そのため、内容依存でありファイル名変更のみではハッシュ値変化は生じない。)また、そのファイルに変更があった場合に連鎖してキャッシュ削除を要求するチャンク(上の例でいえばchunk2)に関しては
dependson="ファイル読み込みチャンク名"
をチャンクオプションに挿すことで紐づけできる。ほかにもRに任せてチャンク依存関係を判断してもらうautodep
= TRUEも存在するが、必ずしも信用ならない模様。
#なるほど。
(R_Studioの基本的な使い方と、そして一部グラフ作成用パッケージを簡潔に紹介する)
#TeXやMarkdownについても多少触れる予定。
(Rstudioの配色や文字フォント、その他スペースチェッカーなど作業ストレスを減らす設定を紹介する)
#個人的には教科書デジタルのフォントが好みだが、いかんせん1(いち)とl(える)の区別がつかない。困りものである。