闪亮的App自引用迭代-解决方案

时间:2019-02-03 14:44:05

标签: r shiny

在闪亮的应用程序中,使用迭代自引用可能很困难。

这使我挠头,但是...

2 个答案:

答案 0 :(得分:0)

如果有其他人尝试在闪亮的应用程序中将值从一个“迭代”传递到下一个“迭代”时遇到问题,我会发布此信息以提供帮助。

就我而言,我需要计算一个移动平均值。

library(shiny)

# UI
{ 
  ui <- fluidPage(
    textOutput('serial')
  )
}

server <- function(input, output, session) {

  serialStream <- reactive({
    invalidateLater(10, session)
    return(sample(1:100,1))
  })

  # Non-solution #1
  # runningMean <- reactive({
  #   isolate(runningMean()*0.4) + serialStream()*0.1
  # })
  # output$serial <- renderText(runningMean())

  # Non-solution #2
  # runningMean <- 0 # initial value
  # observe({
  #   runningMean <<- runningMean*0.4 + serialStream()*0.1
  # })
  # output$serial <- renderText(runningMean)

  # Solution 
  rm <- 0 # initial value
  runningMean <- reactive({
    rm <<- rm * 0.4 + serialStream()*0.1
    rm
  })
  output$serial <- renderText(runningMean())
}

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

使用observe()可以完成类似的事情,但是我遇到了内存泄漏问题。上面的代码对我有用。...请注意在反应函数内部使用<<-代替<-。这样可以确保rm的值保留在该函数之外。

答案 1 :(得分:0)

您提出的解决方案不是正确的方法,我强烈建议您不要这样做。不要使用<<-进行赋值,这几乎从来都不是正确的选择,它可能看起来“正确”,但是具有意想不到的行为,可能导致奇怪的错误。通常,当您要使用<<-时,正确的做法是使用reactiveVal()

考虑以下使用<<-来保存数字的总和的应用程序(我正在使用与您的示例应用程序不同的示例应用程序,以使其更简单易懂):

ui <- fluidPage(
  actionButton("add1", "Add 1"),
  actionButton("add5", "Add 5")
)
server <- function(input, output) {
  mysum <<- 0

  observeEvent(input$add1, {
    mysum <<- mysum + 1
    print(mysum)
  })
  observeEvent(input$add5, {
    mysum <<- mysum + 5
    print(mysum)
  })
}
shinyApp(ui, server)

上面的应用程序在测试时似乎可以正常运行,但是当您将其发布到现实世界中时,您会注意到一个错误:如果打开两个浏览器选项卡,则变量将在两者之间共享。实际上,该号码将在所有用户之间共享。在您的应用中不会发生这种情况,因为您的初始分配使用了<-,而第二次分配使用了<<-,但是上面的模式是我经常看到的,所以我想明确地显示它。另一个错误是,您现在已经离开了反应性世界-mysum不是反应性变量,因此我们不能在任何反应性上下文中使用它(这就是为什么您不采取解决方案的原因) #2无效)。下面是更好的方法:

ui <- fluidPage(
    actionButton("add1", "Add 1"),
    actionButton("add5", "Add 5")
)
server <- function(input, output) {
    mysum <- reactiveVal(0)

    observeEvent(input$add1, {
        mysum(mysum() + 1)
    })
    observeEvent(input$add5, {
        mysum(mysum() + 5)
    })
    observe({
        print(mysum())
    })
}
shinyApp(ui, server) 

您可以阅读this answer进行更深入的讨论