Reactive filtering and adding in shiny

I'm trying to create a reactive count based off distinctive values.

So let's say you adjust the age slide to Age >= 50 and a Current Score >= 10 it returns a count of 1571 unique customer IDs, which are then showed in the table. Then you click the Add to List button and those 1571 are added. But at the same time, those 1571 are also removed from the filtered dataset you're working with. Now all of the inputs reset themselves after you make that add. Then let's say you want to add all hispanic people with a Current Score >= 20, so you move The way I have it setup, it would return a value of 310, but with the filtering setup to what I'm trying to achieve, it would be returning only the unique Customer IDs that haven't been filtered out yet, and those would be added to the total count/table.

Does this make sense?

df <- read.csv('https://raw.githubusercontent.com/gooponyagrinch/sample_data/master/datasheet.csv')

ui <- fluidPage(
  fluidRow(
    column("",
           width = 10, offset = 1,
           tags$h3("Select Area"),
           panel(
             sliderInput("current", "Current Score",
                         min = 0, max = 100, value = 20),
             sliderInput("projected", "Projected Score",
                         min = 0, max = 100, value = 20),
             sliderInput("age", "Age",
                         min = 18, max = max(df$age), value = c(18,24)),
             checkboxGroupInput("ethnicity",label = "Ethnicity", 
                                choices = list("Caucasian"="Caucasian",
                                               "African-American"="African-American",
                                               "Hispanic"="Hispanic",
                                               "Other"="Other")),
             checkboxInput('previous', label = "Previous Sale"),
             checkboxInput('warm', label = "Warm Lead"),
             actionButton("button", "Add to List")), 
           textOutput("counter"),
           DT::dataTableOutput("table")
    )
  )
)

server <- function(input, output, session) {
  
  filtered_df <- reactive({
    
    res <- df %>% filter(current_grade >= input$current)
    res <- res %>% filter(projected_grade >= input$projected)
    res <- res %>% filter(age >= input$age[1] & age <= input$age[2])
    res <- res %>% filter(ethnicity %in% input$ethnicity | is.null(input$ethnicity))
    
    if(input$previous == TRUE)
      res <- res %>% filter(previous_sale == 1)
    
    if(input$warm == TRUE)
      res <- res %>% filter(warm_lead == 1)
    
    res
    
  })
  
  output$counter <- renderText({
    
    
    
    res <- filtered_df() %>% select(customer_id) %>% n_distinct()
    
    res
    
  })
  
  
  output$table <- renderDataTable({
    
    res <- filtered_df() %>% distinct(customer_id)
    
    res
    
  })
  
}

shinyApp(ui,server)

Hi,

First of all, thanks for generating a nice reprex with data and code available. The only thing you forgot was to add the necessary libraries, so I had to guess them :slight_smile:

I think I get what you wanted, so this is my solution:

df <- read.csv('https://raw.githubusercontent.com/gooponyagrinch/sample_data/master/datasheet.csv')

library(shiny)
library(shinyWidgets)
library(tidyverse)
library(DT)

ui <- fluidPage(
  fluidRow(
    column("",
           width = 10, offset = 1,
           tags$h3("Select Area"),
           panel(
             sliderInput("current", "Current Score",
                         min = 0, max = 100, value = 20),
             sliderInput("projected", "Projected Score",
                         min = 0, max = 100, value = 20),
             sliderInput("age", "Age",
                         min = 18, max = max(df$age), value = c(18,24)),
             checkboxGroupInput("ethnicity",label = "Ethnicity", 
                                choices = list("Caucasian"="Caucasian",
                                               "African-American"="African-American",
                                               "Hispanic"="Hispanic",
                                               "Other"="Other")),
             checkboxInput('previous', label = "Previous Sale"),
             checkboxInput('warm', label = "Warm Lead"),
             actionButton("button", "Add to List")), 
           textOutput("counter"),
           tags$h2("Data to filter"),
           DT::dataTableOutput("table"),
           tags$h2("IDs added to list"),
           DT::dataTableOutput("addedToList")
    )
  )
)

server <- function(input, output, session) {
  
  filterData = reactiveVal(df %>% mutate(key = 1:nrow(df)))
  addedToList = reactiveVal(data.frame())
  
  filtered_df <- reactive({
    
    res <- filterData() %>% filter(current_grade >= input$current)
    res <- res %>% filter(projected_grade >= input$projected)
    res <- res %>% filter(age >= input$age[1] & age <= input$age[2])
    res <- res %>% filter(ethnicity %in% input$ethnicity | is.null(input$ethnicity))
    
    if(input$previous == TRUE)
      res <- res %>% filter(previous_sale == 1)
    
    if(input$warm == TRUE)
      res <- res %>% filter(warm_lead == 1)
    
    res
    
  })
  
  output$counter <- renderText({
    res <- filtered_df() %>% select(customer_id) %>% n_distinct()
    res
  })
  
  
  output$table <- renderDataTable({
    res <- filtered_df() %>% distinct(customer_id)
    res
    
  })
  
  observeEvent(input$button, {
    
    addedToList(rbind(addedToList(), 
                      filterData() %>% filter(key %in% filtered_df()$key) %>% 
                        select(customer_id) %>% distinct() ))
    
    filterData(filterData() %>% filter(!key %in% filtered_df()$key))
    
  })
  
  output$addedToList <- renderDataTable({
    addedToList()
  })
  
}

shinyApp(ui,server)
  • First of all, I made the original dataset reactive (called filterData) and added a unique key column for better filtering (your data has no unique column, as 1 customer ID can have multiple rows).
  • I also created a reactive data frame (called addedToList) to store the added values from the filtering
  • I then added an obverveEvent for the add-to-list button in which I first add the filtered values to addedToList, then remove them from the filterData dataset so they will no longer display in that table
  • I also added a second table to your output to show the list (you can remove this of course)

Hope this helps,
PJ

Hi @pieterjanvc Sorry, I've been out of the country the past week.

This worked really well! Thanks.

Another question: What if after you hit the "Add to List" button and adds the selections, the form reset itself by deselecting all values?

Hi,

I'm happy I was able to help!
I don't really understand your follow-up question through, could you elaborate?
Also, please mark my post as the solution if you think it answers the original question so others know it has been resolved.

PJ

This topic was automatically closed 21 days after the last reply. New replies are no longer allowed.