Shinyのisolateを試してみた


## はじめに
- RのShinyのisolateの理解があいまいだったので、いろいろ触ってみた

## isolateを使うケース
- あるインプット値を変更したときに、即座にそれがoutputに影響してほしくないとき
- あるインプット値を変更した時に、別のinput（action）を入力したときにだけoutputに影響してほしいとき

## イメージ図
- [Stop reactions with isolate()](http://shiny.rstudio.com/articles/isolation.html) がわかりやすい

## コード：うまく動くケース
1で、input$goButtonをひも付ける。2で、isolate()で紐付けたいところを囲む

```R
library(shiny)

ui <- fluidPage(
  headerPanel("isolateのテスト"),
  sidebarPanel(
    sliderInput("obs", "Number of observations:",
                min = 0, max = 1000, value = 500),
    actionButton("goButton", "Go Button", icon("refresh"))
  ),
  mainPanel(
    plotOutput("distPlot")
  )
)

server <- function(input, output, session) {
  output$distPlot <- renderPlot({
    # 1. input$goButtonをrenderPlotのトリガーとして紐付ける
    input$goButton
    
    # 2. トリガーがあれば、input$obsの値をもとに変更
    dist <- isolate(rnorm(input$obs))
    hist(dist)
  })
}

shinyApp(ui, server)
```

## コード：うまく動かないケース1

input$goButtonを削除した場合は、ひも付けがないので、何をしてもdistが変わらないのでヒストグラムの結果は変わらない


```R
library(shiny)

ui <- fluidPage(
  headerPanel("isolateのテスト"),
  sidebarPanel(
    sliderInput("obs", "Number of observations:",
                min = 0, max = 1000, value = 500),
    actionButton("goButton", "Go Button", icon("refresh"))
  ),
  mainPanel(
    plotOutput("distPlot")
  )
)

server <- function(input, output, session) {
  output$distPlot <- renderPlot({
    # 変更されない
    dist <- isolate(rnorm(input$obs))
    hist(dist)
  })
}

shinyApp(ui, server)
```

## コード：うまく動かないケース2

isolate()がない場合は、input$obsを変更しても、input$goButtonを変更しても、histの表示が変わってしまう


```R
library(shiny)

ui <- fluidPage(
  headerPanel("isolateのテスト"),
  sidebarPanel(
    sliderInput("obs", "Number of observations:",
                min = 0, max = 1000, value = 500),
    actionButton("goButton", "Go Button", icon("refresh"))
  ),
  mainPanel(
    plotOutput("distPlot")
  )
)

server <- function(input, output, session) {
  output$distPlot <- renderPlot({
    # input$goButtonをrenderPlotのトリガーとして紐付ける
    input$goButton
    
    dist <- rnorm(input$obs)
    hist(dist)
  })
}

shinyApp(ui, server)
```

## コード：うまく動かないケース3

isolate()とinput$goButtonを削除した場合は、ひも付けもないので、input$goButtonの意味もなく、input$obsを変更したときだけhistの表示が変わる


```R
library(shiny)

ui <- fluidPage(
  headerPanel("isolateのテスト"),
  sidebarPanel(
    sliderInput("obs", "Number of observations:",
                min = 0, max = 1000, value = 500),
    actionButton("goButton", "Go Button", icon("refresh"))
  ),
  mainPanel(
    plotOutput("distPlot")
  )
)

server <- function(input, output, session) {
  output$distPlot <- renderPlot({
    dist <- rnorm(input$obs)
    hist(dist)
  })
}

shinyApp(ui, server)
```

## isolateのその他

```
input$goButton
```

上記の意味は以下と同じ意味。input$goButtonをクリックすると1が返り、続きのrenderPlotが実行される。ただし、appをはじめに起動したときは描画されなくなる

```
 if (input$goButton == 0)
      return()
```


参考の[Stop reactions with isolate()](http://shiny.rstudio.com/articles/isolation.html)とおりだが、複数のinputでの対応も下記のように書けるみたい

```
# Separate calls to isolate 
x <- isolate({ input$xSlider }) + 100
y <- isolate({ input$ySlider })  * 2
z <- x/y

# Single call to isolate 
isolate({
  x <- input$xSlider + 100
  y <- input$ySlider * 2
  z <- x/y
})

# Single call to isolate, use return value 
z <- isolate({
  x <- input$xSlider + 100
  y <- input$ySlider * 2
  x/y
})
```

## おわりに

isolate()はよくわかったが、reactive()とobserve()の理解もあやしいので次はそれを試してみる予定

## 参考
- [Stop reactions with isolate()](http://shiny.rstudio.com/articles/isolation.html)