search
LoginSignup
4

More than 1 year has passed since last update.

posted at

updated at

【R】TeX形式の図表をR⇒PDFに直接出力する

0. はじめに

この記事は『R Advent Calendar 2020』第2日目の記事です。
Advent Calendar自体、今回が初参戦です。お手柔らかにお願いします。

1. 趣旨

RはTeX形式と親和性が良いのか、stargazertexreg等、TeX形式で図表を出力することが可能であり、数値の転記ミスを防止できるし、Excelで作るより見た目が整っているのが印象的です。
しかし、私は普段はTeXではなくWordを使うので、SVGやPNG等に変換して使用する必要があります。

その際の手順が少々煩雑であり1

  1. Rで出力したコードをtex形式のファイルに貼り付けて、
  2. pLaTex、XeLaTeX、Cloud LaTeX等をかませてPDF出力し、
  3. InkscapeでPDFをベクター化してから各種画像に変換する

という3ステップを噛ませているのですが、特に1~2が面倒くさい!
どうにか1~2を一発で済ませたい!

というわけで、今回はTeX形式の図表をRからダイレクトにPDFとして出力する方法を書いておきます。

1.2 搭載を目指す機能

1.2.1. data.frame → TeX形式

とりあえず個人的に「相関分析」のテーブルを作らなくてはならないのですが、元データがdata.frameで出力されるので、まずdata.frameをTeX形式に書き換える機能を搭載しようと思います。
これはパッケージを利用すれば簡単にできるはずです。

1.2.2. character型vectorにも対応させる

data.frameのみの対応だとstargazertexregを利用できないのが勿体ないので、TeXコード(character型ベクトル)の入力にも対応させます。

1.2.3. 四捨五入

上記の元データをそのまま利用すると桁数が多すぎるので、四捨五入する機能を載せておきます。(入力がdata.frameの場合のみ)

1.2.4. プレビュー機能

PDF出力後、RStudioのビューアーにPDFをプレビューさせようと思います。
この辺もパッケージを利用すれば手軽に実装できます。

2. 必要な道具

網羅的に書いたつもりですが、元々入れているもの等見落としがあるかもしれません。

2.1. ソフトウェア

  • R
  • RStudio
  • TeXLive
  • XeLaTeX (TeXLiveを入れれば自動で入っているはず)
  • ImageMagick

2.2 パッケージ

  • {dplyr}
  • {kable}
  • {kableExtra}
  • {knitr}
  • {magick}
  • {pdftools}
  • {tinytex}

3. 下準備

3.1. パッケージの導入

# 未導入の物があれば入れておいてください。
install.packages(c("dplyr","kableExtra","knitr","magick","pdftools","tinytex"))

3.2. {tinytex}の導入

{tinytex}はパッケージをダウンロードしただけでは意味がありません。
以下のコードを実行して、初めて導入が完了します。

tinytex::install_tinytex()

4. コード

# data.frameの四捨五入
shisha <- function(df, digits = 3, convert = T) {
  df.new <- df
  for(x in 1: nrow(df)){
    for(y in 1: ncol(df)){
      p <- try(as.numeric(df[x,y]))
      if(!is.na(p)){
        if(convert == T){
          df.new[x,y] <- as.character(signif(p, digits = digits))
        }else{
          df.new[x,y] <- signif(p, digits = digits)
        }
      }
    }
  }
  return(df.new)
}

# TeX形式の文書を作成する
texmaker <- function(x = NA){
  if(is.na(x)) {
    x <- as.character("")
  }
  header <- paste0("\\documentclass{article}\n",
                   "\\usepackage{fontspec}",
                   "\\usepackage{zxjatype}",
                   "\\setjamainfont{MS Mincho} ",
                   "\\usepackage[dvipdfmx]{graphicx}\n",
                   "\\usepackage{caption}\n",
                   "\\usepackage[pass,letterpaper]{geometry}\n",
                   "\\usepackage {scalefnt}\n",
                   "\\usepackage {graphicx}\n",
                   "\\usepackage {booktabs}\n")
  body <- paste0("\\begin{document}\n",
                 "\\thispagestyle{empty}\n")
  content <- paste0(x)
  footer <- paste0("\\end{document}")
  code <- paste0(header, body, content, footer)
  return(code)
}

# 作成した文書を外部ファイルに出力する
maketex <- function(texdoc, filename){
  sink(file(filename, encoding = "UTF-8"))
  cat(texdoc)
  sink()
}

# 完成品 (上記のWrapper関数)
makepdf <- function(df, filename = "result", preview = T) {
  if (is.data.frame(df)){
    p <- texmaker(kableExtra::kbl(shisha(df), booktabs = T, format = "latex"))
  } else {
    if (is.character(df)){
      message('Process "df" as tex document.')
      p <- texmaker(df)
    } else {
      stop('Argument "df" must be data.frame of character.')
    }
  }
  maketex(p, filename = paste0(filename, ".tex"))
  tinytex::xelatex(paste0(filename, ".tex"))
  knitr::plot_crop(paste0(filename, ".pdf"))
  if (preview == T) {
    magick::image_read_pdf(paste0(filename, ".pdf"))
  }
}

5. 動作

5.1. サンプルデータ

今回は二種類用意しました。
Data1が相関分析表(架空のデータ)、Data2がirisの回帰結果をstargazerで出力したモノです。

サンプルデータの用意
data1 <- data.frame(c("1","","","",""), c("0.7892401","1","","",""), c("0.7124973", "0.9673863","1","",""), c("0.4897329","0.8834619","0.9287465","1",""), c ("0.4680764","0.6982260","0.7143392","0.8676399","1"))
colnames(data1) <- c("20代", "30代", "40代", "50代", "60代")
rownames(data1) <- colnames(data1)

data2 <- stargazer(lm (Sepal.Length ~ Sepal.Width + Petal.Length + Petal.Width , data=iris))
data1
> data1
     20      30      40      50      60
20    1 0.7892401 0.7124973 0.4897329 0.4680764
30              1 0.9673863 0.8834619 0.6982260
40                        1 0.9287465 0.7143392
50                                  1 0.8676399
60                                            1
data2
> head(data2)
[1] ""                                                                                                           
[2] "% Table created by stargazer v.5.2.2 by Marek Hlavac, Harvard University. E-mail: hlavac at fas.harvard.edu"
[3] "% Date and time: 日, 11 22, 2020 - 15:55:30"                                                                
[4] "\\begin{table}[!htbp] \\centering "                                                                         
[5] "  \\caption{} "                                                                                             
[6] "  \\label{} "   
# 以下略

5.2. 実際に動かしてみる

5.2.1. データフレームの場合(data1)

まずはデータフレームから。作成したmakepdf()関数に代入します。なお、filenameは出力するファイル名(拡張子除く)のことです。

makepdf(df = data1, filename = "data1")

data1.png

いい感じです。

5.2.2. character型データの場合(data2)

続いて、stargazerの結果をPDF出力します。
こちらは、行毎にベクトルの要素に分解されているので、全部繋げる必要があります。

library(dplyr)
data2 %>% 
  paste0(collapse = "\n") %>%
  makepdf(filename = "data2")

data2.png

6. 補足

6.1. なぜ「XeLaTeX」なのか。

理由は簡単です。日本語に対応しているTeXエンジンで一番楽だったからです。
最初はずっと「pLaTeX」でやろうと考えていたのですが、丸二日試行錯誤した末無理だったので、XeLaTeXに切り替えました。XeLaTeXに関してはRパッケージもある程度充実していたこともあり、あっさりできました。

6.2. OSX・Linuxであれば…

どうやらR上でPDFとSVGの相互変換が可能のようです。そこまで可能であればさらにワンステップ自動化できるので、超理想ですね。いいなぁ。Windowsなもんで。
https://sjp.co.nz/projects/grconvert/

7. おわりに

ということで、何とか実装できました。
「TeX⇒PDF出力」まで自動化できれば、そこそこ便利じゃないでしょうか。

是非お試しください。

おしまい。

8. 参考

https://qiita.com/nozma/items/1c6b000b674225fd40d7
https://cran.r-project.org/web/packages/magick/index.html
https://texwiki.texjp.org/?TeX%E3%81%A8%E3%83%95%E3%82%A9%E3%83%B3%E3%83%88
https://yyhhyy.hatenablog.com/entry/2015/10/17/203000


  1. 拙著『TeX形式の図表をWordで使いたい!!!!』をご参照ください。 

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
4