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。)
这很棘手。
- 为了避免在应用程序启动时自动计算,您应该设置ignoreNULL = T
- 这适用于单一条件,但 not on multiple conditions using c(recalc1,recalc2)
解决方案是:
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)
据我了解,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。)
这很棘手。
- 为了避免在应用程序启动时自动计算,您应该设置ignoreNULL = T
- 这适用于单一条件,但 not on multiple conditions using c(recalc1,recalc2) 解决方案是:
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)