Kim
Kim

Reputation: 117

Set a range in sizeslider: Shiny

I use in my work program on the forum, but testing it I noticed that it works badly. As you can see in the attached image, the set size range shows incorrect fields in the table. Only when we select "Choose Cat 1" as "all" size range work well. Can you indicate what needs to be corrected?

enter image description here

Below is the code:

library(shiny) 
data.input <- data.frame(
  Category1 = rep(letters[1:3],each=15),
  Info = paste("Text info", 1:45),
  Category2 = sample(letters[15:20], 45, replace = T),
  Size = sample(1:100, 45),
  MoreStuff = paste("More Stuff", 1:45)
)
ui <- fluidPage(titlePanel("Test Explorer"),
                sidebarLayout(
                  sidebarPanel(
                    selectizeInput(
                      "show_vars",
                      "Columns to show:",
                      choices = colnames(data.input),
                      multiple = TRUE,
                      selected = c("Category1", "Info", "Category2")
                    ),
                    actionButton("button", "An action button"),
                    uiOutput("category1"),
                    uiOutput("category2"),
                    uiOutput("sizeslider")
                  ),
                  mainPanel(tableOutput("table"))
                ))

server <- function(input, output, session) {
  data.react <- eventReactive(input$button, {
    data.input[, input$show_vars]
  })
  observeEvent(input$button, {
    output$category1 <- renderUI({
      data.sel <- data.react()
      selectizeInput('cat1',
                     'Choose Cat 1',
                     choices = c("All", sort(as.character(
                       unique(data.sel$Category1)
                     ))),
                     selected = "All")
    })

    df_subset <- eventReactive(input$cat1, {
      data.sel <- data.react()
      if (input$cat1 == "All") {
        data.sel
      }
      else{
        data.sel[data.sel$Category1 == input$cat1,]
      }
    })

    output$category2 <- renderUI({
      selectizeInput(
        'cat2',
        'Choose Cat 2 (optional):',
        choices = sort(as.character(unique(
          df_subset()$Category2
        ))),
        multiple = TRUE,
        options = NULL
      )
    })

    df_subset1 <- reactive({
      if (is.null(input$cat2)) {
        df_subset()
      } else {
        df_subset()[df_subset()$Category2 %in% input$cat2,]
      }
    })

    output$sizeslider <- renderUI({
      sliderInput(
        "size",
        label = "Size Range",
        min = min(data.input$Size),
        max = max(data.input$Size),
        value = c(min(data.input$Size), max(data.input$Size))
      )
    })

    df_subset2 <- reactive({
      if (is.null(input$size)) {
        df_subset1()
      } else {
        df_subset1()[data.input$Size >= input$size[1] &
                       data.input$Size <= input$size[2],]
      }
    })
    output$table <- renderTable({
      df_subset2()

    })
  })
}

shinyApp(ui, server)

Upvotes: 0

Views: 128

Answers (1)

InfiniteFlash
InfiniteFlash

Reputation: 1058

After a bit of debugging, you'll notice that

df_subset2 <- reactive({
  if (is.null(input$size)) {
    df_subset1()
  } else {
    df_subset1()[data.input$Size >= input$size[1] &
                   data.input$Size <= input$size[2],]
  }

should be

df_subset2 <- reactive({
  if (is.null(input$size)) {
    df_subset1()
  } else {
    df_subset1()[df_subset1()$Size >= input$size[1] &
                  df_subset1()$Size <= input$size[2],]
  }

You were specifying the wrong condition to subset by in your conditional statement since you're referring to data.input not data_subset1().



A few other [less important] notes


  • dplyr

I would try replacing statements like the one below

df_subset1()[data.input$Size >= input$size[1] &
                   data.input$Size <= input$size[2],]

with

df_subset1()%>% filter(between(Size, input$size[1], input$size[2]))

because of readability. Many of your filtering conditions can be replaced via filter() within the package dplyr. It looks nicer.


  • Display of columns

Please consider (this is only a suggestion, not that important) replacing

selected = c("Category1", "Info", "Category2")

with

selected = c("Category1", "Info", "Category2", "Size")

for the initial display, in the UI, for debugging these kinds of things. It's kind of a pain to click back and forth when looking in the app. Why not have them all displayed at once?

I hope this helped!

Upvotes: 1

Related Questions