0
votes

Is it possible to fill the choices (values) of ‘selectInput’ by calling a dataframe within a list? This would help in expediting the script as well as omitting lengthy choices.

I have a folder (choices) within my app.R folder. This folder contains 15 .xlsx (Excel) files, each of which contains two columns (x=id,y=value).

llist<-list.files(pattern=“*.xlsx”) df_list<-lapply(list,readxl::read_excel)

This returns a list of data-frames (e.g.):

List of 2 $ 001.txt:'data.frame': 15 obs. of 2 variables: ..$ X: Factor w/ 50 levels ..$ Y: Factor w/ 50 levels $ 002.txt:'data.frame': 5 obs. of 2 variables ..$ X: Factor w/ 5 levels ..$ Y: Factor w/ 5 levels

When I attempt to call the values (second column of relevant dataframe) the app fails saying the choices must have a value.

selectInput (“state”, “States:”,
df_list[2][[2]]),

selectInput (“cnfd”, “Confidence”,
df_list[7][[2]])

...

str ( df_list[2])

df x: 1,2,3,4,5...50 y: Alaska, Alabama, Arkansas...

str(df_list[7]

df x: 1,2,3,4,5 y: ‘very low’, ‘low’, ‘moderate’, ‘high’, ‘very high’

Any ideas?

===========Update===============

Wanted to ensure I have the correct structure listed:

str(df_list)
List of 4
 $ :Classes ‘tbl_df’, ‘tbl’ and 'data.frame':   5 obs. of  2 variables:
  ..$ id   : num [1:5] 1 2 3 4 5
  ..$ value: chr [1:5] "very low" "low" "moderate" "high" ...
 $ :Classes ‘tbl_df’, ‘tbl’ and 'data.frame':   45 obs. of  2 variables:
  ..$ id   : num [1:45] 1 2 3 4 5 6 7 8 9 10 ...
  ..$ value: chr [1:45] "George Washington" "John Adams" "Thomas Jefferson" "James Madison" ...
 $ :Classes ‘tbl_df’, ‘tbl’ and 'data.frame':   50 obs. of  2 variables:
  ..$ id   : num [1:50] 1 2 3 4 5 6 7 8 9 10 ...
  ..$ value: chr [1:50] "Alabama" "Alaska" "Arizona" "Arkansas" ...
 $ :Classes ‘tbl_df’, ‘tbl’ and 'data.frame':   196 obs. of  2 variables:
  ..$ id   : num [1:196] 1 2 3 4 5 6 7 8 9 10 ...
  ..$ value: chr [1:196] "Kabul" "Tirana" "Algiers" "Andorra la Vella"...

ShinyApp:

load('C:/Users/me/OneDrive/Documents/RProj/apps/data/dfenv.RData')

ui <- fluidPage(


   titlePanel("Testing selectInput with list of data-frames"),


   sidebarLayout(
      sidebarPanel(
        selectInput("state","States:",
                    df_list[3][2]),
        selectInput("cty","Capital City:",
                    df_list[4][2]),
        selectInput("cnf","Confidence:",
                    df_list[1][2]),
        selectInput('potus',"President:",
                    df_list[2][2])
      )))


server <- function(input, output) {
   }


shinyApp(ui = ui, server = server)

The error:

Error in (function (choice, name) : All sub-lists in "choices" must be named.

1
As long as the df_list object is in scope this should work I think. I have done something similar with the select inputs in my app. Where have you written the two lines of code to create the df_list object? Also perhaps try it again but specifying the argument names to select input i.e. id= label= choices= - Adam Waring

1 Answers

2
votes

As usual, I found the answer..posting for the FUTURE.

library(readxl)
#create list of all files
list<-list.files(pattern="*.xlsx")

#read the files from `list`
df_list<-lapply(list,readxl::read_excel)

#apply function to take the second column from each sub-list (df)
x<-lapply(df_list, function(x) x[2])

#unlist IOT call in app
x2<-unlist(x, recursive = FALSE)

Structure (x2):

> List of 4  $ value: chr [1:5] "very low" "low" "moderate" "high" ... 
> $ value: chr [1:45] "George Washington" "John Adams" "Thomas
> Jefferson" "James Madison" ...  $ value: chr [1:50] "Alabama" "Alaska"
> "Arizona" "Arkansas" ...  $ value: chr [1:196] "Kabul" "Tirana"
> "Algiers" "Andorra la Vella" ...

App (note, the output is completely different as I was testing the selectInput)

library(shiny)
library(readxl)

list<-list.files(pattern="*.xlsx")

df_list<-lapply(list,readxl::read_excel)

df_x<-lapply(df_list, function(x) x[2])

x2<-unlist(x, recursive = FALSE)

shinyApp(
  ui = fluidPage(

        selectInput(inputId = "state",label="States:",
                    choices = 
                    x2[3]),
        selectInput(inputId="cty",label="Capital City:",
                    choices=
                      x2[4]),
        selectInput(inputId="cnf",label = "Confidence:",
                    choices = 
                      x2[1]),
        selectInput(inputId='potus',label = "President:",
                    choices=
                      x2[2]),
        tableOutput('data')),

  server = function(input, output) {
    output$data<-renderTable({
      mtcars[,c("mpg",input$state),drop=FALSE]},rownames=TRUE)
  }
)

working result