11.11 テキストを生の Markdown として出力する (*)

デフォルトではコードチャンクからのテキスト出力は冒頭に2つハッシュを置いて, テキストをそのまま書き出します (11.12節参照). knitr は出力をコードブロックで囲むため, テキストはそのまま表示されます. 例えば 1:5 というコードの生の出力はこうなります.

```
## [1] 1 2 3 4 5
```

時には生のテキストをそのまま出力するのではなく, Markdown 構文として扱いたいこともあるでしょう. 例えば cat('# これは見出しです') でセクション見出しを書きたい時があるかもしれませんが, 生の出力はこうなります.

```
## # これは見出しです
```

テキストをコードブロックで囲んでほしくない, あるいは冒頭のハッシュもいらない. つまり, 生の出力が cat() に与えた文字列そのままになるようにしたい, というわけです.

# This is a header

これを解決するのはチャンクオプション results = 'asis' です. このオプションは テキスト出力をコードブロックで囲むのではなく, “as is” (そのまま) 扱うよう knitr に指示します. R コードから動的にコンテンツを生成したい時に, このオプションは特に有用でしょう. 例えば以下のコードチャンクと results = 'asis' オプションで, iris データから列名のリストを生成します.

cat(paste0("- `", names(iris), "`"), sep = "\n")
  • Sepal.Length
  • Sepal.Width
  • Petal.Length
  • Petal.Width
  • Species

ハイフン (-) は番号のない箇条書き意味する Markdown 構文です. バッククォートはオプションです. results = 'asis' オプションなしで上記のコードチャンクがそのまま出力されるのを見ることもできます.

cat(paste0("- `", names(iris), "`"), sep = "\n")
- `Sepal.Length`
- `Sepal.Width`
- `Petal.Length`
- `Petal.Width`
- `Species`

以下は, セクション見出し, パラグラフ, mtcars データの全ての列に対してfor ループ内で作成したグラフを表示する例の全貌です

---
title: プログラミングでコンテンツを生成する
---

チャンクオプション `results = 'asis'` で生の Markdown コンテンツを書き出すことができます. これはプロットを含めることもできます. 

```{r, mtcars-plots, results='asis'}
for (i in names(mtcars)) {
  cat('\n\n# 変数 `', i, '` の要約.\n\n')
  x <- mtcars[, i]
  if (length(unique(x)) <= 6) {
    cat('`', i, '` はカテゴリカル変数である.\n\n')
    plot(table(x), xlab = i, ylab = '度数', lwd = 10)
  } else {
    cat('連続変数 `', i, '` のヒストグラム.\n\n')
    hist(x, xlab = i, main = '')
  }
}
```

改行 (\n) を過剰に追加していることに注意してください. これは Markdown コンテンツ上でそれぞれの要素を明確に分離したいからです. 要素間の改行は多すぎても無害ですが, 改行が不十分だと問題が起こりえます. 例えば以下の Markdown テキストには大いに曖昧さがあります.

# これは見出し?
これは段落?ヘッダの一部?
![この画像は?](foo.png)
# この行はどうなる?

cat('\n') で生成できていたように空白行を追加すると, この曖昧さは消えます.

# そうこれは見出し!

そしてこれは明らかに段落.

![これは画像](foo.png)

# 完全なる別の見出し

cat() だけがテキスト出力のできる関数ではありません. 他のよく使われる関数には print() があります. print() はしばしばオブジェクトの表示のために暗黙に呼び出されることに注意してください. これが R コンソールでオブジェクトや値をタイプした直後に出力が表示される理由です. 例えば R コンソールで 1:5 とタイプし Enter キーを押した時, R が実際には print(1:5) を暗黙に呼び出しているので出力が見えます. R コンソール上で入力していれば正常に表示されていたはずのオブジェクトや値が for ループなどのコード内では出力の生成に失敗するというのはとても混乱をもたらします. この話はかなり技術的に高度なので, 私はブログに “The Ghost Printer behind Top-level R Expressions” という説明の記事を投稿しました. 技術的な詳細に関心がないなら, このルールだけは覚えてください. 「for ループ内の出力が表示されなかったら, おそらく print() 関数で明示的に表示させるべきです」