How to avoid empty dataframe with updatePickerInput

I'm trying to build an App where filters are updated depending on the input of the other filters. I therefore use the updatePickerInput functions in combination with observe. Since all filters depend on each other and update my input data I face difficulties if all input options are deselected from a given filter. In that case, the dataframe is empty and there is no way of "going" back in order to have data again in the dataframe. Just deselect all options from one of the filters in the given example below and you will know what I mean. My question is: what type of options do I have to avoid that kind of behavior and how could I implement them?


library(shiny)
library(dplyr)
library(plotly)

data("mtcars")

# create ui
ui <- fluidPage(
  fluidRow(
    box(
      title = "Filter",
      pickerInput(inputId = "cyl_pickerinput",
                  label = "CYL",
                  choices = levels(as.factor(mtcars$cyl)),
                  multiple = T,
                  selected = levels(as.factor(mtcars$cyl)),
                  options = list(
                    `actions-box` = TRUE,
                    `selected-text-format`= "count",
                    `count-selected-text` = "{0} out of {1} cyl selected")),
      pickerInput(inputId = "vs_pickerinput",
                  label = "VS",
                  choices = levels(as.factor(mtcars$vs)),
                  multiple = T,
                  selected = levels(as.factor(mtcars$vs)),
                  options = list(
                    `actions-box` = TRUE,
                    `selected-text-format`= "count",
                    `count-selected-text` = "{0} out of {1} vs selected")),
      pickerInput(inputId = "carb_pickerinput",
                  label = "CARB",
                  choices = levels(as.factor(mtcars$carb)),
                  multiple = T,
                  selected = levels(as.factor(mtcars$carb)),
                  options = list(
                    `actions-box` = TRUE,
                    `selected-text-format`= "count",
                    `count-selected-text` = "{0} out of {1} carb selected")),
    ),
    box(
      title = "Plot of mtcars",
      plotlyOutput("carplot")
    )
  ),
)

# create server
server <- function(input, output, session) {
  ## create updaters
  observeEvent(
    # define pickerinputs to be observed
    c(input$vs_pickerinput,
    input$carb_pickerinput,
    input$cyl_pickerinput), 
    { 
      # filter the data based on the pickerinputs
      mtcars2<-mtcars%>%
      filter(vs%in%input$vs_pickerinput)%>%
      filter(carb%in%input$carb_pickerinput)%>%
      filter(cyl%in%input$cyl_pickerinput)
      
      # update the individual picker inputs based on the filtered data
      updatePickerInput(
        session = session,
        inputId = "cyl_pickerinput",
        choices = levels(factor(mtcars$cyl)),
        selected = unique(mtcars2$cyl)
      )
      updatePickerInput(
        session = session,
        inputId = "vs_pickerinput",
        choices = levels(factor(mtcars$vs)),
        selected = unique(mtcars2$vs)
      )
      updatePickerInput(
        session = session,
        inputId = "carb_pickerinput",
        choices = levels(factor(mtcars$carb)),
        selected = unique(mtcars2$carb)
      )
      
    }, ignoreInit = TRUE)
  
  # update mtcars table based on filters
  mtcars.reactive <- 
    reactive({
      mtcars %>%
        filter(cyl %in% input$cyl_pickerinput &
                 vs %in% input$vs_pickerinput &
                 carb %in% input$carb_pickerinput
        )})
  ## create the plot output
  # Start Barplot Emissionen here 
  output$carplot<-
    renderPlotly({
      # create plot
      plot<-ggplot(mtcars.reactive())+
        geom_point(aes(wt, mpg, color=factor(vs)))
      # convert to plotly
      ggplotly(plot)
    })
  
  
  
}

shinyApp(ui, server)

by far the easiest approach is to have a heirarchy where the first picker dictates what the pickers below it can pick but not vice-versa.
Additional flexibility could be provided by allowing reordoring of the heirarchy, but that adds additional complexity.

Thank you very much for your response. I wondered if there was a simple way to include an if else condition that e.g. requires the user to choose at least one input. this is shown here, however only for one filter and not for several independent filters... I'm struggeling to implement such a logic for the example above.

Okay. I got it solved, see here

This topic was automatically closed 7 days after the last reply. New replies are no longer allowed.