個人的(?)にIOT開発で無敵だと考えているR/Shinyに関して、ちょっとしたコツみたいなものをつらつら書き残しておきたいと思います。
自分がつまずいたところがまず複数のデータフレームを1つのReactivityで処理するのにどう書いたら良いかというところです。実は何通りかあるようなのでこの記事ではそれの分類まで記載しておきます(完全動作サンプルは時間ができたら用意するのでしばらくお待ちください)。
※ちなみに以前は永続代入(グローバル変数)を使う方法も併記していましたが、Shiny-Serverで複数ユーザー同時使用時に他ユーザーのデータで上書きされる現象が見つかったため、そちらの記載は削除しました。多分同一インスタンス内でグローバル変数を使っているせいかなとは想像しています。
Reactivityとは
Shinyはフォームへの入力結果が勝手に画面に反応される動作がデフォルトになっています(乱暴な表現ですが、、)。それのスコープを定義しているのがReactivityという概念で、適切な区切りにしておかないと上手く動かないことがあります。詳しくはココ
http://shiny.rstudio.com/articles/reactivity-overview.html
データ読み込み方法の分類
eventReactive()で受けとる
actionButtonなどが押されたときに読み込む、という場合に有効です。Buttonを複数用意して異なるデータセットを異なるタイミングで読み込むことも可能です(例えばヘッダー情報を読み込むボタンでヘッダー一覧を読み込み、それの詳細が必要な場合は詳細読み込みボタンを押す、などのケースが考えられます)。
reload_head <- eventReactive(input$session_load, {
#値を演算、複数DFの場合はリスト
#リストで返す
return(list(data1=data1,data2=data2))
}
output$header_list <- renderTable({
#リストの場合
data <- reload_head()[["data1"]]
data
})
reactive()でくくる
これは演算全体をreactiveにする場合に有効で、画面上で自動更新を実現させたい時などはこれを使うと良いです。
autoInvalidate <- reactiveTimer(15000) #再読み込みタイマーの設定
reload <- reactive({
#自動更新フラグがオンの時は自動更新させる
if (input$auto_reload){
autoInvalidate()
}
#値を演算、複数DFの場合はリスト
return(list(data1=data1,data2=data2))
})
output$list <- renderTable({
data <- reload_head()[["data1"]]
data
})
reactiveValues()な変数を定義する
上記2つとほぼ同じことができるのですが、関数の返り値としての受け取りをする必要がなくなります。
tmp <- reactiveValues() #データ貯めるテンポラリバッファのリスト
observeEvent(input$reload, { #reloadボタンが押されたら、、
#tmpリストに演算結果をセット
tmp$data1_rv <- data1
tmp$data2_rv <- data2
})
output$plot <- renderPlot({
hist(tmp$data1_rv$Strength, breaks = 60, main = NULL)
})