Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

R Shiny Handling - handling error from empty data frames

Tags:

r

ggplot2

shiny

I am writing my first Shiny app and so far am enjoying it. My app works on a data frame that includes many variables measuring aspects of meals. It allows a user to select ranges of half a dozen continuous variables using sliders. These inputs are used to subset the data frame, then a ggplot is created based on the subset of data.

My problem is this -- when the ranges chosen result in no data left in the subsetted data frame, I get this red error message printed in the main panel, where the plot would normally be:

Error: argument is of length zero (from: Error in if (nrow(layer_data) == 0) return() : argument is of length zero).  

I understand why this error happens, and it makes sense if I'm getting static plots during a typical data analysis session. However, I'm trying to figure out the right way to handle this in the shiny web app situation.

Since this message makes no sense to the user, I'd like to:

1) Be able to replace it with a sensible message instead OR
2) Return a blank graph OR
3) Display nothing (i.e. no error message or graph to the user when the data frame is empty)

The problem is that if I check for an empty data frame and return a different (blank) plot or message, then when the user changes the slider settings to something that does have data, the correct plot does not appear (since the reactive object is no longer the same). If I just let the error message appear as it does now and the user changes the settings, the graph updates appropriately.

Can someone recommend a way to handle this gracefully in Shiny?

like image 278
eamcvey Avatar asked Apr 13 '14 02:04

eamcvey


1 Answers

As of shiny 0.10.0 there are two nice functions to help with the situation you describe namely need and validate. The example given requires the user to pick a number of groups and a cohort. If the user hasn't selected the required objects then the need functions display relevant output. It is also possible to assign a bespoke CSS class via the validate function which can then be used for styling:

library(shiny)
library(ggplot2)
myData <- data.frame(group = sample(letters[1:4], 100, TRUE)
                     , cohort = sample(0:4, 100, TRUE)
                     , value = runif(100))
runApp(
  list(ui = fluidPage(
    column(4,
    checkboxGroupInput('group', 'Pick a group', choices = letters[1:4]),
    selectizeInput('cohort', 'Pick a cohort', choices = 0:4)),
    column(8, plotOutput('myplot'))
  )
  , server = function(input, output, session) {
    appData <- reactive({
      myData[myData$group %in% input$group & myData$cohort == input$cohort,]
    })
    output$myplot <- renderPlot({
      validate(
        need(input$group, 'Please select at least one group'),
        need(input$cohort > 0, 'Please choose a cohort greater than zero')
      )
      g <-ggplot(appData(),aes(x=group, y=value)) +
        stat_summary(fun.y=sum, geom="bar") +
        ggtitle(paste('cohort', input$cohort))
      g
    })
  }
  )
)

enter image description here

like image 74
jdharrison Avatar answered Sep 19 '22 19:09

jdharrison