0

I have a .csv that auto-updates every minute with new data. I'd like to have R Shiny reupdate every hour with this new dataset.

From everything I've seen, this will involve invalidateLater or autoInvalidate; however, I'm not sure how to get these working (or more importantly, where to put them).

ui.R is pretty straightforward so I won't include it. server.R is below:

library(ggplot2)
library(reshape2)
library(scales)

# data <- reactive({ # data refresh once a day # 86400000ms is 1 day  
#   invalidateLater(10000, session) # 10s to test
# })

shinyServer(function(input, output, session) {

  autoInvalidate <- reactiveTimer(10000, session)

  observe({
    x <- read.csv("wait_times.csv", header=T, stringsAsFactors=FALSE)
    x <- rename(x, c("Fall.River" = "Fall River", "Martha.s.Vineyard" = "Martha's Vineyard", "New.Bedford" = "New Bedford", "North.Adams" = "North Adams", "South.Yarmouth" = "South Yarmouth"))
    cities <- colnames(x)[-1]

    x[x == 999] <- NA

    x_long <- melt(x, id.var="timestamp") ### does not work after Attleboro ###
    x_long <- rename(x_long, c("variable" = "city", "value" = "wait_time"))
    x_long$timestamp <- strptime(x_long$timestamp, "%d/%m/%Y %H:%M %p")

    weeks <- as.double(difftime(x_long$timestamp[1], x_long$timestamp[length(x_long$timestamp)], units = "weeks")) + 1

    print("REFRESHING CSV!")
    autoInvalidate()
  })

  # pass server-side code into initial UI page
  output$cities <- renderUI({
    checkboxGroupInput("cities", 
                       label = h3("Which cities to view?"),
                       as.list(cities),
                       selected = "Boston")
  })

  output$weeks <- renderUI({
    sliderInput("weeks", 
                label = h3("How many prior weeks to average?"),
                min = 1,
                max = weeks,
                step = 1,
                value = 1)
  })

  output$main <- renderPlot({

    x_output <- x_long[x_long$city == input$cities, ]
    p <- ggplot(x_output, aes(x=timestamp, y=wait_time, group=city)) + geom_line(aes(color=city), size=1.5) + scale_x_datetime(breaks = date_breaks("10 min")) + theme(axis.text.x = element_text(angle = 90, hjust=1), legend.position = "bottom") + labs(x=NULL, y="Waiting time (minutes)")
    print(p)

  })

})

When I pull out certain values from the .csv (like "weeks" and "cities"), R Shiny says they don't exist:

Error in as.list(cities) : object 'cities' not found
Error in sliderInput("weeks", label = h3("How many prior weeks to average?"),  : 
  object 'weeks' not found
Error in func() : object 'x_long' not found

What I think is happening is that since these are being declared inside the observe function, they are encapsulated by it. Perhaps I should be invalidating/declaring these earlier? I've tried putting them before declaring shinyServer() but that hasnt' seemed to work either.

I've researched these sources but haven't been able to replicate:

Community
  • 1
  • 1
Alex Petralia
  • 1,730
  • 1
  • 22
  • 39

1 Answers1

3

observe doesn't return a value (it returns an observer reference class). You want to use reactive instead.

If you wanted only the variable cities for exemple, you could do it like this:

refrehed_cities <- reactive({
    autoInvalidate()

    x <- read.csv("wait_times.csv", header=T, stringsAsFactors=FALSE)
    x <- rename(x, c("Fall.River" = "Fall River", "Martha.s.Vineyard" = "Martha's Vineyard", "New.Bedford" = "New Bedford", "North.Adams" = "North Adams", "South.Yarmouth" = "South Yarmouth"))
    cities <- colnames(x)[-1]
    return cities
)}

and then use it in checkboxGroupInput:

output$cities <- renderUI({
     checkboxGroupInput("cities", 
                       label = h3("Which cities to view?"),
                       as.list(refreshed_cities()),
                       selected = "Boston")
    })
})

An other way to do it would be to use the function reactiveValues, which enables you to store reactive values.

sechstein
  • 305
  • 2
  • 9
  • Can these go before shinyServer() (to prevent more processing) or do they have to go within it? – Alex Petralia Jul 15 '15 at 00:09
  • Any reactive element has to be in the shinyServer() element, precisely to take the reactivity into account. If the csv file had to be loaded only once, then yes it should go before. – sechstein Jul 15 '15 at 09:01