2014-01-22 19 views
8

我已經在R中編寫了一個模擬,我想用閃亮的形象進行可視化。爲了進行評估,我已將模擬的主要部分放入塊中,觀察塊。在評估過程中,即每次迭代我想繪製當前狀態。問題是如何實現這一點,因爲在我的實際代碼中,繪圖的繪製只是在主觀察者被評估之後執行。例如,是否有辦法暫停觀察塊的執行,並在繪圖更新後繼續執行?在閃亮的應用程序中的觀察者循環內的更新圖

不應該有更多的光澤功能來解決這種情況,因爲我可以想象我不是唯一一個想要做這樣的事情?!

這將是很好,如果你可以幫我這個:)

下面是服務器和用戶界面的一些骨架代碼。

ui.R:

library(shiny) 

shinyUI(pageWithSidebar(

    headerPanel("... Simulation"), 

    sidebarPanel(
    sliderInput("epochs", 
       "Number of Epochs:", 
       min = 1, 
       max = 100, 
       value = 10), 
    verbatimTextOutput("curr.iter"), 
    actionButton("actionB", "Action!") 
), 

    mainPanel(
    plotOutput("distPlot") 
) 
)) 

server.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") }) 

}) 

回答

0

既然你已經在你的代碼Sys.sleep()電話,我假設你只希望通過每秒一次迭代運行。如果是這樣的話,你可以設置一個reactiveTimer每秒鐘評估一次代碼。在該計時器中,您將運行當前迭代的代碼,然後修改dummy$iter變量。

+0

感謝您的回答。我已經看到了反應計時器的可能性,但我只是把系統。sleep()命令,以便爲繪圖出​​現預留一些時間(例如,在RStudio中,我必須以相同的方式執行,否則繪圖不會顯示)。在我的模擬中,計算任務會產生必要的延遲。我只是想知道是否存在觸發繪圖渲染的可能性(無論何時都需要),因此可以保留模擬引擎的狀態,而不必重新構建模擬循環。 – user3220352

+0

您可以隨時渲染繪圖。問題是R是單線程的。所以如果它忙於處理你的模擬,那麼它不會評估其他被動依賴。這並不是Shiny的一個深思熟慮的部分,但現在我認爲你需要安排「大型」處理(模擬)以小塊(1或幾個迭代)計劃每隔幾毫秒發生一次 - 這個想法是,CPU不是通過運行模擬100%佔用的,給它時間來評估其他反應性上下文(比如你的圖)。 –

+0

我建議用反應計時器每秒調度一次。看到你可以得到體系結構的工作,然後從那裏修改或者使定時器下降到一個更小的間隔,或者每次定時器觸發時做多次迭代。 –

7

我一直在想這個問題。我認爲正確的解決方案是使用invalidateLater將工作安排在小塊中進行,但允許其他被動依賴項中斷我們的長期運行過程,以執行更新圖形等操作。

我整理了一個快速示例https://gist.github.com/trestletech/8608815。你可以用

runGist(8608815) 

運行這個基本的前提是,我們正在做一些長時間運行的迭代計算像什麼在你的模擬完成,但我們做的更小的塊,以允許其他reactives之間運行英寸我的代碼執行起來非常簡單,所以我可以在大約1秒內處理100,000次迭代,這是我願意等待我的應用程序交互更新的時間。我想做500萬次迭代,所以我安排了50個塊。

每次我跑10萬次迭代一大塊,我更新一對夫婦因爲它產生的最終的renderText(獲得發送到我的UI一些其他更新的反應值雖然renderPlot像你將工作完全一樣)。如果您運行該應用程序,您會看到在下一個塊預定運行之前,在我運行的每個塊之間更新這些反應。

這種方法有一點開銷,所以你的計算可能會稍微減慢一點。但在我的機器上,在控制檯上同時運行500萬次迭代需要21秒,並且在這個延遲調度模型中花費了23秒。當然,你可以通過做更大的塊來進一步推動它。

讓我知道你在想什麼。我想這可能是有道理的,包括它的部分在Shiny或作爲擴展包。

+0

對不起,我有很多其他的事情要做...很好的工作,我目前正在檢查你的代碼:) – user3220352

+0

這解決了我的問題 - 希望這些類型的更高級反應性流程已在教程中討論 – ThomasP85

+0

很高興幫助。巧合的是,我們幾分鐘前推出了http://shiny.rstudio.com/。你可能會在那裏找到更多的幫助,雖然我不相信我們還有關於這個確切主題的文章。 –

相關問題