オリジナルなR Markdownの出力形式を作るoutput_format関数事始め

カテゴリ: r

rmarkdown::output_format関数は、新規に、あるいは既存の出力形式を上書きしてオリジナルなR Markdownのの出力形式を作成するための関数です。 rmarkdown::render関数を実行する際に、レンダリングに必要な情報をリストで渡します。リストの内容は、自身のbase_format引数を除く引数の名前です。詳しくはドキュメントを参照して頂くか、その内解説する日を待って頂きたいところ。

str(formals(rmarkdown::output_format))
#> Dotted pair list of 12
#>  $ knitr                  : symbol 
#>  $ pandoc                 : symbol 
#>  $ keep_md                : logi FALSE
#>  $ clean_supporting       : logi TRUE
#>  $ df_print               : NULL
#>  $ pre_knit               : NULL
#>  $ post_knit              : NULL
#>  $ pre_processor          : NULL
#>  $ intermediates_generator: NULL
#>  $ post_processor         : NULL
#>  $ on_exit                : NULL
#>  $ base_format            : NULL

例えば、output_format関数によって作られるrmarkdown::html_documentの返り値の名前を見てみましょう。

base_html_format <- rmarkdown::html_document(keep_md = TRUE)
names(base_html_format)
#>  [1] "knitr"                   "pandoc"                 
#>  [3] "keep_md"                 "clean_supporting"       
#>  [5] "df_print"                "pre_knit"               
#>  [7] "post_knit"               "pre_processor"          
#>  [9] "intermediates_generator" "post_processor"         
#> [11] "on_exit"

そしてリストの内容は、base_formatを指定しない限りは引数に指定した通りのものです。

str(rmarkdown::output_format(NULL, NULL))
#> List of 11
#>  $ knitr                  : NULL
#>  $ pandoc                 : NULL
#>  $ keep_md                : logi FALSE
#>  $ clean_supporting       : logi TRUE
#>  $ df_print               : NULL
#>  $ pre_knit               : NULL
#>  $ post_knit              : NULL
#>  $ pre_processor          : NULL
#>  $ intermediates_generator: NULL
#>  $ post_processor         : NULL
#>  $ on_exit                : NULL
#>  - attr(*, "class")= chr "rmarkdown_output_format"

改変してみる

output_format関数のbase_format引数に、 rmarkdown::html_document()など既存の書式情報を入力しておくと、他の引数にNULL以外が与えられていれば上書きします。ただし、上書き対象がリストの場合は再帰的に名前を比較し、最小限に上書きします。また、output_format関数のkeep_md引数とclean_supporting引数にはNULLを指定できません。

keep_md編

先の例からbase_html_format$keep_mdTRUEです。

base_html_format$keep_md
#> [1] TRUE

rmarkdown::output_format関数のbase_formatbase_html_formatを指定した上で、 keep_md引数にFALSEを指定すると、返り値の$keep_mdFALSEに改変されます。

modified_html_format <- rmarkdown::output_format(
  knitr = NULL,
  pandoc = NULL,
  keep_md = FALSE,
  base_format = base_html_format
)

modified_html_format$keep_md
#> [1] FALSE

では他の値はどうでしょうか?それぞれの要素がbaseとmodifiedとでidenticalか確認してみましょう。すると、clean_supportingon_exitも改変されているようです。

str(Map(identical, base_html_format, modified_html_format))
#> List of 11
#>  $ knitr                  : logi TRUE
#>  $ pandoc                 : logi TRUE
#>  $ keep_md                : logi FALSE
#>  $ clean_supporting       : logi FALSE
#>  $ df_print               : logi TRUE
#>  $ pre_knit               : logi TRUE
#>  $ post_knit              : logi TRUE
#>  $ pre_processor          : logi TRUE
#>  $ intermediates_generator: logi TRUE
#>  $ post_processor         : logi TRUE
#>  $ on_exit                : logi FALSE

output_formatclean_supporting引数はレンダリングに際して出力した画像ファイルなどを掃除するか決めます。 rmarkdown::html_documentの場合、self_contained引数の値がそのままclean_supporting引数に渡されます。これにより、self_contained = FALSEで参照すべき画像ファイルを残す必要があれば、clean_supporting = FALSEが指定されます。 self_contained引数の既定値はTRUEですが、clean_supporting引数の既定値はFALSEなので、上書きされてしまったわけですね。

c(
  formals(rmarkdown::output_format)$clean_supporting,
  formals(rmarkdown::html_document)$self_contained
)
#> [1] TRUE TRUE

on_exitについては環境が変わっただけで、基本的には同じものと思って頂いてOKです。もし、rmarkdown::output_format関数のon_exit引数に関数を指定していた場合は、レンダリング終了時にbase_formaton_exit要素を実行したあとで、追加指定されたon_exitを実行します 1

modified_html_format$base_format
#> NULL
modified_html_format$on_exit
#> function () 
#> {
#>     if (is.function(base)) 
#>         base()
#>     if (is.function(overlay)) 
#>         overlay()
#> }
#> <bytecode: 0x55e41fbfc0e0>
#> <environment: 0x55e41f5d3d20>

knitr編

base_html_format変数のknitr要素は以下のようになっています。

str(base_html_format$knitr)
#> List of 5
#>  $ opts_knit    : NULL
#>  $ opts_chunk   :List of 4
#>   ..$ dev       : chr "png"
#>   ..$ dpi       : num 96
#>   ..$ fig.width : num 7
#>   ..$ fig.height: num 5
#>  $ knit_hooks   : NULL
#>  $ opts_hooks   : NULL
#>  $ opts_template: NULL

では、output_formatに以下のnew_knitrを与えるとどうなるでしょうか?

new_knitr <- list(
  opts_chunk = list(dev = "jpeg")
)

html_format_with_jpeg <- rmarkdown::output_format(
  knitr = new_knitr,
  pandoc = NULL,
  base_format = base_html_format
)
  1. knitr要素が完全にnew_knitrに置き換えられる
  2. knitr要素のopts_chunk要素だけが置き換えられる
  3. knitr要素のopts_chunk要素のdev要素だけが置き換えられる

答えを見てみましょう。

str(html_format_with_jpeg$knitr)
#> List of 5
#>  $ opts_knit    : NULL
#>  $ opts_chunk   :List of 4
#>   ..$ dpi       : num 96
#>   ..$ fig.width : num 7
#>   ..$ fig.height: num 5
#>   ..$ dev       : chr "jpeg"
#>  $ knit_hooks   : NULL
#>  $ opts_hooks   : NULL
#>  $ opts_template: NULL

3の

knitr要素のopts_chunk要素のdev要素だけが置き換えられる

でした!

まとめとTips

rmarkdown::output_format関数を利用すると、オリジナルフォーマットを作ることができます。特に既存のものを弄るのは結構簡単です。 keep_mdclean_supportingについては親のものを単純には引き継げないのでご注意。無理矢理やるなら、以下のように明示的に引き継ぎましょう。

identical_format <- rmarkdown::output_format(
  knitr = NULL,
  pandoc = NULL,
  keep_md = base_html_format$keep_md,
  clean_supporting = base_html_format$clean_supporting,
  base_format = base_html_format
)

するとon_exit以外は完全に同じになりますね。

str(Map(identical, identical_format, base_html_format))
#> List of 11
#>  $ knitr                  : logi TRUE
#>  $ pandoc                 : logi TRUE
#>  $ keep_md                : logi TRUE
#>  $ clean_supporting       : logi TRUE
#>  $ df_print               : logi TRUE
#>  $ pre_knit               : logi TRUE
#>  $ post_knit              : logi TRUE
#>  $ pre_processor          : logi TRUE
#>  $ intermediates_generator: logi TRUE
#>  $ post_processor         : logi TRUE
#>  $ on_exit                : logi FALSE