Reputation: 17
I want to write an app that reads in the uploaded data, then puts enough numericInput
due to the number of unique elements in a column (the name of the columns is Big). This question here helped me.
The code is as below:
library(shiny)
ui <- fluidPage(
fileInput(inputId = "up","", accept = '.csv'),
uiOutput("sliders")
)
server <- function(input, output, session) {
INPUT <- reactive({
infile <- input$up
#validate(need(input$up, "Input a valid filepath."))
read.csv(infile$datapath, header = TRUE, sep = ",")
})
inVars <- reactive({
unique(INPUT()$Big)
})
output$sliders <- renderUI({
pvars <- length(inVars())
lapply(seq(pvars), function(i) {
numericInput(inputId = paste0("range", pvars[i]),label = pvars[i],value = 1)
})
})
}
shinyApp(ui = ui, server = server)
Three questions:
1. When I put
if (is.null(infile))
return(NULL)
instead of validate
, it gives me an error which looks like this:
missing value where TRUE/FALSE needed
What should I do to get rid of this error?
2. How could I add a label for each one of the numericInput
?
3. How could I use the input values later? In a reactive
environment?
Thanks
Upvotes: 0
Views: 1913
Reputation: 5697
The problem is not with the if (is.null(infile))
statement, it is with the lapply
function. When the Shiny app just starts, the entire server
function is executed, the length of inVars()
is 0
and the sequence seq(pvars)
will be 1
0
. Then the numericInput
will fail because you are making a reference to pvars[i]
when i
is equal to 0
.
Below is the code that fixes the problem and also answers your questions.
library(shiny)
ui <- fluidPage(
fileInput(inputId = "up","", accept = '.csv'),
uiOutput("sliders")
)
server <- function(input, output, session) {
INPUT <- reactive({
infile <- input$up
if (is.null(infile))
return(NULL)
read.csv(infile$datapath, header = TRUE, sep = ",")
})
inVars <- reactive({
unique(INPUT()$Big)
})
output$sliders <- renderUI({
pvars <- length(inVars())
if (pvars > 0) {
div(
lapply(seq(pvars), function(i) {
numericInput(inputId = paste0("range", inVars()[i]),label = inVars()[i],value = 1)
}),
actionButton("getValues", "Get values"),
tableOutput('table')
)
}
})
values <- 0
# get the values of each numericInput and store them in "values"
observeEvent(input$getValues, {
# initialize vector
values <<- rep(NA, length(inVars()))
names(values) <<- inVars()
for(k in 1:length(inVars())) {
inputName <- paste0("range", inVars()[k])
# only get a value if the numeric input exists
if (!is.null(inputName))
values[[k]] <<- input[[inputName]]
}
# show values as a table
output$table <- renderTable(data.frame(
variable = inVars(),
values))
})
}
shinyApp(ui = ui, server = server)
Update:
To test the code, use a .csv file with content like:
num,Big
1,a
2,a
3,b
4,b
5,c
6,c
7,d
8,d
Screenshot:
Upvotes: 1