Home > Net >  How to create "Select All" option in a graphic using updateSelectizeInput() in R shiny?
How to create "Select All" option in a graphic using updateSelectizeInput() in R shiny?

Time:12-04

I am working on a Shiny app where the user would have the ability to select all options in the dropdown, a subset of options, and/or a single option.

My reproducible example of data to use:

set.seed(42)
n <- 366

mydata <- data.frame(id=1:n,
                     date = seq.Date(as.Date("2020-01-01"), as.Date("2020-12-31"), "day"),
                     group = rep(LETTERS[1:26], n/2))

#write_csv(mydata, "repex.csv")

My R Shiny code:

library(shiny)
library(tidyverse)
library(plotly)


mydata <- read_csv("repex.csv")

choices <- c('Select All', 'apple' = 'A', 'beta' = 'B', 'croc' = 'C', 'delta' = 'D',
             'echo chamber' = 'E', 'fudge nuggets' = 'F', 'good boy' = 'G', 'hot' = 'H',
             'it-tree' = 'I', 'joker' = 'J', 'kale' = 'K', 'lambo' = 'L', 'merry' = 'M', 
             'not so easy' = 'N', 'open' = 'O', 'pickles' = 'P', 'quasi' = 'Q', 'rotary' = 'R',
             'same' = 'S', 'token' = 'T', 'unix' = 'U', 'virtue' = 'V', 'whack-a-mole' = 'W', 
             'xylaphone?' = 'X', 'yeti' = 'Y', 'zebra' = 'Z')

#ui
ui <- fluidPage(
  titlePanel("My Dashboard"),
  sidebarLayout(
    sidebarPanel(
      dateRangeInput("dateRange", "Select date range:"),
      selectizeInput('group_type', 'For no action cases, select reason:', 
                     choices = choices, multiple = TRUE)
    ),
    mainPanel(
      tabsetPanel(
        tabPanel('plot1',
                 plotlyOutput("plot1")),
        tabPanel('plot2',
                 plotlyOutput('plot2')),
        tabPanel('plot3',
                 plotlyOutput('plot_3'))
        
      )
    )
  )
)



server <- function(input, output, clientData, session) {
  
  mydata <- mydata %>%
    mutate(
      date = as.Date(date, format="%Y-%m-%d")) %>%
    select(id, date, group)
  
  
  thedata <- reactive({
    my_data <- mydata
    # And update the date range values to match those of the dataset
    updateDateRangeInput(
      inputId = "dateRange",
      session = session,
      start = min(my_data$date),
      end = max(my_data$date)
    )
    my_data
  })
  
  
  observe({
    if ("Select All" %in% input$group_type) {
      selected_choices <- setdiff(choices, "Select All")
      
      updateSelectizeInput(session, "group_type", selected = selected_choices,
                           server = TRUE)
    }
  })
  
  
  output$plot_3 <- renderPlotly({
    # I need to subset the data, using the user input (dateRangeInput)
    data_subset3 <- dplyr::filter(thedata(),
                                  date >= input$dateRange[[1]],
                                  date <= input$dateRange[[2]])
    
    
    # And plot the subset of data
    data_subset3 %>%
      filter(group == input$group_type) %>%
      group_by(date, group) %>%
      summarise(counts = n()) %>%
      ungroup() %>%
      ggplot(., aes(date, counts, color = group))  
      geom_point()  
      theme_bw()
    
  })
  
  
}

shinyApp(ui = ui, server = server)

The current issue I'm having is when I go to plot 3, select the date range, and then select the 'Select All' option the graph stops working and I have to refresh the page. I want the user to be able to select to show all the groups at once (colored by group), a subset of groups to show up at once ('apple', 'beta', and 'yeti' for example), or just one group to show.

All the groups have the same distribution so for my repex data this may not seem useful but for my actual data this would be awesome thing to have!

Thank you!

CodePudding user response:

I think you'd want to use %in% not ==.

data_subset3 %>%
  filter(group %in% input$group_type) %>%
  group_by(date, group) %>%
  summarise(counts = n()) %>%
  ungroup() %>%
  ggplot(., aes(date, counts, color = group))  
  geom_point()  
  theme_bw()

CodePudding user response:

I found a solution that works nicely. I also included an option to clear all choices:

library(shiny)
library(tidyverse)
library(plotly)


mydata <- read_csv("repex.csv")

choices <- c('Select All', 'apple' = 'A', 'beta' = 'B', 'croc' = 'C', 'delta' = 'D',
             'echo chamber' = 'E', 'fudge nuggets' = 'F', 'good boy' = 'G', 'hot' = 'H',
             'it-tree' = 'I', 'joker' = 'J', 'kale' = 'K', 'lambo' = 'L', 'merry' = 'M', 
             'not so easy' = 'N', 'open' = 'O', 'pickles' = 'P', 'quasi' = 'Q', 'rotary' = 'R',
             'same' = 'S', 'token' = 'T', 'unix' = 'U', 'virtue' = 'V', 'whack-a-mole' = 'W', 
             'xylaphone?' = 'X', 'yeti' = 'Y', 'zebra' = 'Z')

#ui
ui <- fluidPage(
  titlePanel("My Dashboard"),
  sidebarLayout(
    sidebarPanel(
      dateRangeInput("dateRange", "Select date range:"),
      selectInput('group_type', 'For no action cases, select reason:', 
                     choices = choices, multiple = TRUE),
      actionButton('reset_group', 'Clear selection(s)')
    ),
    mainPanel(
      tabsetPanel(
        tabPanel('plot1',
                 plotlyOutput("plot1")),
        tabPanel('plot2',
                 plotlyOutput('plot2')),
        tabPanel('plot3',
                 plotlyOutput('plot_3'))
        
      )
    )
  )
)



server <- function(input, output, clientData, session) {
  
  mydata <- mydata %>%
    mutate(
      date = as.Date(date, format="%Y-%m-%d")) %>%
    select(id, date, group)
  
  
  thedata <- reactive({
    my_data <- mydata
    # And update the date range values to match those of the dataset
    updateDateRangeInput(
      inputId = "dateRange",
      session = session,
      start = min(my_data$date),
      end = max(my_data$date)
    )
    my_data
  })
  
  
  observe({
    if ("Select All" %in% input$group_type) 
      selected_choices <- choices[-1]
    else
      selected_choices <- input$group_type
    updateSelectInput(session, "group_type", selected = selected_choices)
    
  })
  
  
  observeEvent(input$reset_group, {
    updateSelectInput(session, "group_type", selected = "")
  })
  
  
  output$plot_3 <- renderPlotly({
    # I need to subset the data, using the user input (dateRangeInput)
    data_subset3 <- dplyr::filter(thedata(),
                                  date >= input$dateRange[[1]],
                                  date <= input$dateRange[[2]])
    
    
    # And plot the subset of data
    data_subset3 %>%
      filter(group %in% input$group_type) %>%
      group_by(date, group) %>%
      summarise(counts = n()) %>%
      ungroup() %>%
      ggplot(., aes(date, counts, color = group, group = group))  
      geom_line()  
      theme_bw()
    
  })
  
  
}

shinyApp(ui = ui, server = server)

I've changed from geom_point() to geom_line() to see if this still worked with other graph types.

CodePudding user response:

You need to subset properly, and there is no need of updateSelectizeInput. Try this

set.seed(42)
n <- 366

mydata <- data.frame(id=1:n,
                     date = seq.Date(as.Date("2020-01-01"), as.Date("2020-12-31"), "day"),
                     group = rep(LETTERS[1:26], n/2))

library(shiny)
library(tidyverse)
library(plotly)

#mydata <- read_csv("repex.csv")

choices <- c('Select All', 'apple' = 'A', 'beta' = 'B', 'croc' = 'C', 'delta' = 'D',
             'echo chamber' = 'E', 'fudge nuggets' = 'F', 'good boy' = 'G', 'hot' = 'H',
             'it-tree' = 'I', 'joker' = 'J', 'kale' = 'K', 'lambo' = 'L', 'merry' = 'M', 
             'not so easy' = 'N', 'open' = 'O', 'pickles' = 'P', 'quasi' = 'Q', 'rotary' = 'R',
             'same' = 'S', 'token' = 'T', 'unix' = 'U', 'virtue' = 'V', 'whack-a-mole' = 'W', 
             'xylaphone?' = 'X', 'yeti' = 'Y', 'zebra' = 'Z')

#ui
ui <- fluidPage(
  titlePanel("My Dashboard"),
  sidebarLayout(
    sidebarPanel(
      dateRangeInput("dateRange", "Select date range:"),
      selectizeInput('group_type', 'For no action cases, select reason:', 
                     choices = choices, multiple = TRUE)
    ),
    mainPanel(
      tabsetPanel(
        tabPanel('plot1',
                 plotOutput("plot1")),
        tabPanel('plot2',
                 plotOutput('plot2')),
        tabPanel('plot3', DTOutput("t1"),
                 plotlyOutput('plot_3'))
        
      )
    )
  )
)

server <- function(input, output, clientData, session) {
  
  mydata <- mydata %>%
    mutate(date = as.Date(date, format="%Y-%m-%d")) %>%
      dplyr::select(id, date, group)
  
  ### I need to subset the data, using the user input (dateRangeInput)
  data_subset1 <- eventReactive(input$dateRange, {
    dplyr::filter(mydata,
                  date >= input$dateRange[[1]],
                  date <= input$dateRange[[2]]) 
  })
  
  data_subset3 <- eventReactive(c(data_subset1(),input$group_type), {
    req(data_subset1(),input$group_type)
    if ("Select All" %in% input$group_type) dfa <- data_subset1()
    else dfa <- data_subset1() %>% dplyr::filter(group %in% input$group_type)
    df <- dfa %>%
      group_by(date,group) %>%
      dplyr::summarise(counts = n()) %>%
      ungroup() 
    df
  })
  
  output$t1 <- renderDT({data_subset1()})
  
  observe({
    my_data <- mydata
    # And update the date range values to match those of the dataset
    updateDateRangeInput(
      inputId = "dateRange",
      session = session,
      start = min(my_data$date),
      end = max(my_data$date)
    )

    # if ("Select All" %in% input$group_type) {
    #   selected_choices <- setdiff(choices, "Select All")
    #
    #   updateSelectizeInput(session, "group_type", selected = selected_choices,
    #                        server = TRUE)
    # }
  })
  
  
  
  output$plot1 <- renderPlot({plot(cars)})
  output$plot2 <- renderPlot({plot(pressure)})
  output$plot_3 <- renderPlotly({
    req(data_subset3())
    p <- ggplot(data_subset3(), aes(date, counts, color = group))  
      geom_point()  
      theme_bw()
    ggplotly(p)
  })
  
}

shinyApp(ui = ui, server = server)
  • Related