1行でまとめると
R reticulateでPySimpleGUIが使えました
はじめに
RにはShinyというWebアプリケーションをつくるライブラリがあります.
しかし個人的に記法に慣れないことと, デスクトップアプリケーションには向いていないために別のライブラリを探しました.
Pythonには良いデスクトップアプリケーションのライブラリがあり, その中でもPySimpleGUIは名前の通り非常に簡潔にGUIアプリが作成できるため, こちらをR環境で使用できるかどうか試してみました.
結果としていくつか細かい注意点はありましたが, 問題なくRでPySimpleGUIが動きましたので報告いたします.
仮想環境の作製
まずconda
を用いてRとPySimpleGUIをもつ仮想環境を作りました.
conda create -y -n r-sg r-base r-essentials
conda install -y -n r-sg -c conda-forge pysimplegui
conda activate r-sg
PySimpleGUI v4.31.0がインストールできました.
conda list | grep pysimplegui
# pysimplegui 4.31.0 pyhd3deb0d_0 conda-forge
Pythonパスの設定
次にRに先ほど作ったr-sg
を認識させたいのですが, 私の環境ではreticulate::use_condaenv("r-sg")
では設定できませんでした.
options(repos = "https://cloud.r-project.org/")
if (!requireNamespace("reticulate", quietly = TRUE)) install.packages("reticulate")
reticulate::use_condaenv("r-sg")
reticulate::py_config()
# python: /home/t-taro/.local/share/r-miniconda/envs/r-reticulate/bin/python
# libpython: /home/t-taro/.local/share/r-miniconda/envs/r-reticulate/lib/libpython3.6m.so
# pythonhome: /home/t-taro/.local/share/r-miniconda/envs/r-reticulate:/home/t-taro/.local/share/# r-miniconda/envs/r-reticulate
# version: 3.6.11 | packaged by conda-forge | (default, Aug 5 2020, 20:09:42) [GCC 7.5.# 0]
# numpy: /home/t-taro/.local/share/r-miniconda/envs/r-reticulate/lib/python3.6/# site-packages/numpy
# numpy_version: 1.18.5
そのため, 一度Rを再起動させたあとでRETICULATE_PYTHON
を環境変数に書き込むことで解決しました.
library(tidyverse)
conda_path <- reticulate::conda_list()$python %>% str_subset("r-sg/bin/python")
Sys.setenv(RETICULATE_PYTHON = conda_path)
reticulate::py_config()
# python: /home/t-taro/anaconda3/envs/r-sg/bin/python
# libpython: /home/t-taro/anaconda3/envs/r-sg/lib/libpython3.7m.so
# pythonhome: /home/t-taro/anaconda3/envs/r-sg:/home/t-taro/anaconda3/envs/r-sg
# version: 3.7.8 | packaged by conda-forge | (default, Nov 27 2020, 19:24:58) [GCC 9.3.0]
# numpy: [NOT FOUND]
#
# NOTE: Python version was forced by RETICULATE_PYTHON
PySimpleGUIのテスト
ここからはPySimpleGUIの日本語公式ドキュメントにしたがって試していきます.
例 1 - ワンショットウィンドウ
注意点は下記のとおりです.
-
layout
変数の定義のときにreticulate::r_to_py()
を用いてPythonのlist
に変換する必要がありました. -
values = window$read()
での返り値が2層のlistのため,flatten
で1層のlistにしました.
library(tidyverse)
conda_path <- reticulate::conda_list()$python %>% str_subset("r-sg/bin/python")
Sys.setenv(RETICULATE_PYTHON = conda_path)
sg <- reticulate::import("PySimpleGUI")
# ウィンドウの内容を定義する
layout <- list( c(sg$Text("お名前はなんですか?")),
c(sg$Input()),
c(sg$Button("はい"))) %>%
reticulate::r_to_py(.)
# ウィンドウを作成する
window = sg$Window('ウィンドウタイトル', layout)
# ウィンドウを表示し、対話する
values = window$read()
values = values %>% flatten
# 収集された情報で何かをする
glue::glue('ハロー ', values$"0", "! PySimpleGUIを試してくれてありがとう")
# 画面から削除して終了
window$close()
例 2 - インタラクティブウィンドウ
注意点は以下の2つです.
-
c(sg$Text(size=c(55L,1L), key="-出力-"))
のsize
の中身は整数型を指定します - 私の環境では
sg$WINDOW_CLOSED
の返り値は終了ボタンを押す押さないにかかわらず常にNULL
のようでした. 終了ボタンを押すとevent
にはNULLが返ってくるため,is.null(event)
で代用することにしました.
library(tidyverse)
conda_path <- reticulate::conda_list()$python %>% str_subset("r-sg/bin/python")
Sys.setenv(RETICULATE_PYTHON = conda_path)
sg <- reticulate::import("PySimpleGUI")
# ウィンドウの内容を定義する
layout <- list( c(sg$Text("お名前はなんですか?")),
c(sg$Input(key="-入力-")),
c(sg$Text(size=c(55L,1L), key="-出力-")),
c(sg$Button("はい"), sg$Button("終了"))) %>%
reticulate::r_to_py(.)
# ウィンドウを作成する
window = sg$Window('ウィンドウタイトル', layout)
# イベントループを使用してウィンドウを表示し、対話する
while (TRUE){
input <- window$read()
event <- input[[1]]
values <- input %>% flatten
# ユーザーが終了したいのか、ウィンドウが閉じられたかどうかを確認してください
if (event == "終了" || is.null(event))
break
# Output a message to the window
window['-出力-']$update(glue::glue('ハロー ', values$'-入力-', "! PySimpleGUI をお試しいただきありがとうございます"))
}
# 画面から削除して終了
window$close()
まとめ
R reticulateをもちいてPySimpleGUIのチュートリアルを再現することができました.
conda環境のセッティングにすこし苦労しましたが, PySimpleGUIはほとんど問題がなく実行できました.
イベントループ内でRの処理してPySimpleGUIに返すこともできそうです. 試してみようと思います.
実行環境
sessionInfo
> sessionInfo()
R version 4.0.3 (2020-10-10)
Platform: x86_64-conda-linux-gnu (64-bit)
Running under: Linux Mint 20
Matrix products: default
BLAS/LAPACK: /home/t-taro/anaconda3/envs/r-sg/lib/libopenblasp-r0.3.12.so
locale:
[1] LC_CTYPE=C.UTF-8 LC_NUMERIC=C LC_TIME=C.UTF-8
[4] LC_COLLATE=C.UTF-8 LC_MONETARY=C.UTF-8 LC_MESSAGES=C.UTF-8
[7] LC_PAPER=C.UTF-8 LC_NAME=C LC_ADDRESS=C
[10] LC_TELEPHONE=C LC_MEASUREMENT=C.UTF-8 LC_IDENTIFICATION=C
attached base packages:
[1] stats graphics grDevices utils datasets methods base
other attached packages:
[1] forcats_0.5.0 stringr_1.4.0 dplyr_1.0.2 purrr_0.3.4
[5] readr_1.4.0 tidyr_1.1.2 tibble_3.0.4 ggplot2_3.3.2
[9] tidyverse_1.3.0
loaded via a namespace (and not attached):
[1] Rcpp_1.0.5 pillar_1.4.7 compiler_4.0.3 cellranger_1.1.0
[5] dbplyr_2.0.0 tools_4.0.3 lattice_0.20-41 jsonlite_1.7.1
[9] lubridate_1.7.9.2 lifecycle_0.2.0 gtable_0.3.0 pkgconfig_2.0.3
[13] rlang_0.4.9 Matrix_1.2-18 reprex_0.3.0 cli_2.2.0
[17] rstudioapi_0.13 DBI_1.1.0 haven_2.3.1 withr_2.3.0
[21] xml2_1.3.2 httr_1.4.2 rappdirs_0.3.1 generics_0.1.0
[25] vctrs_0.3.5 fs_1.5.0 hms_0.5.3 grid_4.0.3
[29] tidyselect_1.1.0 reticulate_1.18 glue_1.4.2 R6_2.5.0
[33] fansi_0.4.1 readxl_1.3.1 modelr_0.1.8 magrittr_2.0.1
[37] ps_1.4.0 backports_1.2.0 scales_1.1.1 ellipsis_0.3.1
[41] assertthat_0.2.1 rvest_0.3.6 colorspace_2.0-0 stringi_1.5.3
[45] munsell_0.5.0 broom_0.7.2 crayon_1.3.4