Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/74.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
R 更新应用程序中观察者循环内的绘图_R_Shiny - Fatal编程技术网

R 更新应用程序中观察者循环内的绘图

R 更新应用程序中观察者循环内的绘图,r,shiny,R,Shiny,我已经用R写了一个模拟,我想现在就用它来可视化。我已将模拟的主要部分放入观察块中,以便进行评估。在这个评估过程中,也就是说,对于每次迭代,我都要绘制当前状态。问题是我如何做到这一点,因为在我的实际代码中,绘图的渲染是在对主观察者进行评估之后执行的。例如,是否有一种方法可以暂停观察块的执行,并在更新绘图后恢复观察块的执行 既然我可以想象,我不是唯一一个想做这种事情的人,那么shiny不应该有更多的功能来解决这种情况吗 如果你能帮我做这件事就太好了:) 下面是服务器和ui的一些框架代码 ui.R:

我已经用R写了一个模拟,我想现在就用它来可视化。我已将模拟的主要部分放入观察块中,以便进行评估。在这个评估过程中,也就是说,对于每次迭代,我都要绘制当前状态。问题是我如何做到这一点,因为在我的实际代码中,绘图的渲染是在对主观察者进行评估之后执行的。例如,是否有一种方法可以暂停观察块的执行,并在更新绘图后恢复观察块的执行

既然我可以想象,我不是唯一一个想做这种事情的人,那么shiny不应该有更多的功能来解决这种情况吗

如果你能帮我做这件事就太好了:)

下面是服务器和ui的一些框架代码

ui.R:

服务器.R:

library(shiny)

sinus <- data.frame()

shinyServer(function(input, output) {

  dummy <- reactiveValues(iter=0)

  obsMain <- observe({
    for (i in 1:input$epochs) {
      cat(i, " ")
      x <- seq(1:input$epochs)
      y <- sin(x)
      sinus <<- data.frame(x, y)
      dummy$iter <- i
      #
      # At this time I want distPlot & curr.iter to be evaluated/updated!
      #
      Sys.sleep(1)

    }

  }, suspended=TRUE)


  obsAction <- observe({ if(input$actionB > 0) obsMain$resume() })  # Helps to avoid initial evaluation of obsMain...

  output$curr.iter <- renderText({ as.numeric(dummy$iter) })

  output$distPlot <- renderPlot({ if (dummy$iter > 1) plot(sinus, type="l") })

})
库(闪亮)

由于在代码中有一个
Sys.sleep()
调用,我假设您只希望每秒运行一次迭代。如果是这种情况,您可以设置一个
reactiveTimer
,它将每秒计算一次代码。在该计时器内,您将运行当前迭代的代码,然后启动
dummy$iter
变量

我一直在思考这个问题。我认为正确的解决方案是使用
invalidaterater
将工作安排成小块进行,但允许其他反应性依赖项中断我们的长期运行过程,以执行更新图形之类的操作

我列举了一个简单的例子。您可以使用

runGist(8608815)
基本前提是,我们正在进行一些长期运行的迭代计算,就像在模拟中所做的一样,但我们在较小的块中进行,以允许其他反应器在其间运行。我的代码执行起来非常简单,因此我可以在~1秒钟内处理100000次循环迭代,这大约是我愿意等待我的应用程序以交互方式更新的时间。我想进行500万次迭代,所以我安排了50个块

每次我运行100000次迭代,我都会更新一些反应性的值,这些值会产生一些其他更新,这些更新最终被发送到
renderText
中的我的UI中(尽管像你这样的
renderPlot
也会工作完全相同)。如果你运行这个应用程序,你会看到在我运行的每个区块之间,这些反应都会在计划运行下一个区块之前更新

这种方法有一点开销,因此您的计算可能会稍微慢一点。但是在我的机器上,当在控制台上同时运行时,500万次迭代需要21秒,在这个延迟调度模型中需要23秒。当然,你可以通过做更大的块来进一步降低这一点


让我知道你的想法。我想把它包装起来,或者把它的一部分放在Shiny中,或者作为一个扩展包。谢谢你的回答。我已经看到了使用reactiveTimer的可能性,但我只是使用Sys.sleep()命令,以便为绘图保留一些时间(例如,在RStudio中,我通常必须以相同的方式进行操作,否则绘图不会显示)。在我的模拟中,计算任务将产生必要的延迟。我只是想知道是否存在触发绘图渲染的可能性(只要我愿意),因此可以让模拟引擎保持原样,而无需重建模拟循环。您可以随时渲染绘图。问题在于R是单线程的。因此,如果它忙于处理您的模拟,那么它就不会评估其他反应性依赖项。这在Shiny中还不是一个经过深思熟虑的部分,但现在我认为您需要将“大”处理(模拟)安排为每几毫秒一次的小段(1次或几次迭代)处理——其思想是CPU不是100%被运行模拟占用,给它时间来评估其他反应性上下文(比如你的情节)。我建议用一个1/s的反应计时器来尝试。请注意,您可以让体系结构正常工作,然后从那里进行修改,要么将计时器的间隔缩短到更小的时间间隔,要么每次计时器启动时进行不止一次的迭代。很抱歉延迟,我还有很多其他事情要做。。。干得好,我现在正在检查你的代码:)这解决了我的问题-希望这些更高级的反应性流在教程中被涵盖。很高兴它有所帮助。巧合的是,我们几分钟前就发射了。你可能会在那里找到更多的帮助,尽管我认为我们还没有关于这个主题的文章。
runGist(8608815)