防止双重调用闪亮的刷子反应?

Preventing double call to brush reactive in shiny?

我正在使用刷过的直方图来查询 shiny 应用程序中的样本。在我的完整应用程序中,我覆盖了一个突出显示所选区域的新直方图,并更新了显示过滤样本属性的 DT 数据 table。

我注意到每次移动时都会调用两次依赖于画笔的反应。例如,每次刷直方图时,下面的 table_data 反应都会被调用两次。

app.R

library(ggplot2)
library(shiny)

df <- data.frame(x = rnorm(1000))
base_histogram <- ggplot(df, aes(x)) +
    geom_histogram(bins = 30)

# Define UI for application that draws a histogram
ui <- fluidPage(
    column(
      plotOutput("histogram", brush = brushOpts(direction = "x", id = "brush", delay=500, delayType = "debounce")),
      width = 6
    )
)

# Define server logic required to draw a histogram
server <- function(input, output) {
    output$histogram <- renderPlot({
        p <- base_histogram
        
        current <- table_data()
        if (nrow(current) > 0) {
            p <- p + geom_histogram(data = current, fill = "red", bins = 30)
        }

        p
    })
    
    table_data <- reactive({
        print("called")
        brushedPoints(df, input$brush)
    })
}

# Run the application 
shinyApp(ui = ui, server = server)

在这个玩具示例中,它几乎不会引起注意。但是在我的完整应用程序中,必须在 table_data 反应中进行繁重的计算,而这种双重调用不必要地减慢了一切。

有什么方法可以构建应用程序,以便在刷完时反应只执行一次?


这是一张 GIF,显示 table_data 每个笔刷执行两次。

试试这个,每次画笔移动只触发一次。

library(ggplot2)
library(shiny)

df <- data.frame(x = rnorm(1000))
base_histogram <- ggplot(df, aes(x)) +
    geom_histogram(bins = 30)

# Define UI for application that draws a histogram
ui <- fluidPage(
    column(
        plotOutput("histogram", brush = brushOpts(direction = "x", id = "brush", delay=500, delayType = "debounce")),
        width = 6
    )
)

# Define server logic required to draw a histogram
server <- function(input, output) {
    output$histogram <- renderPlot({
        p <- base_histogram
        
        if(!is.null(table_data())) {
            p <- p + geom_histogram(data = table_data(), fill = "red", bins = 30)
        }
        p
    })
    
    table_data <- reactive({
        if(is.null(input$brush)) return()
        print("called")
        brushedPoints(df, input$brush)
    })
}

shinyApp(ui, server)