【问题标题】:Self-referencing reactive variables in Shiny (R)Shiny (R) 中的自引用反应变量
【发布时间】:2016-05-10 02:55:43
【问题描述】:

我正在构建一个闪亮的应用程序,它会定期读取新数据,然后使用该数据和以前的参数估计值来生成新的参数估计值(等等无限循环)。

问题是参数必须在数据更新时通过响应式更新,而且还需要引用它的先前值,我不确定如何使用它的当前值来计算它的下一个值,而不会抱怨无限递归。下面是一个最小的示例,它旨在打印一个每秒增加 1 的值。

library(shiny)

omega <- 0

# Define the UI
myui <- basicPage(  
    textOutput('var')
)

# Define the server code
myserver <- function(input, output, session) {

    omega <<- reactive({
        invalidateLater(1000, NULL)
        return(omega() + 1)
    })

    output$var <- renderText(omega())
}


# Return a Shiny app object
shinyApp(ui = myui, server = myserver)

这会产生以下错误

evaluation nested too deeply: infinite recursion / options(expressions=)?

如果我尝试通过使用 isolate() 来保护对 omega() 的调用,我会从 C 堆栈溢出中得到一个段错误。

有没有办法解决这个问题?或者也许是在闪亮中做我想做的更好的方法?

【问题讨论】:

  • segfault 通常发生在您尝试访问不适合您的内存时。你的omega() 结构很差

标签: r recursion shiny reactive-programming


【解决方案1】:

这是问题的快速解决方案,但不能完全解决问题。

library(shiny)

omega_nr <- 0

# Define the UI
myui <- basicPage(  
  textOutput('var')
)

# Define the server code
myserver <- function(input, output, session) {

  omega <- reactive({
    invalidateLater(1000, session)
    return(omega_nr)
  })

  # update non reactive value
  observe({
    omega()
    omega_nr<<-omega_nr+1
  })

  output$var <- renderText(omega())
}


# Return a Shiny app object
shinyApp(ui = myui, server = myserver)

这是有效的,我刚刚测试过。

我会尝试其他选项并通知您。同时我也对精确的解决方案感兴趣。但不知何故,我觉得不应该实现自引用反应式。但我可能错了..

【讨论】:

  • 所以每次omega失效时,都会执行observe块,这意味着新的值会递增。这很清楚谢谢。如果我可以提出改进建议:如果将 isolate() 放在 omega_nr&lt;&lt;-omega_nr+1 周围,则计数器从零开始(即在第一次失效发生之前不会调用观察)。
  • 我猜omega_nr&lt;&lt;-omega_nr+1 周围的隔离不会有任何区别,因为 omega_nr 是非反应性的。我也有点想通为什么递归是不可能的[至少直截了当]。我会写下我的下一个评论/答案。
  • 你不能对涉及invalidateLater的函数[reactive]进行直接递归,因为它将被深度嵌套并且rsession将终止或者它不会运行。
【解决方案2】:

你可以构建一个函数来做到这一点:

library(shiny)

myui <- basicPage(  textOutput('var'))
myserver <- shinyServer(function(input, output, session){

  omega <<- 0
  update_data <- function(){omega <<- omega + 1}

  output$var <- renderText({
    invalidateLater(1000, session)
    update_data()})
})

shinyApp(ui = myui, server = myserver)

【讨论】:

  • 这行得通,谢谢。但是对于我来说,原始问题有必要将invalidateLater() 表达式保留在将更新数据的函数中,因为这将具有几个反应性依赖关系。因此,Indranil 的解决方案对我来说效果更好。
猜你喜欢
  • 2022-01-02
  • 2013-06-29
  • 2015-06-25
  • 1970-01-01
  • 1970-01-01
  • 2021-01-07
  • 1970-01-01
  • 1970-01-01
  • 2019-03-27
相关资源
最近更新 更多