3

I'm trying to output a certain number based on the value from sliderTextInput, but for some reason, it doesn't seem to be displaying the right value as the slider changes. My list of choices for the sliderTextInput are ("0", "1", "2", ">2"), and for each of these values, it's supposed to render a text value of (0, 25, 50, 75), but the value for 0 is usually never displayed, and the values seem to be shifted by one value. Here is a reproducible example of the issue:

library(shiny)
library(shinyWidgets)

ui <- fluidPage(
  sliderTextInput("slider1", label = "What is your Score?", 
                  choices = c("0","1", "2", ">2"), selected = "0"),

    textOutput("score")
)

server <- function(input, output, session) {
  output$score <- renderText(switch(input$slider1,
                                  "0"  = 0,
                                  "1"  = 25,
                                  "2"  = 50,
                                  ">2" = 75))
}
shinyApp(ui, server)

I thought it might be because it can't interpret a mix of strings and numbers (e.g. ">2" vs "2"), or the value 0 might be interpreted differently, but changing these had no effect. The only way I was able to get it to work is if I changed every input value to a clear string (e.g. "Zero", "One", "Two", ">Two"). However, doesn't enclosing the numbers with quotes force evaluation as character, and not as a number? Or is the error something I am missing entirely?

justincj
  • 58
  • 1
  • 7

2 Answers2

2

switch requires exact match, but if you output:

output$score <- renderText(class(input$slider1))

you'll see that the 3 first choices return integer whereas the last one returns character.

Casting input$slider1 to character works:

library(shiny)
library(shinyWidgets)

ui <- fluidPage(
  sliderTextInput("slider1", label = "What is your Score?", 
                  choices = c("0","1", "2", ">2"), selected = "0"),
  
  textOutput("score")
)

server <- function(input, output, session) {
  output$score <- renderText(switch(as.character(input$slider1),
                                    "0"  = 0,
                                    "1"  = 25,
                                    "2"  = 50,
                                    ">2" = 75))
}
shinyApp(ui, server)
 
Waldi
  • 39,242
  • 6
  • 30
  • 78
  • Ah, I see! I had actually tried casting the sliderTextInput choices to characters, but didn't realize I had to cast the input instead. And I didn't even realize it was an issue with a switch instead of sliderTextInput. It worked, thank you! – justincj Aug 07 '20 at 08:51
1

This might have something to do with how switchworks, e.g., from its help page,

if there is a match then that element is evaluated unless it is missing, in which case the next non-missing element is evaluated, so for example switch("cc", a = 1, cc =, cd =, d = 2) evaluates to 2.

...particularly in combination with sliderTextInput -- I note that if you simply define output$score <- renderText(input$slider1) it will not render anything when the slider is set to 0. So I'm not really sure what's going on.

One way you could get the output you want (while not as pretty as switch) is using dplyr::case_when, e.g.,

server <- function(input, output, session) {
    output$score <- renderText(
        dplyr::case_when(
            input$slider1 == "0" ~ 0,
            input$slider1 == "1" ~ 25,
            input$slider1 == "2" ~ 50,
            input$slider1 == ">2" ~ 75))
}
heds1
  • 3,203
  • 2
  • 17
  • 32
  • 1
    Yeah it does seem to be an issue with switch, as @Waldi similarly pointed out. I think there might be some heuristic that automatically converts text like "0" to its integer form, and because switch requires an exact match, it messes up somehow. And thanks for the dplyr alternative, I'll keep it in mind! – justincj Aug 07 '20 at 08:53