17

I am implementing a solution to the Traveling Salesman Problem (TSP) in R (simulated Annealing) and I want to output the current best path periodically. I have searched quite a bit for how to output plots during a for loop and have thus far failed.

I use RStudio, and want to see the graphs as they are generated. If you have ever watched TSP solvers do their thing, you will understand how cool it is to watch. Here is a sample of the graphics output I want to see http://www.staff.science.uu.nl/~beuke106/anneal/anneal.html

I don't think that the memory usage will be a problem (during about 500,000 iterations, I am only expecting 50-100 plots). Here is a sample function, where we would expect to see 10 different plots during the time the function runs:

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()

When I run this, all I see is the final plot produced (in RStudio). How can I see the plots as they're generated?

Also: I am on Ubuntu (whatever the newest stable release is). Don't know if that is relevant.

Thank you everyone in advance.

EDIT: Per Captain Murphy's suggestion, I tried running this in the Linux terminal, and the graphics appeared. I still think the question of "How to do this in RStudio?" Is still relevant, however. It's such a good program, so maybe someone has an idea of what could be done to get this to work?

EDIT2: As Thilo stated, this is a known bug in Rstudio. If anyone has any other ideas to solve this without the software itself being fixed, then there is still something to discuss. Otherwise, consider this question solved.

Josh O'Brien
  • 159,210
  • 26
  • 366
  • 455
Rguy
  • 1,622
  • 1
  • 15
  • 20
  • 1
    Try your code in the standard R console (not R studio). The iterative plots seems to appear for me, not just one at the end. – Captain Murphy Jan 07 '12 at 20:08
  • 1
    I don't know if you have seen that, but there are back and forth arrows in the plot panel in RStudio which are actually a great way for you to loop through the generated plots (I didn't notice them for a while). Of course you don't see the plots as they are generated, but after that you can loop through those plots as often as you want. – Christoph_J Jan 07 '12 at 20:20
  • 4
    I do not have a full answer for you, but maybe some information: It seems this is (was?) a bug in RStudio in 2011. See http://support.rstudio.org/help/discussions/suggestions/214-plots-should-update-in-real-time-osx – Thilo Jan 07 '12 at 20:36
  • If you happen to try and use ggplot2 in a for loop in RStudio you can put a print statement around the plotting function to display the plot. – fabianegli Oct 28 '19 at 11:52

7 Answers7

18

Calling Sys.sleep(0) should cause the plot to draw. Unlike the X11 solution, this will work on server versions of RStudio as well.

(I was surprised that dev.flush() did not give the result you were hoping for, that might be a bug.)

dpel
  • 1,954
  • 1
  • 21
  • 31
Joe Cheng
  • 8,001
  • 42
  • 37
  • 1
    This is a good solution as well. The difference between this one and @Sacha 's is that if we are generating many plots in a short period, this one (at least on my system) will not always show all of the plots if they are being generated too quickly. This is not necessarily a bad thing, depending on if you want to see all of the plots or if your goal is just to have a general idea of what the current state of the TSP system is. For my purposes, the x11() solution works better, but this one is a great one as well. – Rguy Jan 11 '12 at 20:56
9

Following up on @JoeCheng's answer and @RGuy's comment on that answer: as I worked out with the RStudio folks, the problem seems to primarily arise when there is too much plotting going on in too short a timespan. The solution is twofold:

  • Sys.sleep(0) helps force an update to the plotting window.
  • Plotting updates every Wth loop rather than every loop.

For instance, on my computer (i7, RStudio Server), the following code does not update until the loop completes:

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)
}

The following code updates in real-time, despite having the same number of points to be plotted:

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)
  }
}

In other words, it's the number of calls the plot that seems to matter, not the amount of data to be plotted.

Ari B. Friedman
  • 71,271
  • 35
  • 175
  • 235
  • 1
    My problem is what about when I want to plot in a TCL TK window ? I can't find the way to update my window. When I do `Sys.sleep(0)`, it is updating but I can't see changes until I move (literally) the window by holding and moving the title bar. – David Aug 20 '13 at 10:05
8

One thing you can do is open a x11 window and plot in there:

x11()
Plotz()

That should work the same as running it in terminal.

Sacha Epskamp
  • 46,463
  • 20
  • 113
  • 131
2

If you want to save the plots as well you could just open a new device in the loop and close it afterwards.

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))
}
Markus Graf
  • 533
  • 3
  • 16
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()
1

You can also use the back arrows on the plots tab of the lower left pane of the RStudio interface in order to view the plots.

0

You can use the animate package to layer your plots into a GIF.

Peter Prevos
  • 413
  • 4
  • 12