'Why does this selectizeInput minimum values function not work correctly for 2 digit numbers even though it works fine for single digit numbers?

This one has me puzzled. The below code extract uses selectizeInput() to allow the user to choose to/from periods for purposes of data analysis (latter not shown), with the choices offered in the selectizeInput() boxes following the rules that (a) the "To" periods on offer in the right box are > than the "From" Periods shown in the left box, with the default "To" period shown = 1 greater than the selected "From", and (b) the maximum "From" period shown in the left box is 1 less than the max of all periods.

The below code works fine until you get to "From" period 9, at which point the App crashes with the following message: "Warning in min(all_choices_reactive()[all_choices_reactive() > input$transFrom]) : no non-missing arguments to min; returning Inf". And once you exceed "From" period 9, the only "To" period shown is 2.

How can this be fixed?

Please note that in the full code this reproducible code is extracted from, there are unique 40 periods and these functions suffer from the same glitch when dealing with values > 9 (or 2 digit numbers). I've fiddled with using strtoi() function for converting strings to integers (per https://stat.ethz.ch/R-manual/R-devel/library/base/html/strtoi.html), as.numeric() here and there, with no luck yet.

Image at the bottom shows the problem.

Reproducible code:

library(shiny)

transitDF <- data.frame(Period = c(1,2,3,4,5,6,7,8,9,10,11,12))  

all_choices_p1 <- unique(transitDF$Period)

ui <- fluidPage(
  br(),
  fluidRow(
    column(3,h5(strong("Select from/to periods:"))),
    column(2,selectizeInput(
               inputId = "transFrom",
               label = NULL,
               choices = all_choices_p1[-length(all_choices_p1)],
               selected = 1
             )),
    column(2,selectizeInput(
               inputId = "transTo",
               label = NULL,
               choices = all_choices_p1[-1],
               selected = 2
              ))
  ),
  fluidRow(
    column(3,h5(strong("Output to period:"))),
    column(2,textOutput("toResults"),style = "padding-top: 9px;")
    )
)

server <- function(input, output, session) {

  all_choices_reactive <- reactiveVal(all_choices_p1)
  
  observeEvent(input$transFrom, {
    freezeReactiveValue(input,"transTo")
    updateSelectizeInput(
      session,
      inputId = "transTo",
      choices = all_choices_reactive()[all_choices_reactive() > input$transFrom],
      selected = min(all_choices_reactive()[all_choices_reactive() > input$transFrom])
      )
    }, ignoreInit = TRUE)
  
  toResults <- reactive({
      req(input$transTo)
      toResults <- min(all_choices_reactive()[all_choices_reactive() > input$transFrom])
  })
  
  output$toResults <- renderText({toResults()})
  
}

shinyApp(ui, server)

enter image description here



Solution 1:[1]

Code below works by converting character strings to integers using strtoi(...) function per stefan comment as shown below:

library(shiny)

transitDF <- data.frame(Period = as.numeric(c(1,2,3,4,5,6,7,8,9,10,11,12)))  

all_choices_p1 <- (unique(transitDF$Period))

ui <- fluidPage(
  br(),
  fluidRow(
    column(3,h5(strong("Select from/to periods:"))),
    column(2,selectizeInput(
               inputId = "transFrom",
               label = NULL,
               choices = all_choices_p1[-length(all_choices_p1)],
               selected = 1
             )),
    column(2,selectizeInput(
               inputId = "transTo",
               label = NULL,
               choices = all_choices_p1[-1],
               selected = 2
              ))
  ),
  fluidRow(
    column(3,h5(strong("Output to period:"))),
    column(2,textOutput("toResults"),style = "padding-top: 9px;")
    )
)

server <- function(input, output, session) {

  all_choices_reactive <- reactiveVal(all_choices_p1)
  
  observeEvent(input$transFrom, {
    freezeReactiveValue(input,"transTo")
    updateSelectizeInput(
      session,
      inputId = "transTo",
      choices = all_choices_reactive()[all_choices_reactive() > strtoi(input$transFrom)],
      selected = min(all_choices_reactive()[all_choices_reactive() > strtoi(input$transFrom)])
      )
    }, ignoreInit = TRUE)
  
  toResults <- reactive({
      req(input$transTo)
      toResults <- as.numeric(min(all_choices_reactive()[all_choices_reactive() > strtoi(input$transFrom)]))
  })
  
  output$toResults <- renderText({toResults()})
  
}

shinyApp(ui, server)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Curious Jorge - user9788072