我希望我能简洁地解释这一点。我有一个R函数,它运行一个生态模拟,并返回一个输出列表(时间步长,种群大小,死亡率历史,后代数量,诸如此类的东西)。我想放慢某些情况下的图形输出速度这样学生们就能看到人口动态的发生。应该显示绘图轴和标题,然后在0.5秒内出现代表累积后代的第一行,然后在0.5秒后出现累积后代的第二行,然后在0.5秒后出现第三行,直到在"模拟"结束时绘制出整个新后代队列。"
问题是,应用程序要等到整个图像被渲染后才显示它,所以我不能显示学生"减慢"的人口动态。在所有这些0.5 s延迟完成之前,输出图是空白的,然后它会一次呈现所有这些延迟。即使是for()循环之前的图形调用也会被抑制,直到循环结束。下面的代码示例是不完整的,正在进行的版本。
下面是我的服务器代码——如果在renderPlot命令中取消dev.new()调用的注释,应用程序就会完全按照预期工作,除了输出是在一个新的图形设备中,而不是在Shiny的应用程序绘图窗口中:
shinyServer(function(input, output) {
observe({
if(input$runSim == 0) return()
isolate({
sim <- reactive({
switch(input$sim,
dorriefish = {
df.sim(input$S.df, input$p.df, show=FALSE)
} # end case dorriefish
) # end switch(input$sim)
}) # end reactive()
output$modl.plot <- renderPlot({
switch(input$sim,
dorriefish = {
if (input$reps.df == 1)
{
# dev.new()
opar <- par(no.readonly=TRUE)
len <- length(sim()$offspring.t)
par(fig=c(0,1,0.1,0.9), xpd=NA)
plot(sim()$offspring.t, type="n", xlab="Time steps", ylab="Cumulative Doriefish offspring",
xlim=c(1, max(len, length(sim()$mass))))
mtext("Dorriefish living per time step (green = alive, red = dead):", side=3, at=(max(len)/2)+0.5,
line=4.2)
for(i in 1:nrow(sim()$mhistory))
{
z <- rep("green", length(sim()$mass))
z[sim()$mhistory[i,]] <- "red"
points(seq(1,len, length=length(sim()$mass)), rep(max(1.18*sim()$offspring.t), length(sim()$mass)),
pch=21, col="black", bg=z, cex=2.5)
lines(sim()$offspring.t[1:i], type="h")
Sys.sleep(0.5)
}
txt <- paste("Total offspring:", sim()$offspring,
" Time to cohort extinction:", length(sim()$offspring.t), "time steps.")
mtext(txt, side=1, at=0, line=5, adj=0)
par(opar)
} # end if(input$reps.df == 1)
} # end case dorriefish
) # end switch(input$sim)
}) # end renderPlot()
}) # end isolate()
}) # end observe()
}) # end shinyServer()
下面是UI代码:
library(shiny)
shinyUI(
fluidPage(
titlePanel("BIOL 330 ecological simulations"),
sidebarLayout(
sidebarPanel("",
helpText(HTML("<h3 style='text-align:center;'>Control Panel</h3>"), align='center'),
tags$hr(style='height:2px; border-width:0; color:gray; background-color:gray'),
# choose a simulation from a drop down menu
selectInput("sim", HTML("<b>Select a simulation to explore:</b>"),
# list the simulations available
c("No simulation selected (Introduction)" = "none",
"Dorriefish growth/reproduction trade-offs" = "dorriefish",
"Optimal foraging" = "optfor")
),
tags$hr(style='height:2px; border-width:0; color:gray; background-color:gray'),
conditionalPanel(condition="input.sim=='dorriefish'",
helpText(HTML("<b>Simulation model parameters:</b>")),
sliderInput("S.df", label=div(HTML("Specify <em>S</em>, the switch point mass (g) for
transition from somatic growth to reproduction:")),
min = 1, max = 50, value = 10, step=5),
sliderInput("p.df", label=div(HTML("Specify <em>p</em>, the probability of mortality
by predation in any given time step:")),
min = 0, max = 1, value = 0.12, step=0.01),
sliderInput("reps.df", label=div(HTML("Specify the number of full simulations to
run:")), min = 1, max = 100, value = 1, step=1)
),
# bottom controls common to all panels
conditionalPanel(condition="input.sim!='none'",
tags$hr(style='height:2px; border-width:0; color:gray; background-color:gray'),
fluidRow(column(4, actionButton("runSim", "Run simulation")),
column(4, actionButton("saveSim", "Save output file")),
column(4, actionButton("printSim", "Save/print plot"))),
tags$hr(style='height:2px; border-width:0; color:gray; background-color:gray')
)
),
mainPanel("",
# no model selected-- show information page
conditionalPanel(condition="input.sim=='none'",
includeHTML("www/simNoneText.html")
),
tabsetPanel(id="outTabs", type="tabs",
tabPanel("Plot", plotOutput("modl.plot")
),
tabPanel("Summary"
),
tabPanel("R Code"
)
)
)
)
)
)
所以重复我的问题,我如何让服务器在每个时间步中显示后代的累积数量,暂停0.5秒,然后显示下一个,直到显示所有模拟时间步?
谢谢,并致以最良好的问候。——迈克c .
我试着阅读你的代码,这是我看到的:
我建议你用uiOutput()
函数来显示输出,这样ui.R
会更清晰,而把计算放在server.R
要模拟人口增长(或其他任何事情)时的步骤,您可以在服务器中一次计算所有步骤。R,然后在for()
循环中只显示一些数据,就像server.R
output$plot <- renderUI({
### here calculate the results all at once and save it to a variable
result <- calculations
for(i in 1:dim(result)[1]){
Sys.sleep(0.5) # time to wait to perform each plot
### here you put the code to only get some results of
### the calculation you've perfomed earlier
ggplot(results[i,...], ...)
}
})