library(shiny)library(dplyr)library(ggplot2)
ui <- fluidPage( fluidRow( # control panel column( # initial input required to query large dataset numericInput( inputId = "min_year", label = "Select Min Model Year", min = 1999, max = 2008, value = 2000 ), # progressive manufacturer filter uiOutput("manufacturer_control"), # progressive transmission filter uiOutput("trans_control"), # progressive compact filter uiOutput("cyl_control"), width = 2 ), # display table column( tableOutput("table"), width = 10 ) ))
server <- function(input, output) { # reactive function to pull down large dataset once mpg_all <- reactive({ ggplot2::mpg %>% filter(year >= input$min_year) }) # reactive filtering on large dataset that progressively narrows input choices mpg_fltr <- reactive({
mpg_fltr <- mpg_all() if (!is.null(input$manufacturer)) { mpg_fltr <- filter(mpg_fltr, manufacturer %in% input$maufacturer) } if (!is.null(input$trans)) { mpg_fltr <- filter(mpg_fltr, trans %in% input$trans) }
if (!is.null(input$cyl)) { mpg_fltr <- filter(mpg_fltr, cyl %in% input$cyl) }
mpg_fltr }) # create manufacturer input output$manufacturer_control <- renderUI({
selectizeInput( inputId = "manufacturer", label = "Select Manufacturers", choices = mpg_fltr()$manufacturer, multiple = TRUE ) }) # create transmission input output$trans_control <- renderUI({
selectizeInput( inputId = "trans", label = "Select Transmissions", choices = mpg_fltr()$trans, multiple = TRUE ) }) # create cylinder count input output$cyl_control <- renderUI({
selectizeInput( inputId = "cyl", label = "Select Cylinder Count", choices = mpg_fltr()$cyl, multiple = TRUE ) }) # display results in table output$table <- renderTable({ head(mpg_fltr(), 20) })}
shinyApp(ui = ui, server = server)
--
You received this message because you are subscribed to the Google Groups "Shiny - Web Framework for R" group.
To unsubscribe from this group and stop receiving emails from it, send an email to shiny-discus...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/shiny-discuss/0a2868ba-bee1-459f-9b83-58d8336374e7%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
--
You received this message because you are subscribed to the Google Groups "Shiny - Web Framework for R" group.
To unsubscribe from this group and stop receiving emails from it, send an email to shiny-discus...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/shiny-discuss/854831cd-7c96-46df-b568-d02fd5471606%40googlegroups.com.
library(shiny)
columnFilterUI <- function(id) {
ns <- NS(id)
uiOutput(ns("filter_container"))
}
columnFilter <- function(input, output, session, df, col_num, choice_filter, reset=F) {
if(reset){
updateSelectInput(session, "filter_value",
choices = sort(unique(df()[,col_num,drop=TRUE])),
selected = NULL
)
}else{
# This renders a selectInput and only re-renders when the selected data
# frame changes. (i.e. it doesn't re-render when filters change state.)
output$filter_container <- renderUI({
# Don't render if col_num is > actual number of cols
req(col_num <= ncol(df()))
freezeReactiveValue(input, "filter_value")
selectInput(session$ns("filter_value"), names(df())[[col_num]],
choices = sort(unique(df()[,col_num,drop=TRUE])),
multiple = TRUE)
})
# When the other filters change, update this filter to remove rows that
# are filtered out by the other filters' criteria. (We also add in the
# currently selected values for this filter, so that changing other
# filters does not cause this filter's selected values to be unselected;
# while that behavior might make sense logically, it's a poor user
# experience.)
observeEvent(choice_filter(), {
current_values <- input$filter_value
updateSelectInput(session, "filter_value",
choices = sort(unique(c(current_values, df()[choice_filter(),col_num,drop=TRUE]))),
selected = current_values
)
})
}
# Return a reactive that is a row index of selected rows, according to
# just this filter. If this filter shouldn't be taken into account
# because its col_num is too high, or if there are no values selected,
# just return TRUE to accept all rows.
reactive({
if (col_num > ncol(df())) {
TRUE
} else if (!isTruthy(input$filter_value)) {
TRUE
} else {
df()[,col_num,drop=TRUE] %in% input$filter_value
}
})
}
columnFilterSetUI <- function(id, maxcol, colwidth) {
ns <- NS(id)
fluidRow(
lapply(1:maxcol, function(i) {
column(colwidth,
columnFilterUI(ns(paste0("col", i)))
)
})
,actionButton(ns("clear_all_filters_button"), "clear")
)
}
columnFilterSet <- function(input, output, session, df, maxcol) {
# Each column filter needs to only display the choices that are
# permitted after all the OTHER filters have had their say. But
# each column filter must not take its own filter into account
# (hence we do filter[-col], not filter, in the reactive below).
create_choice_filter <- function(col) {
reactive({
filter_values <- lapply(filters[-col], do.call, args = list())
Reduce(`&`, filter_values, TRUE)
})
}
observeEvent(input$clear_all_filters_button, {
cat("clear", "\n")
filters <- lapply(1:maxcol, function(i) {
callModule(columnFilter, paste0("col", i), df= df, col_num =i, create_choice_filter(i), reset=T)
})
})
# filters is a list of reactive expressions, each of which is a
# logical vector of rows to be selected.
filters <- lapply(1:maxcol, function(i) {
callModule(columnFilter, paste0("col", i), df, i, create_choice_filter(i))
})
reactive({
# Unpack the list of reactive expressions to a list of logical vectors
filter_values <- lapply(filters, do.call, args = list())
# Combine all the logical vectors using & operator
selected_rows <- Reduce(`&`, filter_values, TRUE)
# Return the data frame, filtered by the selected rows
df()[selected_rows,]
})
}
ui <- fluidPage(
selectInput("dataset", "Dataset", c("mtcars", "pressure", "cars"), selected = "mtcars"),
columnFilterSetUI("filterset", maxcol = 4, colwidth = 3),
DT::dataTableOutput("table")
)
server <- function(input, output, session) {
selected_data <- reactive({
get(input$dataset, "package:datasets")
})
filtered_data <- callModule(columnFilterSet, "filterset", df = selected_data, maxcol = 4)
output$table <- DT::renderDataTable({ filtered_data() })
}
shinyApp(ui, server)