eventReactive 在输入不变的情况下重新计算已经计算的对象

eventReactive recalculates already calculated objects with unchanged input

据我了解,eventReactive(或任何反应函数)不​​应重新计算相关输入未更改的内容,但这就是我的情况。我很确定我做错了什么,但我只是不知道是什么。本质上,我有两个 eventReactive 函数,一个涉及非常耗时的计算,另一个主要是绘图(应该很快)。但是,即使我更改了一些绘图输入,第一个 eventReactive 函数也会执行(即使不需要)。

这是我的代码的简化版本:

server <- function(input, output) {
    res_tabl <-
        eventReactive(c(input$recalc, input$recalc2), # this is a time-consuming calculation
                      ignoreNULL = FALSE, {
                          prep_sim(
                              gg_start = input$gg_start,
                              gg_end = input$gg_end
                          )
                      })
    threeplots <-
        eventReactive(c(input$recalc, input$recalc2), # this is for plotting
                      ignoreNULL = FALSE, {
                          prep_plot(
                              results_to_plot = res_tabl(),
                              yval_opt = input$yval_opt
                          )
                      })

    output$esdc_plot_comb <- renderPlot({
        threeplots()[[1]]
    })
    output$esdc_plot_tot <- renderPlotly({
        threeplots()[[2]]
    })
    output$esdc_plot_comb2 <- renderPlot({
        threeplots()[[1]]
    })
    output$esdc_plot_tot2 <- renderPlotly({
        threeplots()[[2]]
    })
    output$esdc_table <- renderDataTable({
        res_tabl()
    })
}

我应该怎么做才能在按下单个操作按钮时只更改 input$yval_opt,只有第二个 eventReactive 内容会 运行? (在我点击按钮之前,什么都不应该 运行。)

不太重要——也许这应该是一个单独的问题——正如你所看到的,我将两个返回的图分别渲染了两次。是否有更有效的方法来做到这一点?

(完整代码可用here。)

这很棘手。

eventReactive(req(isTruthy(input$recalc1) | isTruthy(input$recalc2)), ignoreNULL = T,...
  • 添加了一个 reactiveVal() 来跟踪上次计算更新

我认为以下 Minimal Reproducible 示例可以满足您的需求:

library(shiny)

# Define UI 
ui <- fluidPage(

    # Application title
    titlePanel("Test"),

    # Sidebar with a slider inpust 
    sidebarLayout(
        sidebarPanel(
            sliderInput("vizslider",
                        "viz percentage:",
                        min = 1,
                        max = 100,
                        value = 30),
            sliderInput("calcslider",
                        "Calculation duration (s):",
                        min = 1,
                        max = 10,
                        value = 2),
            actionButton("recalc1", "Calc 1"),
            actionButton("recalc2", "Calc 2"),
        ),

        # Show result
        mainPanel(
           textOutput("result")
        )
    )
)

# Define server logic 
server <- function(input, output) {
    lastcalc <- reactiveVal(0)
    run <- reactive({})
    calcresult <- eventReactive(req(isTruthy(input$recalc1) | isTruthy(input$recalc2)), ignoreNULL = T, {
        if (lastcalc()==input$calcslider)  {return("last calculation")} else {lastcalc(input$calcslider)}
        cat("Start calc for ",input$calcslider, "seconds\n")
        Sys.sleep(input$calcslider)
        cat("End calc \n")
        paste("calculation done in",input$calcslider,"seconds")

    })

    output$result <- eventReactive(c(input$recalc1,input$recalc2), ignoreNULL = T, {
       req(calcresult())
       paste("filter",input$vizslider,"% of a ",calcresult())
    })
}

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