参考:Tutorial: Building 'Shiny' Applications with R
Shinyの最大の特長が"Reactivity Programming"だ。Shinyのインタラクティビティは、
ユーザ入力>R言語>ウェブ出力
を自動的に実行することで実現されている。入力値や関数の変更を評価し、必要に応じてRコードを再実行するしくみがReactivityで、ShinyはReactivityライブラリを提供している。Reactivity Programmingでは、変更を陽にモニターする必要はない。
次のExampleコードを見てみる。
ui.R
library(shiny) # Define UI for dataset viewer application shinyUI(pageWithSidebar( # Application title headerPanel("Reactivity"), # Sidebar with controls to provide a caption, select a dataset, and # specify the number of observations to view. Note that changes made # to the caption in the textInput control are updated in the output # area immediately as you type sidebarPanel( textInput("caption", "Caption:", "Data Summary"), selectInput("dataset", "Choose a dataset:", choices = c("rock", "pressure", "cars")), numericInput("obs", "Number of observations to view:", 10) ), # Show the caption, a summary of the dataset and an HTML table with # the requested number of observations mainPanel( h3(textOutput("caption")), verbatimTextOutput("summary"), tableOutput("view") ) ))
server.R
library(shiny) library(datasets) # Define server logic required to summarize and view the selected dataset shinyServer(function(input, output) { # By declaring datasetInput as a reactive function we ensure that: # # 1) It is only called when the inputs it depends on changes # 2) The computation and result are shared by all the callers (it # only executes a single time) # 3) When the inputs change and the function is re-executed, the # new result is compared to the previous result; if the two are # identical, then the callers are not notified # datasetInput <- reactive(function() { switch(input$dataset, "rock" = rock, "pressure" = pressure, "cars" = cars) }) # The output$caption is computed based on a reactive function that # returns input$caption. When the user changes the "caption" field: # # 1) This function is automatically called to recompute the output # 2) The new caption is pushed back to the browser for re-display # # Note that because the data-oriented reactive functions below don't # depend on input$caption, those functions are NOT called when # input$caption changes. output$caption <- reactiveText(function() { input$caption }) # The output$summary depends on the datasetInput reactive function, # so will be re-executed whenever datasetInput is re-executed # (i.e. whenever the input$dataset changes) output$summary <- reactivePrint(function() { dataset <- datasetInput() summary(dataset) }) # The output$view depends on both the databaseInput reactive function # and input$obs, so will be re-executed whenever input$dataset or # input$obs is changed. output$view <- reactiveTable(function() { head(datasetInput(), n = input$obs) }) })
ui.Rでは、
- "caption"という名前の textInput
- "dataset"という名前のselectInput
- "obs”という名前のnumericInput
を定義している。
server.Rの先頭が、
shinyServer(function(input, output) {
となっている。関数に渡されるinput, output各オブジェクトがuiとのやり取りを媒介している。
inputオブジェクトはウェブページ上の入力をリスト形式で取得する。Reactivityは通常の関数を"reactive"関数に渡すことで実現する。下の例では、datasetInputをreactive関数として宣言している。
datasetInput <- reactive(function() { switch(input$dataset, "rock" = rock, "pressure" = pressure, "cars" = cars) })
一方、出力はoutputオブジェクトを使う。下では、textinput "caption"への入力を、そのまま"caption"へ文字出力(reactiveText)している。
output$caption <- reactiveText(function() { input$caption })
次では、datasetinputの再実行(つまり、input$datasetの変更)を見て、summary関数の出力を、outputオブジェクトの"summary"として表示(reactivePrint)している。
output$summary <- reactivePrint(function() { dataset <- datasetInput() summary(dataset) })
こちらは、datasetInputの再実行(つまり、input$datasetの変更)または、numericInput"obs"の変更が生じた場合に、outputオブジェクトの"view"が変更される(reactiveTable)。
output$view <- reactiveTable(function() { head(datasetInput(), n = input$obs) })