12.4 テキスト出力を中断する

コードチャンクから出力されたテキストが長い時, 冒頭の数行だけを表示させたくなります. 例えば数千行のデータフレームを表示する時, データ全体を表示するのは不便で, 最初の数行だけで十分でしょう. 以下では output フックを再定義してカスタムチャンクオプション out.lines によって最大行数を制御できるようにしています.

# 組み込みの出力フックを保存
hook_output <- knitr::knit_hooks$get("output")

# テキスト出力を打ち切る出力フックを新規に作成
knitr::knit_hooks$set(output = function(x, options) {
  if (!is.null(n <- options$out.lines)) {
    x <- xfun::split_lines(x)
    if (length(x) > n) {
      # 出力を切断
      x <- c(head(x, n), "....\n")
    }
    x <- paste(x, collapse = "\n")
  }
  hook_output(x, options)
})

上記のフック関数の基本的なアイディアはテキスト出力の行数が, チャンクオプション out.linesで指定したしきい値 (関数本体では変数 n として保存されています) を上回ったら, 最初の n 行だけを残し, 省略記号 (....) を末尾に加え出力が打ち切られたことを表します.

以下のチャンクでチャンクオプション out.lines = 4 を設定し, この新たな output フックをテストできます.

print(cars)
##    speed dist
## 1      4    2
## 2      4   10
## 3      7    4
....

期待通りに4行の出力が現れました. 元の output フックを hook_output に保存しているので, 再度 set() メソッドを呼び出して復元することができます.

knitr::knit_hooks$set(output = hook_output)

読者への練習問題として, 異なる方法で出力を打ち切ることに挑戦してみてください. 最大行を決定するチャンクオプション out.lines を所与として, 末尾の行ではなく中間の行を打ち切ることができますか? 例えば out.lines = 10 なら, このように最初と最後の5行を残し, 中間に .... を追加します.

##    speed dist
## 1      4    2
## 2      4   10
## 3      7    4
## 4      7   22
....
## 46    24   70
## 47    24   92
## 48    24   93
## 49    24  120
## 50    25   85

出力の最終行, つまりフック関数の引数 x が空白行ならば, c(head(x, n/2), '....', tail(x, n/2 + 1)) のような処理が必要であることに注意してください. +1 は最後の空白行を考慮するためです.