在RStudio中进行循环过程中的绘图

18
我正在使用R语言(模拟退火算法)实现旅行商问题(TSP)的解决方案,并希望定期输出当前的最佳路径。我已经搜索了很多关于如何在for循环中输出图形的资料,但到目前为止都没有成功。
我使用RStudio,并希望在生成图形时看到它们。如果您曾经观察过TSP求解器的工作,您就会明白观察它们的过程是多么酷。这里是一个示例图形输出:http://www.staff.science.uu.nl/~beuke106/anneal/anneal.html 我不认为内存使用量会成为问题(在约500,000次迭代期间,我只期望看到50-100个图形)。以下是一个示例函数,我们期望在函数运行期间看到10个不同的图形:
Plotz <- function(iter = 1000000, interval = 100000) {
  x <- 1:10
  for(i in 1:iter){
    y <- runif(10)
    if(i %% interval == 0) {
      plot(x, y)
    }
  }
  return(c(x, y))
}
Plotz()
当我运行这个代码时,在RStudio中只能看到最后绘制的图形。如何在生成过程中查看所有的图形?
此外,我使用的是Ubuntu操作系统(最新的稳定版本),不知道这是否相关。
提前感谢大家。
编辑:按照Captain Murphy的建议,在Linux终端上运行代码,画面出现了。但是我仍然认为“如何在RStudio中实现这一点?”这个问题很重要。它是一个非常好的程序,也许有人知道如何解决这个问题?
编辑2:正如Thilo所说,这是Rstudio中已知的一个错误。如果有任何其他解决此问题的想法而无需修复软件本身,则仍有值得讨论的内容。否则,将此问题视为已解决。

1
请在标准的R控制台中尝试您的代码(而非R Studio)。迭代图似乎对我来说会一直出现,而不仅仅是在最后出现一个。 - Captain Murphy
1
我不知道你是否注意到了,在RStudio的绘图面板中有前进和后退箭头,这实际上是一个很好的方式,让你可以循环浏览生成的图形(我一开始也没注意到)。当然,你不能在生成时看到这些图形,但之后你可以随意循环浏览这些图形。 - Christoph_J
4
我无法为您提供完整的答案,但或许可以提供一些信息:这似乎是2011年RStudio中的一个错误(bug)。请参阅http://support.rstudio.org/help/discussions/suggestions/214-plots-should-update-in-real-time-osx。 - Thilo
如果你在RStudio中尝试使用ggplot2进行for循环,你可以在绘图函数周围放置一个打印语句来显示绘图。 - fabianegli
7个回答

19

调用Sys.sleep(0)应该会导致绘图。与X11的解决方案不同,这种方法也适用于RStudio服务器版本。

(我惊讶于dev.flush()没有给出您希望得到的结果,这可能是一个错误。)


1
这也是一个很好的解决方案。与 @Sacha 的区别在于,如果我们在短时间内生成许多图形,这个解决方案(至少在我的系统上)不会总是显示所有的图形,如果它们被太快地生成。这并不一定是件坏事,这取决于您是否想看到所有的图形,或者您的目标只是对TSP系统的当前状态有一个大致的了解。对于我的目的,x11() 解决方案效果更好,但这个解决方案也很棒。 - Rguy

9

回答@JoeCheng和评论@RGuy的问题:正如我与RStudio的同事商讨的,主要是由于短时间内绘图次数太多所导致的问题。解决方法有两个:

  • Sys.sleep(0) 可以帮助更新绘图窗口。
  • W个循环而不是每个循环进行绘图更新。

例如,在我的计算机上(i7,RStudio服务器),以下代码在循环完成之前不会更新:

N <- 1000
x <- rep(NA,N)
plot(c(0,1)~c(0,N), col=NA)
for(i in seq(N)) {
  Sys.sleep(.01)
  x[i] <- runif(1)
  iseq <- seq(i-99,i)
  points( x[i]~i )
  Sys.sleep(0)
}

以下代码实时更新,尽管要绘制的点数相同:
N <- 1000
x <- rep(NA,N)
plot(c(0,1)~c(0,N), col=NA)
for(i in seq(N)) {
  Sys.sleep(.01)
  x[i] <- runif(1)
  iseq <- seq(i-99,i)
  if(i%%100==0) {
    points( x[iseq]~iseq )
    Sys.sleep(0)
  }
}

换句话说,似乎关键是 plot 的调用次数,而不是要绘制的数据量。

1
我的问题是,当我想在TCL TK窗口中绘图时怎么办?我找不到更新窗口的方法。当我执行Sys.sleep(0)时,它正在更新,但是我无法看到变化,直到我通过按住并移动标题栏来移动(字面上)窗口。 - David

8

你可以做的一件事是打开一个X11窗口并在其中绘图:

x11()
Plotz()

这应该与在终端中运行它的方式相同。


2

如果您想保存图表,您可以在循环中打开一个新设备,然后在之后关闭它。

Plotz <- function(iter = 1000, interval = 100) {
  x <- 1:10

  p <- 0 #plot number

  for(i in 1:iter){

    y <- runif(10)
    if(i %% interval == 0) {
        png(file=paste(i,"png",sep="."))
        p <- p + 1; plot(x, y)
        dev.off()
    }
  }
return(c(x, y))
}

1

您还可以在RStudio界面左下角的绘图选项卡上使用后退箭头来查看绘图。


1
Plotz <- function(iter = 1000, interval = 100) {
  x <- 1:10
  p <- 0 #plot number
  for(i in 1:iter){
    y <- runif(10)
    if(i %% interval == 0) {
        p <- p + 1; plot(x, y)
        readline("Please press the Enter key to see the next plot if there is one.")
    }
  }
  return(c(x, y))
}
Plotz()

0
你可以使用animate包将你的绘图层叠成一个GIF。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接