Reputation: 67
I want to use different datasets in my app depending on the user's input.
Imagine I have these files:
AA.csv
AB.csv
AC.csv
Is it possible to formulate a conditional statement that changes the file name to be called according to the selection of the user in the input field?
For illustration purposes, I'm attaching some code of the behaviour that I'd like to have.
ui<- fluidPage(
selectInput(inputId="file", label= "File",
choices = c("AA", "AB", "AC"))
)
server<- function(input, output,session){
datafile<- reactive({read.csv("input$file".csv })
I hope my question is clear.
Upvotes: 0
Views: 33
Reputation: 160397
The first step is that your read.csv
code should be something like
datafile <- reactive({ read.csv(paste0(input$file, ".csv")) })
Two ways to make this a little better:
req
, so that a missing (mislocated) file doesn't spawn an error, just a lack of data; andselectInput
.If you're only concerned about checking for the available files at app startup, then perhaps this will suffice:
files <- list.files("./data", pattern = "\\.csv$", full.names = TRUE)
choices <- setNames(files, tools:::file_path_sans_ext(basename(files)))
shinyApp(
ui = fluidPage(
selectInput("file", "File", choices = choices, selectize = FALSE),
textAreaInput("txtarea", "File top 10 lines:", rows = 10)
),
server = function(input, output, session) {
somedata <- reactive({
req(input$file)
readLines(input$file, n = 10)
})
observeEvent(somedata(), {
updateTextAreaInput(session, "txtarea", value = somedata())
})
}
)
(I'm using a textAreaInput
just to show the file contents ... assuming you have different needs, then you likely don't need the observeEvent
in order to update that input field.)
If this is a "long-running" app that needs to react to new files without restarting, then you can set a "poll" that will periodically update the list of available files for input. While this is intended to adjust for new files, it also reacts to removed files.
shinyApp(
ui = fluidPage(
selectInput("file", "File", choices = c(), selectize = FALSE),
textAreaInput("txtarea", "File top 10 lines:", rows = 10)
),
server = function(input, output, session) {
observe({
invalidateLater(30000, session) # 30 seconds
sel <- input$file
files <- list.files("./data", pattern = "\\.csv$", full.names = TRUE)
choices <- setNames(files, tools:::file_path_sans_ext(basename(files)))
if (!sel %in% choices) sel <- choices[1]
updateSelectInput(session, "file", choices = choices, selected = sel)
})
somedata <- reactive({
req(input$file)
readLines(input$file, n = 10)
})
observeEvent(somedata(), {
updateTextAreaInput(session, "txtarea", value = somedata())
})
}
)
This second app starts with zero choices (c()
) and updates them immediately. I set a 30-second poll; your use-case will dictate something more reasonable, recognizing that sub-second response might be compromising unnecessary filesystem access for apparent need for file-reactivity.
I did a quick setup for testing with:
# setup
dir.create("data")
writeLines("hello world", "./data/AA.csv")
writeLines("hello world again", "./data/AB.csv")
Upvotes: 1