mib1413456
mib1413456

Reputation: 337

R "real time" plot not showing up in RShiny

I am trying to get my RShiny application to show a somewhat real time barplot. Basically the logic goes like this: RShiny will establish a connection to a file and continuously read from it until it reaches end of file. The file will be updated too. My code for server.R is below:

library(stringr)

shinyServer
(
 function(input, output, session)
 { 

output$plot1.3 = renderPlot({
  con  = file("C:/file.csv", open = "r")
  a = c()
  while (length((oneLine = readLines(con, n = 1, warn = F))) > 0) 
  {
    #constructing vector
    a = c(a, str_extract(oneLine, "\\[[A-Z]+\\]"))
    #making vector into a table
    b = table(a)
    #plotting the table
    barplot(b, xlim = c(0,10), ylim = c(0,1000), las = 2, col = rainbow(5))
    #Sleeping for 1 second to achieve a "animation" feel
    Sys.sleep(1)
  } 
  close(con)
})

}

)

I know what I am trying to do here is inefficient, because I am continously reconstructing a vector and making a table from it and replotting for every iteration, but this code works perfectly on RStudio, but the plot only appears on my RShiny application when the last iteration is done (when EOF is reached). What is happening?

Upvotes: 1

Views: 597

Answers (1)

Bob
Bob

Reputation: 1459

What's happening is that the browser doesn't have anything to display until the call to renderPlot() returns, which it only does at the end of all of the while loop.

@Shiva suggested making your data reactive (and providing the whole code). I agree completely, but there's more.

Your best bet is to use a pair of tools, shiny reactiveTimer and ggvis rendering.

First you'll define your data something like this:

# any reactive context that calls this function will refresh once a second
makeFrame <- reactiveTimer(1000, session) 

# now define your data
b <- reactive({
     # refresh once a second
     makeFrame()
     # here put whatever code is used to create current data
     data.frame([you'll need to have your data in data.frame form rather than table form])
})

If you use ggvis to render the plot, the ggvis internals know how to connect to the shiny reactive context so that... oh don't worry about it, the point is if you feed b (the function b, not b() the return value of the function) into ggvis, it will smoothly animate each update.

The code will look something like this:

 b %>% # passing the reactive function, not its output!
      ggvis([a bunch of code to define your plot]) %>%
      layer_bars([more code to define your plot]) %>%
      bind_shiny("nameofplotmatchingsomethinginoutput.ui")

And then it will all look nice and pretty. If you want, you should also have an easy time finding example code to let the user start and stop the animation or set the frame rate.

If you post a minimally reproducible example, I'll try to stop back and edit the code to function.

Upvotes: 3

Related Questions