文書の過去の版を表示しています。
目次
Rmarkdown
主にRmarkdownからPDFを生成する際のメモ。Latexを経由するためLatexの知識も必要だが、RmarkdownからLatexにコマンドなどを渡す際の方法など、直接Latexを記述する場合とは異なるtipsがある。また、Rmarkdownでloopを回してチャンクを作成する方法など、効率化する手段も色々ありそう。
PDF出力用の基本設定
新しいコマンドを理解するたびに拡張している。とりあえず2020/05/05現在のもの。
ヘッダ部分
title: "タイトル"
author: "作成者"
date: "2020/05/05"
output:
pdf_document:
keep_tex: yes
latex_engine: xelatex
number_sections: yes
always_allow_html: true
# bxjsarticleクラスはgeometryパッケージを呼んでいるらしくここで使うとエラーになったため「no」を設定。
# どこかのバージョンアップにて設定項目があるとエラーになるようになったため削除
#geometry: no
header-includes:
- \usepackage{amsmath,amssymb}
# 別のパッケージと競合して1ページ目に無駄な文字列が出力されるので無効に
#- \usepackage{mathspec}
- \usepackage{indentfirst}
- \parindent = 1em
- \usepackage{zxjatype}
- \setmainfont{Century}
- \setsansfont{Century}
- \setjamainfont{IPAexMincho}
- \setjasansfont{IPAexGothic}
- \usepackage{float}
- \setpagelayout * {margin=20mm}
- \renewcommand{\baselinestretch}{0.9}
-
- \usepackage[compact]{titlesec}
- \titlespacing{\section}{0pt}{5pt}{3pt}
- \titlespacing{\subsection}{0pt}{5pt}{3pt}
- \usepackage{secdot} # 章番号の後ろに「.」を追加するパッケージ。
- \sectiondot{section} # セクション番号に「.」を追加
#- \renewcommand{\thesection}{\arabic{section}} # セクション番号のフォーマットを変更するとき
- \renewcommand{\labelitemi}{■}
- \renewcommand{\labelitemii}{$\circ$}
- \usepackage{caption}
- \captionsetup[table]{skip=5pt}
- \captionsetup[figure]{skip=2mm}
- \renewcommand{\textfraction}{0.001}
- \renewcommand\floatpagefraction{0.99}
- \setcounter{topnumber}{10}
- \setcounter{bottomnumber}{10}
- \setcounter{totalnumber}{20}
- \makeatletter
- \setlength{\@fptop}{0pt}
- \setlength{\@fpsep}{8pt}
- \setlength{\@fpbot}{0pt plus 1fil}
- \makeatother
- \makeatletter
- \renewcommand{\theequation}{% 式番号の付け方
- \thesection-\arabic{equation}}
- \@addtoreset{equation}{section}
- \renewcommand{\thefigure}{% 図番号の付け方
- \thesection-\arabic{figure}}
- \@addtoreset{figure}{section}
- \renewcommand{\thetable}{% 表番号の付け方
- \thesection-\arabic{table}}
- \@addtoreset{table}{section}
- \makeatother
- \usepackage{xcolor} % kableExtraのkable_stylingでlatex_optionsをstripedで表を縞模様にする場合に必要(以前はいらなった)
#- \definecolor{my_color}{rgb}{0.95,0.98,1.00} % stripe_color = “my_color”で縞模様の色を自分で作って指定する場合
# ページを横置きにするコマンドを定義:\blandscapeで開始、\elandscapeで戻す
- \usepackage{lscape}
- \newcommand{\blandscape}{\begin{landscape}}
- \newcommand{\elandscape}{\end{landscape}}
# header、footerのカスタマイズ
# 余白を調整するとそのままでは本文文字にページ番号などが被る場合がある
# fancyhdrパッケージで調整する。複雑なヘッダ、フッタも作成できるが、とりあえず余白との兼ね合いを調整するためだけに読み込み
- \usepackage{fancyhdr}
- \pagestyle{fancy} # ページスタイルを適用
- \lhead{} # ヘッダ左
- \chead{} # ヘッダ中央
- \rhead{} # ヘッダ右・・・いずれも空にする
- \renewcommand{\headrulewidth}{0.0pt} # ヘッダの区切り線を消す
- \cfoot{\thepage} # フッタ中央にページ番号記載
documentclass: bxjsarticle
subparagraph: yes
classoption: xelatex,ja=standard
最初のsetupチャンク
PDFファイルを作成するとき、ggplotで日本語を含む図表を美しく出力するために図表をcairo PDFで作成する設定や、全体のチャンクオプションを一括して設定する。
```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = FALSE)
knitr::opts_chunk$set(warning = FALSE, message = FALSE)
# Latexのfloatを使う場合の図表のfloatオプションを設定
knitr::opts_chunk$set(fig.pos = 'h')
# キャッシュの設定。執筆中は時間短縮のためキャッシュを有効に。最後にOff
knitr::opts_chunk$set(cache = TRUE)
# 出力フォーマットが TeX(PDF含む)の場合のみ対処する
if (knitr::opts_knit$get("rmarkdown.pandoc.to") %in% c("beamer", "latex")) {
# conversion failure on '...' in 'mbcsToSbcs' の Warning 発生の workaround
options(
device = function(file, width = 17, height = 17, ...){
cairo_pdf(tempfile(), width = width, height = height, ...)
}
)
## 1. cairo_pdf を使う方法
# * family には OS にインストールされているフォント名を指定する。
#knitr::opts_chunk$set(dev="cairo_pdf", dev.args=list(family=c("Century","MigMix 1M")))
knitr::opts_chunk$set(dev="cairo_pdf", dev.args=list(family=c("Century","IPAexMincho")))
}
```
図のチャンクオプション
詳細な設定はもっといろいろあるが、基本の設定。PDFの出力が前提なので、ベクタ画像を利用するため解像度はあまり意識しなくてよいようなので、out.widthで横幅を設定し、縦は横幅との相対的な比率で調整するようにした。図は中央寄せ。
```{r チャンク名, fig.cap="キャプション", out.width="90%", fig.asp=0.5, fig.align="center"}
```
パラグラフ間の余白(パラグラフ送り)
パラグラフ間の字送り(余白)の設定。標準では1行空きになっているようだ。全体の設定を変更するにはヘッダ部分に以下を記述。
- \setlength{\parskip}{1.5em}
Loopでチャンク作成
図表を連続して作成する場合など、チャンク内のLoopから別のチャンクを生成したい場合がある。
まずテンプレートとなるチャンクを作成する。ループで回すように、必要な個所は変数化し該当箇所を「{{変数名}}」にしておく。以下の例では、チャンク名とキャプション、ggplotのy軸に使う変数名を外部から与えるパラメータにした。
```{r チャンク名_{{prm_chankname}}, fig.cap="{{fig_name}}", out.width="90%", fig.asp=0.45, fig.align="center"}
ggplot(data=DAT, aes(x=時間, y={{target_var}}) +
geom_line() ...
```
呼び出し側はknitr::knit_expandを利用する。第1引数はテンプレート名、第2引数以降は設定したパラメータを列挙する。ループなどを使う場合は、変数でパラメータを渡してやればよい。他にもif_elseなどで条件別にパラメータを変更したりなど、いろいろできる。Knit_expandでテンプレートに変数を埋め込んだ状態のコードをオブジェクトにいったん保存する。次に、knitr::knitでオブジェクトに入れておいたチャンクを解釈したうえでcatでRmarkdown側に出力する。これで、ループを使って連続的にチャンクを生成できる。デバッグをする場合などは、インラインで図表を確認できない(生成されたチャンクのコードが表示される)のでちょっと不便。
rmd <- paste(
knitr::knit_expand(
"sub.Rmd",
prm_chankname="チャンク名",
fig_name="キャプション",
target_var="工場1"
),
collapse = "\n"
)
rendered <- knitr::knit(text = rmd, quiet = TRUE)
cat(rendered, sep="\n")
コードチャンク内からLatexの改ページを出力
ループなどを使って連続的にグラフを出力するとき、グラフ以外にLatexのコードも出力したい場合がある。
改ページを出力する場合。チャンク出力の変更と、Latexコマンド前後に改行を入れて、Latexコードに変換された際に適切に解釈できるようにすることが重要。
# チャンクの出力をasisにして生のRの結果を出力
```{r results="asis"}
# catで\newpageを出力
# 前後に改行を入れ、コマンド冒頭の「\」をエスケープ
cat("\n\n\\newpage\n")
```
半角スペース
日本語を出力する関係でtexエンジンはxelatexを使うため、半角スペースは適切にエスケープしておかないと出力されない。エスケープの仕方は場所によって異なる。例えばknitr::kableのcaptionに設定する場合ならば
caption="日本語のテキストに\\ 半角スペースを入れます。"
のように、半角スペースの前に「\\」を入れる。他方で、ggplotなどでグラフを出力する際に、チャンクオプションに指定する「fig.cap」では以下のようにする。
... fig.cap="日本語のテキストに\\\ 半角スペースを入れます"
こちらではは「\」が3つ必要。おそらく1つ目はLatexコード認識のため、2つ目は3つ目の「\」のためのエスケープ。
テーブルの5行ごとに縦スペースを追加(しない)
Rで作成した表は、knitr::kableおよびkableExtrパッケージを利用すると、比較的容易に美しくPDFに出力できる。
Latexの機能かRmarkdown、pandocの機能かは調べていないが、標準ではLatexに変換した段階で表の5行ごとに\addlinespaceが入っている。場合によっては等間隔にしたい。これを解除するためには、kableに以下のようにオプションを渡す。
kable(...., linesep="")
linesep=““はkableのヘルプに記載されいないが、kable_latexに引数がそのまま渡されて解除されるようだ。
テーブルなどのラベルを改行する
Latexに変換するときに改行を保持するための関数を使わないと、R側の改行が無視される。
col.names = linebreak(c("男性","女性","クラス\n全体"))
このように、改行「\n」が入った文字列やベクトルをlinebreakに渡してやるとよい。
回帰分析の結果出力
回帰分析の結果の出力は、texregパッケージを使うと手間なく美しくできる。類似パッケージもあるが、とりあえずこのパッケージを使っている。
ここでは主にPDFに出力するために使っているので、要するにLatexのコードを出力するために利用している。
単純に回帰分析の結果を出力するだけなら以下。
# lm()の結果がres.lmに代入されているとして texreg( list(res.lm), digits = 3, caption = "回帰分析の結果", float.pos = "h" )
関数の第一引数に回帰分析の結果が入ったオブジェクトをリストで渡してやればよい。複数の結果を与えると、自動的に横に並べて表示してくれる。2つのモデルの結果で同じ変数があれば、同じ行に示してくれる。モデル内の変数が異なる行は、存在しない場合は空白になって表示される。その他によく使うのは、小数点以下の桁数、キャプション、Latex側でfloatで表を挿入する際のオプション指定など。これ以外にも、モデル名を設定(custom.model.names)や変数名を設定(custom.coef.names)、変数の順序(reorder.coef)、表示しない変数(omit.coef:正規表現で除外変数を指定)など細かく指定できる。
なお、開発中は「texreg」の部分を「screenreg」にしておくと、インラインで見やすいように出力してくれる。
ロジスティック回帰を行ったときなど、結果の係数を指数変換してオッズ比にしたい場合などがある。その場合は、次のように係数をいったん取り出して、オーバーライドしてやればよい。
# res.glmにglm()の結果が代入されているとして # texregパッケージのextract関数で各種係数を取り出す # ロードしていてもパッケージ名を指定しないと同名の関数が被ることがよくある res.glm.ext <- texreg::extract(res.glm) texreg( list(res.glm), # 上のリストで与えたモデルと同じ順で上書きする係数の入ったオブジェクトをリストで渡す # ここでは先にextractで取り出した係数を指数変換してオッズ比にしている override.coef = list(exp(res.glm.ext@coef)), override.se = list(exp(res.glm.ext@se)), digits = 3, caption = "ロジスティック回帰の結果", float.pos = "h" )
図のテキスト回り込み
例によってRmarkdownからPDFを出力する際の細かい設定は、RmarkdownからLatexを制御しなければならないため、やや複雑になる。他に利用しているパッケージによってはうまく動かないなど、実用レベルではない気もする。とりあえず現状のメモ。
まず、Latexでwrapfigを読み込む。
header-includes:
- \usepackage{wrapfig}
ただし、titlesecパッケージを読み込むとうまく動かない。
- \usepackage[compact]{titlesec}
bxjsarticleのクラスオプションにeveryparhook=compatを指定しないとうまく動かない。
documentclass: bxjsarticle classoption: xelatex,ja=standard,everyparhook=compat
次に、Rmarkdownで図を出力する際にLatex側に指定する環境を書き換える(たぶん)
```{r, include = F}
defOut <- knitr::knit_hooks$get("plot") # save the default plot hook
knitr::knit_hooks$set(plot = function(x, options) { # set new plot hook ...
x <- defOut(x, options) # first apply the default hook
if(!is.null(options$wrapfigure)) { # then, if option wrapfigure is given ...
# create the new opening string for the wrapfigure environment ...
wf <- sprintf("\\begin{wrapfigure}{%s}{%g\\textwidth}", options$wrapfigure[[1]], options$wrapfigure[[2]])
x <- gsub("\\begin{figure}", wf, x, fixed = T) # and replace the default one with it.
x <- gsub("{figure}", "{wrapfigure}", x, fixed = T) # also replace the environment ending
}
return(x)
})
```
図を出力するチャンクでwrapfigureオプションを指定する。ここでは図を右寄せで行幅の70%の大きさに指定している。
```{r echo = F, warning = F, message = F, fig.width=7, fig.height = 6, out.width = ".7\\textwidth", fig.cap = "My Flowchart", fig.align="right", wrapfigure = list("R", .7)}
plot(mpg ~ hp, data = mtcars)
```
ということで、何とか回り込みを設定できるものの、いろいろと問題が多い。素直にRmarkdownから指定できるようになってほしい。
