我有一个闪亮的应用程序,其中多个反应组件使用计算速度很慢的函数的相同结果。为了避免多次计算慢函数,我可以使用reactiveValues()
当输入发生变化时重新计算函数,并使结果可供所有需要它的反应组件使用。
但是,如果reactiveValues
对象是一个data.table
,然后我使用更新它:=
,shiny 不会检测到更改,并且依赖它的输出不会更新。
有没有办法使用 data.table 通过引用分配reactiveValues
或者避免多次重新计算函数的另一种方法。
这是一个使用 data.table 按引用分配的可重现示例,其中output$result2
输入更改时无法更新:
library(shiny)
library(data.table)
library(plotly)
ui = fluidPage(
sidebarLayout(
sidebarPanel(
sliderInput('x1', 'x1', min=0, max=2, value=1, step=0.1)
),
mainPanel(
plotlyOutput('result1'),
verbatimTextOutput('result2')
)
)
)
server = function(input, output) {
values <- reactiveValues()
values$dt = data.table(v1 = 1:100, v2 = 1)
slow.func = function(my.dt, x) {
Sys.sleep(2)
my.dt[, v2 := v1^x]
}
output$result1 = renderPlotly({
values$dt = slow.func(values$dt, input$x1)
plot_ly(values$dt) %>%
add_lines(x = ~v1, y = ~v2)
})
output$result2 = renderText({
paste('Final value =', values$dt[.N, v2])
})
}
shinyApp(ui = ui, server = server)
为了进行比较,这里是使用 data.frames 标准分配的服务器函数版本,它确实按预期执行:
server = function(input, output) {
values <- reactiveValues()
values$dt = data.frame(v1 = 1:100, v2 = 1)
slow.func = function(my.dt, x) {
my.dt$v2 = my.dt$v1^x
Sys.sleep(2)
my.dt
}
output$result1 = renderPlotly({
values$dt = slow.func(values$dt, input$x1)
plot_ly(values$dt) %>%
add_lines(x = ~v1, y = ~v2)
})
output$result2 = renderText({
paste('Final value =', values$dt[100,]$v2)
})
}