Reputation: 639
I am new to Shiny, and the answers to similar questions as mine on SO are helping me.
I want to display dynamic choices on the pull down menu, depending on what the user chooses on the radio button. But the snippet below can only show one choice for the subspecies, once the user chooses, first #1 the animal type, and then #2 the whole vs. subspecies choice.
I have three variables: #1. animal type (Lion vs Tiger); #2. whole vs subspecies (radiobutton); #3. subspecies (and if the user chooses "whole" in #2, then the subspecies should be equal to "Not Applicable").
FYI:
Tiger subspecies = {Bengal, Siberian}
Lion subspecies = {Barbary, Southwest African, Transvaal}
Any help is appreciated. Thanks.
library(shiny)
if (interactive()) {
ui <- fluidPage(
selectizeInput("VarAnimal",
label = "Animal",
choices = c("Tiger", "Lion"),
selected = "Tiger"),
radioButtons("VarWholeOrSub",
"Whole or Sub",
choices = c("Whole species", "Subspecies"),
selected = "Whole species"),
selectizeInput("VarSubspecies",
label = "Subspecies",
choices = c("Not Applicable", "Bengal", "Siberian", "Barbary", "Southwest African", "Transvaal"),
selected = "")
)
server <- function(input, output, session) {
observe({
x <- input$VarWholeOrSub
if (input$VarWholeOrSub == "Whole species"){
x <- c("Not Applicable")} else{
x <- ifelse(input$VarAnimal == "Tiger", c("Bengal", "Siberian"), c("Barbary", "Southwest African", "Transvaal"))
}
updateSelectizeInput(session,
"VarSubspecies",
choices = x)
})
}
shinyApp(ui, server)
}
Upvotes: 0
Views: 148
Reputation: 23101
Couple of points:
(1) As mentioned in the previous posts, ifelse
is the culprit here.
?ifelse
says
ifelse(test, yes, no)
ifelse returns a value with the same shape as test
which is one in your case, you should use if-else block as suggested.
(2) You may want to have less hard-coding in your code, by separating out the data (may be globally, so that later you don't need to change your R code to change data) and getting rid of some redundant codes:
df <- data.frame(Animals = c("Tiger", "Lion"),
WholeSpecies=rep("Not Applicable", 2),
SubSpecies=c("Bengal, Siberian", "Barbary, Southwest African, Transvaal"),
stringsAsFactors = FALSE)
head(df)
# Animals WholeSpecies SubSpecies
#1 Tiger Not Applicable Bengal, Siberian
#2 Lion Not Applicable Barbary, Southwest African, Transvaal
library(shiny)
if (interactive()) {
ui <- fluidPage(
selectizeInput("VarAnimal",
label = "Animal",
choices = df$Animals,
selected = df$Animals[1]),
radioButtons("VarWholeOrSub",
"Whole or Sub",
choices = c("Whole species", "Subspecies"),
selected = "Whole species"),
selectizeInput("VarSubspecies",
label = "Subspecies",
choices = c(unique(df$WholeSpecies), unlist(strsplit(unique(df$SubSpecies), split=','))),
selected = "")
)
server <- function(input, output, session) {
observe({
x <- df[df$Animals==input$VarAnimal,]$WholeSpecies
if (input$VarWholeOrSub == "Subspecies"){
x <- unlist(strsplit(df[df$Animals==input$VarAnimal,]$SubSpecies, split=','))
}
updateSelectizeInput(session,
"VarSubspecies",
choices = x)
})
}
shinyApp(ui, server)
}
Upvotes: 1
Reputation: 19544
The problem comes from the use of ifelse(test, yes, no)
when yes or no have different length of test:
> ifelse("a"=="a", c("a","b"), c("b","a"))
[1] "a"
> ifelse(rep("a"=="a",2), c("a","b"), c("b","a"))
[1] "a" "b"
In your case - with 3 different lengths - you should use if
instead:
if (input$VarWholeOrSub == "Whole species"){
x <- c("Not Applicable")
} else {
if(input$VarAnimal == "Tiger")
x <- c("Bengal", "Siberian")
else
x <- c("Barbary", "Southwest African", "Transvaal")
}
Upvotes: 2
Reputation: 1438
The documentation for ifelse states:
ifelse returns a value with the same shape as test which is filled with elements selected from either yes or no depending on whether the element of test is TRUE or FALSE.
library(shiny)
if (interactive()) {
ui <- fluidPage(
selectizeInput("VarAnimal",
label = "Animal",
choices = c("Tiger", "Lion"),
selected = "Tiger"),
radioButtons("VarWholeOrSub",
"Whole or Sub",
choices = c("Whole species", "Subspecies"),
selected = "Whole species"),
selectizeInput("VarSubspecies",
label = "Subspecies",
choices = c("Not Applicable", "Bengal", "Siberian", "Barbary", "Southwest African", "Transvaal"),
selected = "")
)
server <- function(input, output, session) {
observe({
if (input$VarWholeOrSub == "Whole species"){
updateSelectizeInput(session, 'VarSubspecies', choices = c("Not Applicable"))
} else{
if(input$VarAnimal == "Tiger"){
updateSelectizeInput(session, 'VarSubspecies', choices = c("Bengal", "Siberian"))
} else if (input$VarAnimal == "Lion"){
updateSelectizeInput(session, 'VarSubspecies', choices = c("Barbary", "Southwest African", "Transvaal"))
}
}
})
}
shinyApp(ui, server)
}
Upvotes: 1