琥珀色呑んだくれ備忘録

メモとか備忘録とか

Rで作成した図表を「パワポでくれ」と言われた時の対処法

2020年9月7日現在、GitHub版ではofficer関連の対応がされたようだ。

niszetさん(id:niszet)から、コメントで教えていただいた。

GitHub上のexportパッケージをインストールしてコードを一式流してみたのですが、現時点(2020/Sep/06)では一通りコードが動くことを確認しました。 table2*** 関数の内部で使用している、flextableパッケージ起因の警告が出ていますが、それ以外は期待した動作をしていると思います。

また、broom::tidy(iris3)も警告は出ますが値が表示されるようです。

rglがpngのみサポートしている、は状況変わらずです(rglパッケージ自身がpngのみ対応している)

セットアップ

CRANは相変わらず凍結中なので、GitHubから最新のバージョンをインストールする。

github.com

install.packages("officer")
install.packages("rvg")
install.packages("openxlsx")
install.packages("ggplot2")
install.packages("flextable")
install.packages("xtable")
install.packages("rgl")
install.packages("stargazer")
install.packages("tikzDevice")
install.packages("xml2")
install.packages("broom")
install.packages("devtools")
library(devtools)
devtools::install_github("tomwenseleers/export")

パワポにする

基本的には、exportパッケージが提供する関数に、何も考えずにオブジェクトを放り込むだけ。

描画オブジェクトを Microsoft PowerPointにエクスポート

直前にプロットした描画オブジェクトをPowerPointに埋め込むことができる。ファイル名を指定しないとRplot.pptxという名前で出力される。

ggp <- iris %>% 
  ggplot(aes(x = Sepal.Length, y = Sepal.Width, colour = Species)) +
  geom_point()

ggp

f:id:kato-satoshi-0:20191219143749p:plain

graph2ppt()
>  Exported graph as Rplot.pptx

ベクター形式で出力されるため、PowerPointで開いて[グループ化]から解除⇔再グループ化が可能。

f:id:kato-satoshi-0:20191219144226p:plain

ggplotでなくてもOK。

plot(Sepal.Length ~ Sepal.Width, data = iris)

f:id:kato-satoshi-0:20191219144029p:plain

graph2ppt()
>  Exported graph as Rplot.pptx

f:id:kato-satoshi-0:20191219144650p:plain

直前に描画したものでなくても、描画オブジェクトが残っていれば出力できる。

ggp + geom_line() # ラインを追加描画
graph2ppt(ggp)    # ラインを追加描画していないプロットがエクスポートされる
>  Exported graph as Rplot.pptx

(イメージ省略)

スライドの追加

同じ出力ファイル名を指定して、append = TRUEを指定することで、次のスライドとして追記することができるのでfor()などを使って、一度に多量のスライドを作成することもできる。

注意点は、

  • 指定したファイルを開いたままにすると出力に失敗する*1
  • append = TRUEを指定しないと、同名のファイルに上書きされてしまう
for (sp in unique(iris$Species)) {
  ggp <- iris %>% 
    filter(Species == sp) %>% 
    ggplot(aes(x = Sepal.Length, y = Sepal.Width, colour = Petal.Length)) +
    geom_point() +
    labs(title = sp)
  
  graph2ppt(ggp, file = "./my_plot.pptx", append = TRUE)
  
}
>  Exported graph as ./my_plot.pptx
>  Exported graph as ./my_plot.pptx
>  Exported graph as ./my_plot.pptx

f:id:kato-satoshi-0:20191219145532p:plain

データフレームをPowerPointにエクスポート

データフレームの先頭の数件を表としてスライドに埋め込んでみる。全件埋め込むと、たいていの場合はひどいことになるので要注意。

iris %>% head() %>% table2ppt(append = TRUE)
>  Exported table as Rtable.pptx

(イメージ省略)

プロットとサマリーを組み合わせたスライドとかが便利そう。

ggp <- iris %>% 
  ggplot(aes(y = Sepal.Width, x =  Sepal.Length, color = Species)) +
  geom_point() + 
  geom_smooth(method=lm) 
graph2ppt(ggp, file = "./iris.pptx")
>  Exported graph as ./iris.pptx

tbl <- iris %>%
    group_by(Species) %>%
    group_modify(~ broom::tidy(lm(Sepal.Width ~ Sepal.Length, data = .x))) %>%
  table2ppt(file = "./iris.pptx", append = TRUE)
>  Exported table as ./iris.pptx

f:id:kato-satoshi-0:20191219145956p:plain

その他のオブジェクトをPowerPointにエクスポート

summary.lm()やsummary.lm()なども直接放り込めば表にしてくれる。*2 一部のオブジェクトはadd.rownames = TRUEを指定して、行名を明示的に取り込む必要があるので注意。

fit <- lm(Sepal.Width ~ Sepal.Length, data = iris)
x <- summary(fit)
tbl <- table2ppt(x = x, file = "./iris_ggplot.pptx", add.rownames = TRUE, append = TRUE)
>  Exported table as ./iris_ggplot.pptx

(イメージ省略)

その他のエクスポート

MS Office以外の出力にも充実しているので、好きなファイル形式にお任せで出力したいときには良いのでは。 

作図データのエクスポート

f:id:kato-satoshi-0:20191219150526p:plain

graph2office()は、オプションで様々な調整ができるが、代表的なものだけ紹介。

  • aspectr アスペクト比の調整
  • orient 用紙の縦横向きの指定("auto", "portrait", "landscape")
  • upscale TRUEを指定すると用紙いっぱいになるまでプロットを拡大する

表データのエクスポート

data.frameをはじめとして、xtable::xtable()broom::tidy()でサポートされているオブジェクトを出力できる。ファイル名を指定しない場合、Rtable+拡張子というファイルが作られる。

f:id:kato-satoshi-0:20191219150610p:plain

Excelへのエクスポート

table2excel()openxlsxパッケージの機能をコンパクトにまとめてくれている。loadWorkbook()またはcreateWorkbook()addWorksheet()createStyle()writeData()addStyle()saveWorkbook()をしなくていいので、お手軽でいい。

エクセルは同一ファイル内で同名のシートを許さないので、append = TRUEでシートを追加しようとするとエラーになる。

f:id:kato-satoshi-0:20191219165944p:plain

tbl <- table2excel(iris, "./my_table.xlsx")
>  Exported table as ./my_table.xlsx
tbl <- table2excel(iris, "./my_table.xlsx", append = TRUE)
>  Error in addWorksheet(doc, sheetName = sheetName): A worksheet by that name already exists! Sheet names must be unique case-insensitive.

シートを追加したい場合はsheetNameオプションをつかって、重複しないようにシート名をつけてやればよい。

sheet_index = 2
tbl <- table2excel(iris, "./my_table.xlsx", append = TRUE, sheetName = paste("sheet", sheet_index))
>  Exported table as ./my_table.xlsx

f:id:kato-satoshi-0:20191219151002p:plain

table2csv()write.csv()でもよさそうに思うが、lmなどの各種オブジェクトをわざわざ自分でテーブル形式にしなくてもdata.frameを返してくれるので、一時ファイルの保存機能付きお手軽コンバータとしても使える?かも。

fit <- lm(yield ~ block + N * P + K, npk)
x <- summary(fit)
tbl <- table2csv(x)
>  Exported table as Rtable.csv
tbl %>% str
>  'data.frame':  10 obs. of  4 variables:
>   $ Estimate  : num  52.86 3.42 6.75 -3.9 -3.5 ...
>   $ Std. Error: num  2.55 2.8 2.8 2.8 2.8 2.8 2.28 2.28 1.61 3.23
>   $ t value   : num  20.71 1.22 2.41 -1.39 -1.25 ...
>   $ Pr(>|t|)  : chr  "<0.01" "0.24" "0.03" "0.18" ...
>   - attr(*, "align")= chr  "r" "r" "r" "r" ...
>   - attr(*, "digits")= num  NA 2 2 2 NA
>   - attr(*, "display")= chr  "s" "f" "f" "f" ...

また、多彩なオブジェクトに対応しているのだが、あくまでxtable::xtable()broom::tidy()が扱えるものに限られるため、例えばarray には対応してなかったりする。

table2excel(iris3)
>  Error in table2spreadsheet(..., type = "XLS"): array is currently not supported by table2office
xtable::xtable(iris3)
>  Error in UseMethod("xtable"):  'xtable' をクラス "c('array', 'double', 'numeric')" のオブジェクトに適用できるようなメソッドがありません
broom::tidy(iris3)
>  Error: All columns in a tibble must be 1d or 2d objects:
>  * Column `x` is array

Word/PowerPointへのエクスポート

table2doc()table2ppt()も内部ではflextableに渡すための面倒な調整をやっている。素直に恩恵にあずかりたい。

rgl 3Dオブジェクトのエクスポート

rglパッケージが出力する3DプロットをPNGで保存する。現在のバージョンではPNG形式しかサポートしていない。サンプルコードはあるものの、(いまではPNGもサポートされていない)https://stackoverflow.com/questions/4543272/rgl-snapshot-no-longer-worksらしい

# Create a file name
filen <- tempfile(pattern = "rgl") # or 
# filen <- paste("YOUR_DIR/rgl")

# Generate a 3D plot using 'rgl'
x = y = seq(-10, 10, length = 20)
z = outer(x, y, function(x, y) x^2 + y^2)
rgl::persp3d(x, y, z, col = 'lightblue')

# Save the plot as a png
rgl2png(file = "temp.png")

*1:結果を確認しようとして、よくやってしまいがち

*2:実際にはxtableかbroom::tidyがテーブルに変換している