How to make Shiny selectInput dropdown choose between multiple dataframes

Viewed 343

I’m attempting to build my first Shiny app and keep running into trouble so hopefully someone can help. The core of what I want to do is simple (for anyone other than me): create a dropdown where the user can select a dataframe from a list, and that selected DF will then be turned into a data table (from the DT package).

Here’s a simplified version of what I’ve done so far:

I have 2 dataframes in my global.R. In my actual code I do some data wrangling to add columns, etc. to 20ish csv files so I set this up as a global to keep things neat.

df1 <- data.frame(Name = c("a", "b", "c"),
                  Parameter = c("pH", "pH", "pH"),
                  Amount = c(7, 7.5, 6.8),
                  Violation = c("No", "No", "Yes"))

df2 <- data.frame(Name = c("d", "e", "f"),
                  Parameter = c("pH", "pH", "pH"),
                  Amount = c(6.7, 7.2, 7.3),
                  Violation = c("Yes", "No", "No"))

My ui.R:

shinyUI(fluidPage(

    titlePanel("Title"),

    fluidRow(
        selectInput(inputId = "df_test",
                    label = "Select DF",
                    choices = c("DF 1" = "df1", 
                                "DF 2" = "df2"), 
                    selected = "DF 1", 
                    width = "50%"),
    
        
        DT::dataTableOutput("test_table")
    )
))

and my server.R:

shinyServer(function(input, output) {
    
    output$test_table <- DT::renderDataTable({
        input$df_test
    })

})

Right now I’m getting an error that says “’data’ must be 2 dimensional" but I'm pretty sure it won't work even if I resolve that. I don’t know what I’m doing wrong here. Does anyone have advice for how to fix this error and set up the selectInput dropdown to actually select from the list of dataframes? Sorry that this is such a beginner question, but I’m really struggling. Thanks in advance for any help.

2 Answers

We need to return the value of the object from the string i.e. get (using the OP's original syntax)

ui = fluidPage(
  
  titlePanel("Title"),
  
  fluidRow(
    selectInput(inputId = "df_test",
                label = "Select DF",
                choices = c("DF 1" = "df1", 
                            "DF 2" = "df2"), 
                selected = "DF 1", 
                width = "50%"),
    
    
    DT::dataTableOutput("test_table")
  )
)
server <- function(input, output) {
  
  output$test_table <- DT::renderDataTable({
    get(input$df_test)
  })
}
shinyApp(ui, server)

-ouptut

enter image description here

Another option would be to wrap your data frames inside a named list:

df <- list(df1 = df1, df2 = df2)

library(shiny)
library(DT)

ui <- fluidPage(
  titlePanel("Title"),
  fluidRow(
    selectInput(
      inputId = "df_test",
      label = "Select DF",
      choices = c(
        "DF 1" = "df1",
        "DF 2" = "df2"
      ),
      selected = "DF 1",
      width = "50%"
    ),
    DT::dataTableOutput("test_table")
  )
)

server <- function(input, output) {
  output$test_table <- DT::renderDataTable({
    df[[input$df_test]]
  })
}

shinyApp(ui, server)
#> 
#> Listening on http://127.0.0.1:8891

Related