2.2 R Markdown の解剖学

R Markdown にあるいくつかの部品を考慮することで, 我々はさらに1レベル深く掘り下げることができます. では, この部品がレンダリング作業中にいつどのように処理を変化させるかに注目してみましょう.

2.2.1 YAML メタデータ

YAML metadata (YAML ヘッダとも呼びます) はレンダリング作業中の多くのステージで処理され, 様々な形で最終的な文書に作用することができます. YAML メタデータは文書ファイルの一番冒頭に書かれ, Pandoc, rmarkdown, そして knitr のそれぞれで読み込まれます. その過程で, YAML メタデータに含まれる情報は, コード, コンテンツ, そしてレンダリング処理に影響をあたえます.

典型的な YAML ヘッダは以下のような形をしており, 文書とレンダリング操作指示の基礎となるメタデータを含んでいます.

---
title: My R Markdown Report
author: Yihui Xie
output: html_document
---

上記の場合, title, author フィールドは Pandoc によって処理され, テンプレートの変数の値が設定されます. デフォルトのテンプレートでは, titleauthor の情報は得られた文書の冒頭に現れます. Pandoc が YAML ヘッダの情報をどう扱うかのより詳細な話は, Pandoc マニュアルの YAML metadata block. に関するセクションで見られます.11

対照的に output フィールドは rmarkdown によるレンダリング処理中に出力フォーマット関数 rmarkdown::html_document() に適用されます. output に指定した出力フォーマットに引数を与えることで, 以降のレンダリング処理に影響させることができます. 例えばこのように書きます.

output:
  html_document:
    toc: true
    toc_float: true

これは rmarkdown::render() に, rmarkdown::html_document(toc = TRUE, toc_float = TRUE) と指示することと同じです. これらのオプションが何をするのか知るために, あるいは使える他のオプションを知るためには, R コンソールで ?rmarkdown::html_document を実行してヘルプページを読むとよいでしょう. output: html_documentoutput: rmarkdown::html_document と等価であることに注意してください. 出力フォーマットが rmarkdown:: のような修飾子を持たない場合, R Makrodown はこれを rmarkdown パッケージ由来のものと想定します. そうでないなら, R パッケージ名のプレフィックスが必要です. 例えば bookdown::html_document2 のような.

17.4 節に書いたように, YAML ヘッダ内でパラメータを選択したのなら, コンテンツとコードにも影響することができます. 簡潔に言うと, R Markdown ドキュメント全体で参照可能な変数や R 評価式をヘッダに含めることができるということです. 例えば以下のヘッダでは start_dateend_date パラメータを定義することで, 以降の R Markdown 文書内で params というリスト内に反映されます. つまり, R コード内でこれらの値を使いたければ, params$start_dateparams$end_date でアクセスできるということです.

---
title: My RMarkdown
author: Yihui Xie
output: html_document
params:
  start_date: '2020-01-01'
  end_date: '2020-06-01'
---

2.2.2 ナラティブ

ナラティブ (物語術) としてのテキスト要素は YAML メタデータやコードチャンクよりは理解が簡単でしょう. 典型的には, これはテキストエディタで書いているような感覚でしょう. しかし Markdown コンテンツは, どのようにコンテンツが作られるか, そこからどうやって文書の構造が作られるか, の両方に関して, 単純なテキストよりも強力で面白いものに違いありません.

世のナラティブの多くは人の手で書かれていますが, 多くの R Markdown 文書では, 用いられているコードと分析を参照しようとします. この理由として, 4 章において, コードがテキストの一部を生成するのを助ける様々な方法が実演されています. 例えば単語を結合してリストにしたり (4.11節), 参考文献リストを書いたり (4.5節)といった方法です. この変換は .Rmd から .md への変換と同様に knitr で制御されます.

Markdown のテキストは文書に構造を与えることもできます. Markdown の構文をこの場で復習するには紙面が足りませんが,12 特に関連深い概念の1つとしてセクション見出しがあります. これは 1つ以上の, 対応したレベルの数のハッシュ (#) で表現されます. 例えば, 以下のように.

# 第1水準の見出し

## 第2水準の見出し

### 第3水準の見出し

これらの見出しは rmarkdown.md を最終的な出力フォーマットに変換する際に文書全体に構造を与えます. この構造は, ある属性を付与することで章や節を参照し整形するのに役立ちます. 例えば以下のように, Pandoc 構文は見出しの記述に {#id} の表記にしたがってユニークな識別子をつけることで参照が作成できますし, {.クラス名} のように書くことで, セクションに一つないし複数のクラスを付与できます.

## 第2水準の見出し {#introduction .important .large}

これから学ぶいくつもの方法で, 例えば ID やクラスを参照することで, このセクションにアクセスすることができるようになります. 具体例として, 4.7節ではセクションIDを使って文書内のどこでも相互参照する方法を実演していますし, 7.6節では小節を再構成させる .tabset クラスを紹介しています.

R Markdown のテキスト部分で見られる最後の興味深いコンテンツのタイプとして, 特定の出力したいフォーマットに対して「生のコンテンツ」をそのまま書き出す方法, 例えば LaTeX 出力に対して LaTeX コードを直接書く (6.11 節), HTML 出力に対して HTML コードを直接書く (9.5 節), 等を挙げます. 生のコンテンツは基本的な Markdown ではできないことが達成できますが, 出力フォーマットが異なるとたいていは無視されてしまうことに留意してください. 例えば生の LaTeX コマンドは出力が HTML の場合, 無視されます.

2.2.3 コードチャンク

コードチャンクは R Markdown にとっての心臓の鼓動です. チャンク内のコードは knitr によって実行され, 出力は Markdown に翻訳され, レポートは現在のスクリプトとデータに動的に同期します. 各コードチャンクは言語エンジン (15章), 任意に指定できるラベル, チャンクオプション (11章), そしてコードで構成されます.

コードチャンクに対してできるいくつかの修正について理解するためには, knitr の処理を少しだけ詳しく知ることが有意義です. 各チャンクでは, knitr 言語エンジンは3つの入力の部品を得ます. knit 環境 (knitr::knit_global()), 入力されたコード, そしてチャンクオプションのリストです. コードチャンクはコードの出力とともに見た目も整形して返します. 副作用として, knit 環境も修正されます. 例えばコードチャンク内のソースコードを介してこの環境内で新しい変数がつくられます. この処理は図2.2のように表せます.

図 2.2: 言語エンジンへの入出力フローチャート

この処理は以下の方法で修正できます.

  • 言語エンジンを変更する

  • チャンクオプションを, グローバル, ローカル, あるいは言語エンジンに特定のものに修正する

  • フックやチャプターを使用して, 入出力にさらなる処理を追加する

例えば12.1節で, 後処理をするフックを加えてソースコードの特定行を編集する方法を学べるでしょう.

コードチャンクには2.2.2節でつぶさに見てきたナラティブのクラスと識別子に類似するコンセプトがあります. コードチャンクは識別子 (よく「チャンクラベル」と呼ばれます) を言語エンジンの直後に任意で指定することができます. チャンクオプション class.sourceclass.output でそれぞれコードブロックとテキスト出力ブロックに対するクラスを設定することもできます (7.3節参照). 例えばチャンクヘッダ ```{r summary-stats, class.output = 'large-text'} はチャンクラベルに summary-stats を与え, テキスト出力ブロックに large-text というクラスを与えています. チャンクのラベルは1つだけですが, クラスは複数持つことができます.

2.2.4 文書の本文

文書を執筆し編集する際に理解すべき重要なことは, コードとナラティブの小片が文書内のいくつもの節やコンテナを作る方法です. 例えばこのような文書があったとします.

# タイトル

## X 節

ここから導入文

```{r chunk-x}
x <- 1
print(x)
```

### 第1小節

ここに詳細な話

### 第2小節

ここにさらに詳しい話

## Y 節

ここから新しい節

```{r chunk-y}
y <- 2
print(y)
```

この文書を書いていると, それぞれの小片は, テキストとコードを含む独立した節を一直線上に並べたものだとみなせるでしょう. しかし我々が実際にしているのは, 概念としては図2.3でより細かく描いているように, 入れ子 (ネスト) になったコンテナの作成です13

図 2.3: 入れ子状のコンテナとして表現された単純な R Markdown 文書の例

この図に関する2つの重要な特徴は (1) テキストやコードのどのセクションも個別のコンテナであり, (2) コンテナは他の別のコンテナを入れ子にできる, ということです. この入れ子は R Markdown 文書を RStudio IDE で執筆し, 文書のアウトラインを展開14しているとはっきりと分かります.

2.3では同じレベルのヘッダは同じレベルの入れ子を表していることに注意してください. より低いレベルのヘッダはより高レベルなヘッダのコンテナ内部にあります. この場合, 通常は高レベルの節を「親」といい, 低レベルの節を「子」といいます. 例えば「小節」は「節」の子です. 5.8節で実演するように, ヘッダだけでなく ::: を使ってまとまりの単位を作ることができます.

このテキストで説明されているフォーマットやスタイルのオプションを適用するとき, この構造は重要な意味を持ちます. 例えば, Pandoc が抽象構文木 (AST) でどのように文書を表現するかを我々が学ぶ時 (4.20節) や, HTML出力のスタイルを決めるために CSS セレクタを使用する時 (7.1節ほか), 入れ子構造の概念が現れます.

フォーマットとスタイルは類似するいずれのタイプのコンテナ (例えばコードブロック) や, あるコンテナの内部にある全てのコンテナ (例: 「Y 節」以下にある全てのコンテナ) に対して適用できます. 加えて2.2.2節で説明したように, 同一のクラスを特定の節に対して適用し同様のものとして扱うよう明示できますが, この場合の共通するクラス名は, 節と節に共通のプロパティや共通の意図を示すようになります.

本書を読みながら, 特定の「レシピ」がどんな種類のコンテナに対して作用しているのかを自問し思いを馳せることは役に立つでしょう.


  1. 訳注: 日本語訳での対応箇所はこちら: https://pandoc-doc-ja.readthedocs.io/ja/latest/users-guide.html#metadata-blocks↩︎

  2. Markdown の復習には, 代わりに, https://bookdown.org/yihui/bookdown/markdown-syntax.html をご覧になってください.↩︎

  3. 実際にはここで見えているよりも多くのコンテナがあります. 例えば knit されたコードチャンクや, コードと出力がそれぞれ別のコンテナとして存在し, そしてこれらは親要素を共有しています.↩︎

  4. 訳注: エディタ右上にあるボタンで表示を切り替えることができます.↩︎