flex_dashboard shiny_prerendered 带有 eventReactive 过滤

flex_dashboard shiny_prerendered with eventReactive filtering

我正在尝试使用 runtime: shiny_prerendered 构建一个数据繁重、计算繁重的闪亮 flex_dashboard。 我希望所有计算和过滤都在服务器端完成,渲染在客户端完成。 shiny_prerendered 让我可以节省客户端和服务器的启动时间。在下面,我有一个我所做的简化版本。 我有一个大数据集(下面的 faithful)。我正在根据客户的需要过滤该数据。筛选后的数据应该用于仪表板的所有图表和结果。 我将库放在 context="setup",UI 和 context="render"(不需要,因为它是默认设置)。

我还想对按钮点击进行过滤和绘图。所以我投入 context="server" 两个 eventReactive 函数。一种用于过滤数据,另一种用于 直方图箱的选择。

最后,对于每个结果(绘图或 table),我将 renderPlotrenderTable 放入输出变量 在 context="server" 中并在 context="render" 中显示它们。在里面 渲染函数(Plot 或 Table),我使用过滤数据的 eventReactive 函数(并获取 bin 的数量)。

faithful_filtered()做过滤,在下面2renderPlot里面调用。 1-这是否意味着数据被过滤了两次? 2- 手术进行了两次吗?由于我的数据非常大,所以我还有更多 在实际项目中输出,那将是非常缓慢和低效的。 3- 如果以上 2 个问题是肯定的,我如何首先获得过滤数据的按钮,然后在所有绘图中使用该数据并呈现 tables?

原型代码如下:

---
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. 数据只在eventReactive初始化时过滤一次, 之后,通过单击操作按钮
  2. 进行每次更新
  3. 单击操作按钮时,我希望操作执行一次,而不是两次。
  4. 因此我认为按钮的行为符合预期。

检查引擎盖下发生的事情的好地方是 Reactive Log Visualizer。但是,在您仪表板的当前形式中(在 shiny_prerendered 的 rmarkdown 中)我无法得到它 运行ning.

仪表板的香草闪亮方法如下所示:

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 中发生的事情。

我们可以使用 reactives 和 isolate:

重写仪表板
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 的其他两种方法的行为几乎相同,但我还无法确定。