How to associate reactively a select() and filter() in a Shiny app?

Hello,

I'm trying to combine a dplyr::select() and a dplyr::filter() to allow reactive columns selection and obs filtering with shiny.
When I tryed separately an app that select columns only (below: App 1 : select()), it works good. Same thing for the app that filter only (below: App 2 : filter()).

But, when combining the two (below: App 3 : select() %>% filter()), I got the error: get(input$x)` must evaluate to column positions or names, not a function.

Note that I would like to filter the columns that have been selected before.

Ps : data are from the "movies" file (http://s3.amazonaws.com/assets.datacamp.com/production/course_4850/datasets/movies.Rdata)

Does somebody encountred this before?
Any idea about how to handle this?

Many thanks :slight_smile:
Yacine

App 1 : select()


if (interactive()){
  
  # Load data 
  load(url("http://s3.amazonaws.com/assets.datacamp.com/production/course_4850/datasets/movies.Rdata"))
  
  library(tidyverse)
  library(shiny)
  library(shinydashboard)
  library(DT)
  
  ui3 <- shinyUI(
    dashboardPage(
      dashboardHeader(title = "Data Viewer"), 
      dashboardSidebar(
        # select()
        selectInput(inputId = "x", 
                    label = "Choisir ici vos colonnes : ", 
                    choices = c("title", "studio","best_pic_nom",
                                "top200_box", "title_type", 
                                "critics_rating", "director", 
                                "genre", "best_actor_win", "audience_rating", 
                                "best_actress_win","best_dir_win", "imdb_num_votes",
                                "thtr_rel_date", "dvd_rel_year", 
                                "thtr_rel_year","dvd_rel_month", "critics_score", 
                                "runtime", "thtr_rel_month", "dvd_rel_day", 
                                "mpaa_rating", "thtr_rel_day", "imdb_rating", "audience_score"),
                    selected = "title", 
                    multiple = TRUE)
      ), 
      dashboardBody(
        fluidPage(
          box(DT::dataTableOutput(outputId = "T"), 
              title = "Les colonnes sélectionnées")
        )
      )
    )
  )
  
  server3 <- shinyServer(function(input, output, session) {
    output$T <- DT::renderDataTable({
      selTable <- movies %>% 
        select(input$x)
      
      DT::datatable(data = selTable, 
                    options = list(pageLength = 5, 
                                   row.names = TRUE))
    })
  })
  shinyApp(ui = ui3, server=server3)
}

App 2 : filter()

if (interactive()){
  
  # Load data 
  load(url("http://s3.amazonaws.com/assets.datacamp.com/production/course_4850/datasets/movies.Rdata"))
  
  library(tidyverse)
  library(shiny)
  library(shinydashboard)
  library(DT)
  
  ui2 <- shinyUI(
    dashboardPage(
      dashboardHeader(title = "Data Viewer"), 
      dashboardSidebar(
        
        # Critère du filtre 
        selectInput(inputId = "y", 
                    label = "Choisir ici le critère du filtre : ", 
                    choices = c("runtime", "thtr_rel_day", "dvd_rel_year","critics_score", "audience_score"),
                    selected = "runtime"), 
        
        # Slider 
        numericInput(inputId = "numValue", 
                     label = "Choisir une valeur numérique pour le filtre", 
                     value ="500", 
                     min = 1, 
                     max = 1000,
                     step = 50, 
                     width = '100%')
      ), 
      dashboardBody(
        fluidPage(
          box(DT::dataTableOutput(outputId = "T"), title = "Les données filtrées")
        )
      )
    )
  )
  
  server2 <- shinyServer(function(input, output){
    output$T <- DT::renderDataTable({
      
      filteredTable <- movies %>%
        dplyr::filter(get(input$y) < input$numValue)
  
      DT::datatable(data = filteredTable, 
                    options = list(pageLength = 5, 
                                   rownames = TRUE))
    })
  })
  shinyApp(ui = ui2, server = server2)
}

App 3 : select() %>% filter()

if (interactive()){
  
  # Load data 
  load(url("http://s3.amazonaws.com/assets.datacamp.com/production/course_4850/datasets/movies.Rdata"))
  
  library(tidyverse)
  library(shiny)
  library(shinydashboard)
  library(DT)
  
  ui <- shinyUI(
    dashboardPage(
      dashboardHeader(title = "Data Viewer"), 
      dashboardSidebar(

        # select()
        selectInput(inputId = "x", 
                    label = "Choisir ici vos colonnes : ", 
                    choices = c("title", "studio","best_pic_nom",
                                "top200_box", "title_type", 
                                "critics_rating", "director", 
                                "genre", "best_actor_win", "audience_rating", 
                                "best_actress_win","best_dir_win", "imdb_num_votes",
                                "thtr_rel_date", "dvd_rel_year", 
                                "thtr_rel_year","dvd_rel_month", "critics_score", 
                                "runtime", "thtr_rel_month", "dvd_rel_day", 
                                "mpaa_rating", "thtr_rel_day", "imdb_rating", "audience_score"),
                    selected = "title", 
                    multiple = TRUE), 

        # Critère du filtre 
        selectInput(inputId = "y", 
                    label = "Choisir ici le critère du filtre : ", 
                    choices = c("runtime", "thtr_rel_day", "dvd_rel_year","critics_score", "audience_score"),
                    selected = "runtime"), 

        # Slider 
        numericInput(inputId = "numValue", 
                     label = "Choisir une valeur numérique pour le filtre", 
                     value ="500", 
                     min = 1, 
                     max = 1000,
                     step = 50, 
                     width = '100%')
      ), 
      dashboardBody(
        fluidPage(
          box(DT::dataTableOutput(outputId = "T"), 
              title = "Les données filtrées")
        )
      )
    )
  )
  server <- shinyServer(function(input, output){
    output$T <- DT::renderDataTable({
      
      filteredTable <- movies %>%
        # Select 
        dplyr::select(get(input$x)) %>%
        # Filter
        dplyr::filter(get(input$y) < input$numValue)
      
      DT::datatable(data = filteredTable, 
                    options = list(pageLength = 5, 
                                   rownames = TRUE))
    })
  })
  shinyApp(ui, server)
}

Hi, I think it is looking for a column named get(input$y), as opposed to that function's output. If that's the case, then try bang-bang to force the get() function evaluation: !!get(input$y). The same it's true for the rest of the input$... calls within dplyr commands

1 Like

Hi @edgararuiz,
Thanks for your return.
I tried bang bang to force it, but it doesn't work yet.
It returns the error: object 'runtime' not found

Any other idea. Thanks :+1:

And object 'runtime' is a numeric variable from the used file ...

Ok, can you share that part of the new version of the code please?

When tried in a separate app (that filters only). It returns: error:object 'runtime' not found

# server 
  server <- shinyServer(function(input, output){
    output$filteredtable <- DT::renderDataTable({
      newtab <- movies %>%
        dplyr::filter(!!get(input$y) < !!get(input$numValue))
      
      DT::datatable(data = newtab)
    })
  })

When tried in the whole app (select + filter). It gives the error: get(input$x) must evaluate to column positions or names, not a function

# Server 
  server <- shinyServer(function(input, output){
    output$T <- DT::renderDataTable({
      
      
      filteredTable <- movies %>%
        # Select 
        dplyr::select(get(input$x)) %>%
        # Filter
        dplyr::filter(!!get(input$y) < !!get(input$numValue))
     
      
      DT::datatable(data = filteredTable, 
                    options = list(pageLength = 5, 
                                   rownames = TRUE))
    })
  })

You drop the variable that you filter by during the select step! select(get(input$x)) drops all other variables except the value of x -- so runtime (or whatever y is) is dropped!

Try this:

server <- shinyServer(function(input, output){
        output$T <- DT::renderDataTable({
            
            filteredTable <- movies %>%
                # Select 
                dplyr::select(one_of(input$x, input$y)) %>%
                # Filter
                dplyr::filter(get(input$y) < input$numValue)
            
            DT::datatable(data = filteredTable, 
                          options = list(pageLength = 5, 
                                         rownames = TRUE))
        })
    })
1 Like

Ok I see. Thanks! I guess I need tell R to take y in the x multiple selection result