【Python】DashでRの出力を呼び出して描画する
背景
Dashで可視化アプリケーションを作りたいが、出力する内容の一部をRのpackageから出力したい場面がありました。
UI(dropdown)はDashで用意して、計算の部分はRで行うような簡単なサンプルを作ってみます。
-
環境
- macOSX Mojave version 10.14,3
- Python 3.6.1
- R version 3.5.3
- 実行環境はlocalで
-
仕様
- Dropdownで表示するBayesian networkを選んで,Rでinputに応じたネットワークが返されて描写される
方法
PythonからRを実行するとか、やり方は無数にありそうですが、ひとまず以下の流れで1パターン実装してみます。
- 目次
- 1. R(plumber)でAPIserverを準備
- 2. Dashで、inputの内容をクエリパラメータに反映させて
html.Img()
で1.のエンドポイントにGETリクエストを送る - 3. できた
実装
ファイル構造は以下のようにします
$ tree
.
├── R
│ ├── run.R
│ └── api.R
├── app
│ └── app.py
└── README.md
1. R(plumber)でAPI serverを準備
GETリクエストのクエリパラメータ?type=
に応じて描くBNが変わるようにfunctionを書きます。
library(plyr)
library(dplyr)
library(bnlearn)
library(plumber)
library(magrittr)
# BNを定義
alarm.model.string <- paste("[HIST|LVF][CVP|LVV][PCWP|LVV][HYP][LVV|HYP:LVF]",
"[LVF][STKV|HYP:LVF][ERLO][HRBP|ERLO:HR][HREK|ERCA:HR][ERCA]",
"[HRSA|ERCA:HR][ANES][APL][TPR|APL][ECO2|ACO2:VLNG][KINK]",
"[MINV|INT:VLNG][FIO2][PVS|FIO2:VALV][SAO2|PVS:SHNT][PAP|PMB][PMB]",
"[SHNT|INT:PMB][INT][PRSS|INT:KINK:VTUB][DISC][MVS][VMCH|MVS]",
"[VTUB|DISC:VMCH][VLNG|INT:KINK:VTUB][VALV|INT:VLNG][ACO2|VALV]",
"[CCHL|ACO2:ANES:SAO2:TPR][HR|CCHL][CO|HR:STKV][BP|CO:TPR]", sep = "")
alarm.net <- alarm %>%
names %>%
empty.graph %>%
`modelstring<-`(value = alarm.model.string)
#* @get /bayesiannetwork
#* @png
bn <- function(type="type1") {
if(type=="type1"){
plot(hc(learning.test))
} else if(type=="type2"){
graphviz.plot(alarm.net)
} else {
graphviz.plot(moral(alarm.net))
}
}
細かい解説
これによって
/bayesiannetwork?type=type1
なら↓が返されて、plot(hc(learning.test))
/bayesiannetwork?type=type2
なら↓が、graphviz.plot(alarm.net)
/bayesiannetwork?type=type3
なら↓が返されるapiができます!graphviz.plot(moral(alarm.net))
- 上の
api.R
を実行するscriptを用意します.
library(plumber)
rapi <- plumb("api.R")
rapi$run(port=8888)
ここまで準備できたら、以下のコマンドでAPIサーバーを立ち上げます
$ Rscript run.R
Running plumber API at http://127.0.0.1:8888
2. Dashで、inputの内容をクエリパラメータに反映させてhtml.Img()
で1.のエンドポイントにGETリクエストを送る
- dashの
dash_core_components.Dropdown
で選んだ内容が、クエリパラメータに反映されたリンクを生成するような処理を書きます
import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output, State
app = dash.Dash()
app.title = 'dash app with python and R'
app.scripts.config.serve_locally = True
app.config.suppress_callback_exceptions = True
app.layout = html.Div([
html.H1(children='dash app with python and R'),
dcc.Dropdown(
id='my-dropdown',
options=[
{'label': 'Bayesian network 1', 'value': 'type1'},
{'label': 'Bayesian network 2', 'value': 'type2'},
{'label': 'Bayesian network 3', 'value': 'type3'}
],
value='type1'
),
html.Div(id='output-container')
])
@app.callback(
dash.dependencies.Output('output-container', 'children'),
[dash.dependencies.Input('my-dropdown', 'value')])
def render_link_with_parameter(value):
url = 'http://localhost:8888/bayesiannetwork' + "?type=" + value
render_div = html.Div(
html.Div([
html.P(url),
html.Img(src=url)
])
)
return render_div
if __name__ == '__main__':
app.run_server(debug=True)
- dropdownで選んだ内容が、のちに生成するlinkのurlに反映されるようになっています。
- dropdownで描画するネットワークを選ぶ
-
render_link_with_parameter
が実行される - 先ほど準備したAPIにGETリクエストが飛んで、RがBNを描画する
- htmlにネットワークが表示される
- ここまで準備できたら、別なterminalからdashのapplicationのサーバーを起動します
$ python ¥app.py
3. できた
おわりに
- PythonとRの連携方法として、API経由でやりとりするのは便利そうでした
- 画像の出力だけじゃなく、
htmlwidgets
などもRから返せるとのことです - よりスマートな方法があればぜひ教えてください
参考
Author And Source
この問題について(【Python】DashでRの出力を呼び出して描画する), 我々は、より多くの情報をここで見つけました https://qiita.com/sasaki_K_sasaki/items/e0b9e424106abb2313e1著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .