Home > Software design >  Select a column of a dataframe to subset the whole dataframe based on value of this column in a shin
Select a column of a dataframe to subset the whole dataframe based on value of this column in a shin

Time:01-19

In the shiny app below I have already developed a method in which the user types a string in the first textInput() then he clicks "Begin search" in the 1st actionButton() and subsets its dataset based on this string. Then he can click Reset to reset the dataset.

Now I want to add a 2nd search method in which the user will be able to select also a column, then type a string in the 2nd textInput(), click Begin Search on the 2nd actionButton() and subset the whole dataset based on this column, then clicks Reset to reset.

#Load libraries needed
library(shiny)
library(shinydashboard)
library(DT)
library(shinyWidgets)
library(purrr)
library(dplyr)

#load ldataset
data_test_1_ <-structure(list(Dimension = c("environmental", "environmental", 
                                            "environmental", "environmental", "environmental", "environmental", 
                                            "environmental", "environmental", "environmental", "environmental"
), Component = c("air quality", "air quality", "air quality", 
                 "water quality", "environmental hazards", "environmental hazards", 
                 "environmental hazards", "environmental hazards", "environmental hazards", 
                 "physical safety"), Indicator = c("outdoor", "outdoor", "indoor", 
                                                   NA, "Hazardous waste", "Heavy metals", "Pesticides", "Climate extremes", 
                                                   "Noise", "Traffic")), row.names = c(NA, 10L), class = c("tbl_df", 
                                                                                                           "tbl", "data.frame"))

#Dashboard
ui <- dashboardPage(
  dashboardHeader(title = "Dataset Inventory"),
  #left sidebar part
  dashboardSidebar(

    #the search box
    textInput("tt","Search whole dataset",""),
    
    #the button that triggers search
    actionButton("ser","Begin search"),
    
    tags$hr(),
    
    #select column to search
    uiOutput("column"),
    
    pickerInput(
      inputId = "p3",
      label = "Select Column to search",
      choices = colnames(data_test_1_),
      selected = colnames(data_test_1_[1]),
      multiple = F,
      options = list(`actions-box` = TRUE)
    ),
    
    #the search box for column
    textInput("tt2","Search column",""),
    
    #the button that triggers search column
    actionButton("ser2","Begin search"),
    
    tags$hr(),
    
    #the button that triggers reset
    actionButton("res","Reset")
    
  ),
  #the main body part
  dashboardBody(
    #the table
    div(DT::dataTableOutput("table"), style = "font-size: 80%; width: 100%")
    
  )
)

#the server part
server <- function(input, output,session) {
  #a counter that is used for search and reseting
  cntrl <- reactiveValues(n = 0)
  
  #the reacive calling of the dynamic datatable
  output$table <- renderDataTable({
    datatable(data_test_1_)
    
  })
  
  #the observer that activates the search button and searches all the felds of the dataset
  observeEvent(input$ser,
               {
                 cntrl$n <- cntrl$n   1
                 output$table<-renderDataTable({
                   datatable(d_new <- data_test_1_[apply(data_test_1_, 1, function(x) any(grepl(isolate(input$tt), x))), ],escape = F
                             )
                 })
               }
               
  )
  
  #the observer that resets the dataset before the searching
  observeEvent(input$res,
               {
                 cntrl$n <- 0
                 updateTextInput(session, "tt", value = "")
                 output$table <- renderDataTable(datatable(data_test_1_,
                                                           escape = F
                                                           ))
               })
  
  
  
}

shinyApp(ui, server)

CodePudding user response:

Is there a specific reason why you want to include searching functionality in the sidebar rather than directly in DT?

The quickest way to filter in DT is by adding the filter parameter. In any event here's one possible solution.

Rather than creating a new datatable every time a search is made. I've added a reactiveValue called data_test that contains the data. Then in each observeEvent all you need to do is modify data_test$d and renderDataTable will render the data that is pointed to that reactiveValue. I also added filter = "top" in case you haven't seen that before.

Lastly, in the second observeEvent where you want to search by column. I've set input$p3 to the variable col. Then wrapped col with the bang bang operator !! and rlang::sym.

#the server part
server <- function(input, output,session) {
  #a counter that is used for search and reseting
  cntrl <- reactiveValues(n = 0)
  
  data_test = reactiveValues(
    d = data_test_1_
  )
  
  #the reacive calling of the dynamic datatable
  output$table <- renderDataTable({
    datatable(data_test$d, filter = "top")
  })
  
  #the observer that activates the search button and searches all the felds of the dataset
  observeEvent(input$ser, {
    cntrl$n <- cntrl$n   1
    data_test$d = data_test_1_[apply(data_test_1_, 1, function(x) any(grepl(isolate(input$tt), x))), ]
  })
  
  observeEvent(input$ser2, {
    col = input$p3

    data_test$d = data_test_1_ %>%
      filter(grepl(isolate(input$tt2), !!sym(col)))
  })
  
  #the observer that resets the dataset before the searching
  observeEvent(input$res, {
    cntrl$n <- 0
    updateTextInput(session, "tt", value = "")
    data_test$d = data_test_1_ # reset to original data
  })
}

shinyApp(ui, server)
  • Related