Sep 10, 2020
17 mins read
論文を執筆する時や、結果をボスに見せる時などに表を作成することがあると思います。 そのような時に皆さんはどのように表を作成していますか? Excelで作成した表をWordに埋め込む、Wordで直接表を作成する、LaTeXの表組みを用いる、Markdownで記述してpandocで吐き出す…などなどいろいろな方法があると思います。
筆者はもっぱらLaTeXの表組みを用いていました。(筆者はそのうち.Rmdに完全移行したいと思いつつ2年くらいはR+LaTeXの組み合わせを用いています。)
いつものようにRで得た解析結果をぽちぽちとコピペをしていたところ、ふと 「Rで吐き出した解析の結果をコピペする作業、虚しくない?」 と思い立ったのが本記事のきっかけです。
皆さんはどうですか?胸に手を当てて考えてみてください。え、何も思わない?そうですか…。
ということで、今回は Rから表をimageとして吐き出す ことを目的とした記事です。imageとして吐き出せば、あとはLaTeXだとて\includegraphics
でおしまいなわけです。なんと楽なことか。
注意!!実際問題として、論文を投稿する時にはimageとしてtableを提出できない場合の方が多いと思います。そのような場合もある程度まではカバーできますが、今回は主に学会発表やプログレスミーティングの時のお役立ち情報くらいに考えてください。 こちらの記事を参照ください。“Can we insert tables as images in a manuscript submission document?”
また、今回もかなり備忘録に近いです。
今回は、
の順です。
まずは{gt}パッケージによる表作成から。
{gt}パッケージでは慣れ親しんだtibbleなどからgtオブジェクトを介してきれいな表を作成してくれます。 例えばirisを例にすると
library(tidyverse)
library(gt)
iris %>% gt()
これだけです。ブラウザ(Rstudioならviewer)が立ち上がり、下のようなtableが表示されたのではないでしょうか。
ちょっと長ったらしいので、データ自体を整形しましょう。
各種のSepal.Length
のTOP5を集めて、tableとして表示します。
iris_SLtop5 <- iris %>% group_by(Species) %>%
arrange(desc(Sepal.Length)) %>%
mutate(rownum=row_number()) %>%
filter(rownum<=5) %>%
select(-rownum) %>% ungroup()
iris_SLtop5 %>% gt()
すでにキレイな見た目に見えます。が、ここからさらに細かく編集していきましょう。
表のタイトルです。習うより慣れろの精神で以下のスクリプトを実行してみてください。
iris_SLtop5 %>% gt() %>%
tab_header(
title = "Anderson's Iris Data",
subtitle = md("_Top 5_ flowers from each species of Sepal.Length value")
)
タイトルがつきました。
md()
という関数を用いると、Markdown記法で文字をいじることができます。これは便利。
注釈を付け加えましょう。データの出典を記述します。
iris_SLtop5 %>% gt() %>%
tab_header(
title = "Anderson's Iris Data",
subtitle = md("_Top 5_ flowers from each species of Sepal.Length value")
) %>%
tab_source_note(
source_note = "The data were collected by Anderson, Edgar (1935)."
)
もうちょっと使い勝手良く注釈を付けたいですよね。それもできます。
SL_longest <- iris %>% group_by(Species) %>%
summarize(SL_mean=mean(Sepal.Length),
PL_mean=mean(Petal.Length)) %>%
ungroup() %>%
filter(SL_mean==max(SL_mean)) %>%
pull(Species) %>%
as.character()
iris %>% group_by(Species) %>%
summarize(SL_mean=mean(Sepal.Length),
PL_mean=mean(Petal.Length)) %>%
ungroup() %>%
gt() %>%
tab_footnote(
footnote = md("The **longest** by Sepal.Length."),
locations = cells_body(
columns = vars(SL_mean),
rows = Species == SL_longest)
) %>%
tab_footnote(
footnote = md("The **shortest** by Petal.Length"),
locations = cells_body(
columns = vars(PL_mean),
rows = PL_mean == min(PL_mean))
)
1つ目のtab_footnote()
では、先に作成しておいたSL_longest
に入っている"virginica"
とのマッチングでSepal.Lengthの平均が最長の種を指定しています。
2つ目のtab_footnote()
では関数内でPetal.Lengthの平均が最短の種を選択しています。
このような注釈を付け加えるのも数行で済んでしまいます。
ここまでのスクリプトではungroup()
をした後にgt()
を行っていましたが、groupd_dfのままgt()
を行うとどうなるのか見ていきます。
iris_SLtop5 %>% group_by(Species) %>%
gt()
groupごとに表示されてすっきりしました。
tidydataで慣れている身からするとむしろnon-tidyでモヤッとする…
見やすさは、おそらくtidydataよりもむしろこっち。多分。スライドなどにはこちらの方が使い勝手が良いかもしれません。
続いて{gtsummary}を用いた表作成です。
{gtsummary}は名前の通り、{gt}を元に作成されたパッケージです。summaryデータを一瞬で表現できるすごいパッケージです。
使い方はこちらもシンプル。これだけです。
library(gtsummary)
iris %>% tbl_summary()
勝手にまとめてくれた上に表示までしてくれました。すごい。
上記の値、どこかで近しい何かを見たことあるかもしれません。そう、summary()
を用いた時です。
> iris %>% summary
Sepal.Length Sepal.Width Petal.Length Petal.Width
Min. :4.300 Min. :2.000 Min. :1.000 Min. :0.100
1st Qu.:5.100 1st Qu.:2.800 1st Qu.:1.600 1st Qu.:0.300
Median :5.800 Median :3.000 Median :4.350 Median :1.300
Mean :5.843 Mean :3.057 Mean :3.758 Mean :1.199
3rd Qu.:6.400 3rd Qu.:3.300 3rd Qu.:5.100 3rd Qu.:1.800
Max. :7.900 Max. :4.400 Max. :6.900 Max. :2.500
Species
setosa :50
versicolor:50
virginica :50
最小値や最大値、平均などはtbl_sumamry()
のデフォルトではついてきませんが、個人的には結構満足です。
summary()
がこんなにきれいに描けるならもしやliner modelとかも…と期待してしまいますよね。
あります。
まずは単純にglm()
から。モデル式などなどは適当です。
> model1 <- glm(Sepal.Length~Sepal.Width + Species + Sepal.Width*Species, dat=iris)
> summary(model1)
Call:
glm(formula = Sepal.Length ~ Sepal.Width + Species + Sepal.Width *
Species, data = iris)
Deviance Residuals:
Min 1Q Median 3Q Max
-1.26067 -0.25861 -0.03305 0.18929 1.44917
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 2.6390 0.5715 4.618 8.53e-06 ***
Sepal.Width 0.6905 0.1657 4.166 5.31e-05 ***
Speciesversicolor 0.9007 0.7988 1.128 0.261
Speciesvirginica 1.2678 0.8162 1.553 0.123
Sepal.Width:Speciesversicolor 0.1746 0.2599 0.672 0.503
Sepal.Width:Speciesvirginica 0.2110 0.2558 0.825 0.411
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
(Dispersion parameter for gaussian family taken to be 0.1933783)
Null deviance: 102.168 on 149 degrees of freedom
Residual deviance: 27.846 on 144 degrees of freedom
AIC: 187.09
Number of Fisher Scoring iterations: 2
これを{gtsummary}で書くとこうなります。
model1 %>% tbl_regression()
Interceptが欲しい、p-valueは小数点3桁で揃えたい、説明変数は斜体にしたい、などもできます。
model1 %>% tbl_regression(intercept=T,
pvalue_fun = ~style_pvalue(.x, digits = 3)) %>%
italicize_levels()
他にもいろいろ便利な関数が用意されているようですが、私はまだ使いこなせていません。そのうち勉強して追記します。
参考: https://cran.r-project.org/web/packages/gtsummary/gtsummary.pdf
最後に出力の話を少しだけします。
特にRstudio以外でRを動かしている場合、ブラウザが立ち上がって見たら.htmlだったと思います。 ここからの出力の方法はいくつかあるのかな、と個人的には思っています。 ただ今回は画像としての出力が目標でしたのでそちらで進めていきます。
まずは、{webshot}パッケージを読み込みます。このパッケージを用いると(正確にはPhantomJSというアプリケーションを用いると)Rでwebページのスクリーンショットを撮ることができます。
library(webshot)
install_phantomjs()
準備はこれで終わりです。
では作成したhtmlのスクリーンショットを撮ってみます。
例えば、一番最後に作成した表を画像として保存したいとします。
model1 %>% tbl_regression(intercept=T,
pvalue_fun = ~style_pvalue(.x, digits = 3)) %>%
italicize_levels() %>%
as_gt() %>%
gtsave("hogehoge.png")
これで、hogehoge.png
が作成されていると思います。
先ほど表を作成した時と違うのはas_gt()
を噛ませていることです。
{gtsummary}のtbl_regression()
それそのものではgtオブジェクトになっていないようですね。as_gt()
でgtオブジェクトへ変換した後にgtsave()
を行ってsaveします。
このgtsave()
の際に先ほどの{webshot}が要求されます。
また、保存は.png以外にも.htmlや.pdf、.texなども可能です。
そうです。この.texに変換したものをLaTeX中に直接組み込むことで投稿論文にも{gtsummary}の転用が可能になります。(ただし、精度はあまり良くないので吐き出した.texファイルを元に自ら手直しをする必要があります。)
{gtsummary}は、今後も開発が続くようですので、今後に期待ということになると思います。
というわけで、{gt}などを用いて表を画像として出力する方法でした。
enjoy!
Sharing is caring!