はじめに
captioner を使うと相互参照に未対応な Rmd フォーマットも相互参照できるようになる
(rmarkdown::html_document
とか pkgdown
とか……).
詳しくはテラモナギさんの記事を参照
(captionerパッケージで図・表に対する参照(レファレンス)を取得する).
ただ,リンクをつけようとすると結構面倒.
あと,キャプション付きで出すときは fig_cap("figure-name", "hogehoge")
で「図1」みたいに参照番号だけ出す時は fig_cap("figure-name", display = "cite")
といった具合な仕様で,繰り返し同じ図を参照する時は毎度 display
引数を指定しなければならないのが不便だ.
また,相互参照を実現するための関数を図,表,式など,それぞれについて作成しないといけない.
このあたりの改善を試みる.
ついでに, gt::gt
のような bookdown パッケージなどが相互参照に対応できていない関数も相互参照させられるようになる.
あとは任意の Rmd で内蔵の相互参照を無効化する機能さえあれば……!!
実装
キャプションを振る時は相互参照に利用する名前を id
に流用
相互参照に利用する名前をそのまま図表の id
として利用できるように,
captioners
の引数を弄るかラッパー関数を作ろう.
Pandoc’s markdown では [hoge]{#fuga}
とすることで
文字列 hoge
に id fuga
を与えられる.
html に出力した時は <span id = "hoge">hoge</span>
になる.
図表の name
引数に与えた文字列を利用して []{#name}
という文字列を作り, caption
冒頭にでも入れてやればいい.
cap <- lapply(
captioners,
function(f) {
formals(f) <- append(formals(f), alist(.caption = ), 1)
formals(f)$caption <- quote(paste0("[]{#", name, "}", .caption))
f
# 以下のようにラッパー関数にしてもOK
# function(name, caption = "", ...) {
# f(name, paste0("[]{#", name, "}", caption), ...)
# }
}
)
参照する時は相互参照に利用する名前をリンクにする
先の cap
の実装で,キャプションには id
が振られている.
この id
にリンクされるよう,通常の captioner
なら 図1
としか出力しないところを [図1]{#fuga}
といった具合に出力されるよう,captioners
をラッパーしよう.
cite <- lapply(
captioners,
function(f) {
function(name, display = "cite", ...) {
paste0("[", f(name, display = display, ...), "](#", name, ")")
}
}
)
これで準備は完了だ.
図をテスト
plot()
`r cite$fig("plot-iris")`
は 図 1 になる.
ちゃんとリンクも貼れてるね.
blogdown
が図表の番号付けに対応しているせいで, Figure 1: 図 1:
となってしまうのはご愛嬌.
```{r plot-iris, fig.cap = .cap}
.cap <- cap$fig("plot-iris", "plot(iris) に図表番号とキャプション,idをつけた")
plot(iris)
```
表をテスト
knitr::kable()
`r cite$tbl("kable-iris")`
は 表 1 になる.
ちゃんとリンクも貼れてるね.
library(knitr)
.cap <- cap$tbl("kable-iris", "kable(iris) に図表番号とキャプションとidをつけた.")
kable(iris[1:2, ], caption = .cap)
Sepal.Length | Sepal.Width | Petal.Length | Petal.Width | Species |
---|---|---|---|---|
5.1 | 3.5 | 1.4 | 0.2 | setosa |
4.9 | 3.0 | 1.4 | 0.2 | setosa |
gt::gt()
gt
は今のところ相互参照に対応していない (後述).
従って captioner
を使う他ない.
gtが受け取る文字列を md や html として解釈させるには md()
や html()
といった関数を用いる.
しかし,この md()
は Pandoc’s markdown を解釈してくれないようで,以下のように id 付けに失敗する.
id付け失敗
library(gt)
gt(iris[1, ]) %>%
tab_header(
title = md(cap$tbl(
"gt-iris",
"gt(iris) に図表番号とキャプションをつけたが,idはうまくついていない."
))
)
表 2: []{#gt-iris}gt(iris) に図表番号とキャプションをつけたが,idはうまくついていない. | ||||
---|---|---|---|---|
Sepal.Length | Sepal.Width | Petal.Length | Petal.Width | Species |
5.1 | 3.5 | 1.4 | 0.2 | setosa |
id付け成功例1
表 3 のように, gt
の外でキャプションをつける.
やや不恰好だが,とりあえず動く.
cap$tbl(
"gt-iris2",
"gt(iris) に図表番号とキャプションをつけたが,idはうまくついていない."
)
gt(iris[1, ])
表 3: gt(iris) との一体感はなくなるが,idもつく
Sepal.Length | Sepal.Width | Petal.Length | Petal.Width | Species |
---|---|---|---|---|
5.1 | 3.5 | 1.4 | 0.2 | setosa |
id付け成功例2
Ppandoc’s markdown が通らないだけで html は通るので, cap
を以下のように書き換える.
すると 表 4 のように, 見栄えを gt
で完結できる.
cap <- lapply(
captioners,
function(f) {
function(name, caption = "", ...) {
f(name, paste0("<span id = '", name, "'></span>", caption), ...)
}
}
)
gt(iris[1, ]) %>%
tab_header(
title = html(cap$tbl(
"gt-iris3",
"gt(iris) に図表番号とキャプションをつけたが,idはうまくついていない."
))
)
表 4: gt(iris) に図表番号とキャプションをつけたが,idはうまくついていない. | ||||
---|---|---|---|---|
Sepal.Length | Sepal.Width | Petal.Length | Petal.Width | Species |
5.1 | 3.5 | 1.4 | 0.2 | setosa |
gt は相互参照未対応であることを確認
fig.cap
を指定してもタイトルが表示されない.
```{r gt-iris, fig.cap = "gt with fig.cap", echo = FALSE}
gt(iris[1, ])
```
Sepal.Length | Sepal.Width | Petal.Length | Petal.Width | Species |
---|---|---|---|---|
5.1 | 3.5 | 1.4 | 0.2 | setosa |
tab_header(title = )
を指定するとタイトルは表示されるが,図表番号は表示されない.
```{r gt-iris-titled, echo = FALSE}
gt(iris[1, ]) %>%
tab_header(title = "gt with title")
```
gt with title | ||||
---|---|---|---|---|
Sepal.Length | Sepal.Width | Petal.Length | Petal.Width | Species |
5.1 | 3.5 | 1.4 | 0.2 | setosa |