selectizeInput with choices from data frame

shiny

#1

Is it possible for the choices in selectizeInput to be rows from a data frame? If so, would the returned data be a list of items from the selected row? I have been unable to make this work. In the code below, cityInput works fine since the choices are a character vector, but locationInput does not work, the item list in the select box is empty.

This is a common occurrence where user input requires selection based on multiple columns to determine a unique row. In the example below, different cities have the same name and state is used to uniquely determine the location. Pasting the two columns together is one solution, but in complex cases this approach gets messy.

library(shiny)

locations <- data.frame(City=c("Ames", "Beaumont", "Beaumont", "Portland", "Portland"),
                        State=c("IA", "CA", "TX", "ME", "OR"))

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      selectizeInput("cityInput", "City", choices=NULL, selected=NULL),
      selectizeInput("locationInput", "Location", choices=NULL, selected=NULL)
    ),
    mainPanel("Main Panel")
  )
)

server <- function(input, output, session) {
  updateSelectizeInput(session, 'cityInput',
              choices = locations$City,
              server = TRUE
  )
  updateSelectizeInput(session, 'locationInput',
              choices = locations,
              server = TRUE
  )
}

shinyApp(ui, server)

#2

yes, you can use a dataframe as input for the input. It needs to have a label and value column in that case.
The input will show the label and the value is returned as output.

library(shiny)

locations <- data.frame(City=c("Ames", "Beaumont", "Beaumont", "Portland", "Portland"),
                        value=c("IA", "CA", "TX", "ME", "OR"),
                        label=c("Iowa", "California", "Texas", "Maine", "Oregon"))

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      selectizeInput("cityInput", "City", choices=NULL, selected=NULL),
      selectizeInput("locationInput", "Location", choices=NULL, selected=NULL),
      textOutput("values")
    ),
    mainPanel("Main Panel")
  )
)

server <- function(input, output, session) {
  updateSelectizeInput(session, 'cityInput',
                       choices = locations$City,
                       server = TRUE
  )
  updateSelectizeInput(session, 'locationInput',
                       choices = locations,
                       server = TRUE
  )
  
  output$values <- renderText({
    paste(input$cityInput, input$locationInput)
  })
}
shinyApp(ui, server)

#3

Thank you! It wasn't exactly what I was looking for but it pointed the way toward a solution. Mapping the City and State columns to a unique identifier (in this case a fictitious zip code) enables me to effectively use your suggestion.

library(shiny)

locations <- data.frame(City=c("Ames", "Beaumont", "Beaumont", "Portland", "Portland"),
                        State=c("IA", "CA", "TX", "ME", "OR"),
                        value=c("10010", "20020", "30030", "40040", "50050"))

locations$label = paste(locations$City, locations$State, sep=", ")

ui <- fluidPage(
  sidebarLayout(
    sidebarPanel(
      selectizeInput("locationInput", "Location", choices=NULL, selected=NULL),
      textOutput("values")
    ),
    mainPanel("Main Panel")
  )
)

server <- function(input, output, session) {
  updateSelectizeInput(session, 'locationInput',
                       choices = locations,
                       server = TRUE
  )

  output$values <- renderText({
    paste("Zip code =", input$locationInput)
  })
}
shinyApp(ui, server)

#4

Nice that you got it working! Can you mark your answer as the solution?