带有事件响应过滤功能的flex_dashboard shine_prerendered

时间:2019-09-17 10:23:29

标签: r shiny flexdashboard

我正在尝试使用runtime: shiny_prerendered构建一个数据密集,计算繁重的flex_dashboard。 我希望所有计算和过滤都在服务器端完成,在客户端进行渲染。 Shiny_prerendered允许我节省客户端和服务器的启动时间。在下面,我做了一个简化的版本。 我有一个很大的数据集(下面的faithful)。我正在根据客户的需求过滤数据。过滤后的数据应在仪表板的所有图表和结果中使用。 我将库放在context="setup"的用户界面context="render"中(默认情况下不需要)。

我还想对按钮单击做出反应。所以我把 context="server"个两个eventReactive函数。一种用于数据过滤,另一种用于 选择直方图箱。

最后,对于每个结果(图或表),我将renderPlotrenderTable放入输出变量 context="server"中将其显示在context="render"中。在里面 渲染函数(图或表),我使用eventReactive函数来过滤数据(并获取箱数)。

faithful_filtered()进行过滤,并在下面的2 renderPlot内部被调用。 1-这是否意味着数据被过滤两次? 2-操作是否完成两次?由于我的数据很大,所以我还有更多 实际项目中的输出,那将是非常缓慢且低效的。 3-如果以上两个问题是肯定的,我该如何首先获得一个按钮以过滤数据,然后在所有要绘制的绘图和表格中使用该数据?

这是原型代码:

---
title: "test shiny_prerendered with button"
output: 
  flexdashboard::flex_dashboard:
    orientation: rows
editor_options: 
  chunk_output_type: console
runtime: shiny_prerendered 
---


```{r, include=FALSE, message=FALSE, context="setup"}
library(tidyverse)
library(flexdashboard)
library(plotly)
library(shiny)
library(knitr)
```

Input {.sidebar data-width=300}
-------------------------------------

```{r, echo=FALSE, context="render"}
sliderInput("bins", "Number of bins:", min = 1, max = 50, value = 30)
textInput("min_e", "min eruptions", min(faithful$eruptions))
textInput("max_e", "max eruptions", max(faithful$eruptions))
actionButton(inputId = "OK", label = "OK")
```

```{r, context="server"}
nbins = eventReactive(input$OK, {input$bins})
faithful_filtered = eventReactive(input$OK, {faithful %>% filter(eruptions>=input$min_e,
                                                                 eruptions<=input$max_e)})

```

Row
-----------------------------------------------------------------------

### Plot 1 - filter reactive, bin reactive

```{r, context="server"}
output$distPlot1 <- renderPlot({
  x <- faithful_filtered()[, 2]  # Old Faithful Geyser data
  bins <- seq(min(x), max(x), length.out =  nbins() + 1)
  hist(x, breaks = bins, col = 'darkgray', border = 'white')
})
```

```{r, echo=FALSE}
plotOutput("distPlot1")
```

### Plot 2 - twice the number of bins - filter reactive, bin is not

```{r, context="server"}
output$distPlot2 <- renderPlot({
  x <- faithful_filtered()[, 2]  # Old Faithful Geyser data
  bins <- seq(min(x), max(x), length.out = input$bins*2 + 1)
  hist(x, breaks = bins, col = 'darkgray', border = 'white')
})
```

```{r, echo=FALSE}
plotOutput("distPlot2")
```

### Table - filter reactive

```{r, message=FALSE, context="server"}
output$table = renderTable({
  head(faithful_filtered())
})

```

```{r, echo=FALSE}
tableOutput("table")
```

1 个答案:

答案 0 :(得分:0)

我的理解是:

  1. 初始化eventReactive时,数据仅过滤一次, 然后,通过单击操作按钮
  2. 进行每次更新
  3. 单击操作按钮时,我确实希望该操作执行一次,而不是两次。
  4. 因此,我认为该按钮的行为符合预期。

Reactive Log Visualizer是检查引擎盖下正在发生的事情的好地方。但是,在您当前的仪表板形式中(与rmarkdown一起使用shiny_prerendered),我无法使其运行。

仪表盘上的原始光泽效果如下所示:

library(tidyverse)
library(flexdashboard)
library(plotly)
library(shiny)
library(knitr)

shinyApp(ui = fluidPage(

  sidebarLayout(

    sidebarPanel(
      sliderInput("bins", "Number of bins:", min = 1, max = 50, value = 30),
      textInput("min_e", "min eruptions", min(faithful$eruptions)),
      textInput("max_e", "max eruptions", max(faithful$eruptions)),
      actionButton(inputId = "OK", label = "OK")
    ),

    mainPanel(
      fluidRow(
        column(4, plotOutput("distPlot1")),
        column(4, plotOutput("distPlot2")),
        column(4, tableOutput("table"))
    )

  )

)
),

  server = function(input, output) {

    nbins = eventReactive(input$OK, {input$bins})

    faithful_filtered = eventReactive(input$OK, {

      faithful %>% filter(eruptions >= input$min_e,
                          eruptions <= input$max_e)

      })

    output$distPlot1 <- renderPlot({
      x <- faithful_filtered()[, 2]  # Old Faithful Geyser data
      bins <- seq(min(x), max(x), length.out =  nbins() + 1)
      hist(x, breaks = bins, col = 'darkgray', border = 'white')
    })


    output$distPlot2 <- renderPlot({
      x <- faithful_filtered()[, 2]  # Old Faithful Geyser data
      bins <- seq(min(x), max(x), length.out = input$bins*2 + 1)
      hist(x, breaks = bins, col = 'darkgray', border = 'white')
    })

    output$table = renderTable({
      head(faithful_filtered())
    })


  }

)

您可以在此处运行反应式日志可视化器,但是-至少据我所知-要查看eventReactives中正在发生的事情并不容易。

我们可以使用reactiveisolate来重写仪表板:

library(tidyverse)
library(flexdashboard)
library(plotly)
library(shiny)
library(knitr)

shinyApp(ui = fluidPage(

  sidebarLayout(

    sidebarPanel(
      sliderInput("bins", "Number of bins:", min = 1, max = 50, value = 30),
      textInput("min_e", "min eruptions", min(faithful$eruptions)),
      textInput("max_e", "max eruptions", max(faithful$eruptions)),
      actionButton(inputId = "OK", label = "OK")
    ),

    mainPanel(
      fluidRow(
        column(4, plotOutput("distPlot1")),
        column(4, plotOutput("distPlot2")),
        column(4, tableOutput("table"))
    )

  )

)
),

  server = function(input, output) {

    nbins = reactive({input$OK
                     isolate(input$bins)})

     faithful_filtered = reactive({input$OK

      faithful %>% filter(eruptions >= isolate(input$min_e),
                          eruptions <= isolate(input$max_e))

      })

    output$distPlot1 <- renderPlot({
      x <- faithful_filtered()[, 2]  # Old Faithful Geyser data
      bins <- seq(min(x), max(x), length.out =  nbins() + 1)
      hist(x, breaks = bins, col = 'darkgray', border = 'white')
    })


    output$distPlot2 <- renderPlot({
      x <- faithful_filtered()[, 2]  # Old Faithful Geyser data
      bins <- seq(min(x), max(x), length.out = input$bins*2 + 1)
      hist(x, breaks = bins, col = 'darkgray', border = 'white')
    })

    output$table = renderTable({
      head(faithful_filtered())
    })


  }

)

在这里,反应式日志可视化器基本上可以确认反应式仅在单击按钮后才执行。

我希望使用eventReactive的其他两种方法的行为几乎相同,但是我尚无法确定。