shinyfilters creates shiny inputs for filtering data. This article
uses nyc_flights, a sample of flights that left New York
City in 2013.
Filters from a data frame
shinyfilters() turns a data frame into a set of
filters.
filters <- shinyfilters(nyc_flights)Printing it shows the input each column gets:
filters
#> <shinyfilters> • 7 filters
#>
#> Filters
#> date <date> dateRangeInput
#> carrier <chr> selectizeInput
#> origin <fct> selectizeInput
#> dest <chr> selectizeInput
#> dep_delay <dbl> sliderInput
#> distance <dbl> sliderInput
#> delayed <lgl> selectizeInputCustomizing filters
You can customize these settings on a shinyfilters
object:
- A filter’s input function
- The values used to create and update the input function
- Add a namespace
Change a filter’s input function
- Set an argument of
shinyfilters():
shinyfilters(nyc_flights, range = TRUE)
#> <shinyfilters> • 7 filters
#>
#> Filters
#> date <date> dateRangeInput
#> carrier <chr> selectizeInput
#> origin <fct> selectizeInput
#> dest <chr> selectizeInput
#> dep_delay <dbl> sliderInput
#> distance <dbl> sliderInput
#> delayed <lgl> selectizeInput- Use
with_defaults():
filters |> with_defaults(range = TRUE)
#> <shinyfilters> • 7 filters
#>
#> Filters
#> date <date> dateRangeInput
#> carrier <chr> selectizeInput
#> origin <fct> selectizeInput
#> dest <chr> selectizeInput
#> dep_delay <dbl> sliderInput
#> distance <dbl> sliderInput
#> delayed <lgl> selectizeInput- Use
with_filters():
filters |> with_filters(date = "range")
#> <shinyfilters> • 7 filters
#>
#> Filters
#> ● date <date> dateRangeInput
#> carrier <chr> selectizeInput
#> origin <fct> selectizeInput
#> dest <chr> selectizeInput
#> dep_delay <dbl> sliderInput
#> distance <dbl> sliderInput
#> delayed <lgl> selectizeInput
#>
#> ● Filter set by `with_filters()`See vignette("shinyfilters-catalog") for the full list
of input functions available in shinyfilters.
Change a filter’s arguments
- Use
with_args():
filters |>
with_args(dep_delay ~ list(value = range(.x)))
#> <shinyfilters> • 7 filters
#>
#> Filters
#> date <date> dateRangeInput
#> carrier <chr> selectizeInput
#> origin <fct> selectizeInput
#> dest <chr> selectizeInput
#> dep_delay <dbl> sliderInput
#> value = range(.x, na.rm = TRUE)
#> distance <dbl> sliderInput
#> delayed <lgl> selectizeInput- Use
with_filters():
filters |>
with_filters(dep_delay ~ list(value = range(.x)))
#> <shinyfilters> • 7 filters
#>
#> Filters
#> date <date> dateRangeInput
#> carrier <chr> selectizeInput
#> origin <fct> selectizeInput
#> dest <chr> selectizeInput
#> dep_delay <dbl> sliderInput
#> value = range(.x, na.rm = TRUE)
#> distance <dbl> sliderInput
#> delayed <lgl> selectizeInput- Choose the input and set its arguments together:
filters |>
with_filters(dep_delay ~ "slider" ~ list(value = range(.x)))
#> <shinyfilters> • 7 filters
#>
#> Filters
#> date <date> dateRangeInput
#> carrier <chr> selectizeInput
#> origin <fct> selectizeInput
#> dest <chr> selectizeInput
#> ● dep_delay <dbl> sliderInput
#> value = range(.x, na.rm = TRUE)
#> distance <dbl> sliderInput
#> delayed <lgl> selectizeInput
#>
#> ● Filter set by `with_filters()`
filters |>
with_filters(dep_delay ~ sliderInput ~ list(value = range(.x)))
#> <shinyfilters> • 7 filters
#>
#> Filters
#> date <date> dateRangeInput
#> carrier <chr> selectizeInput
#> origin <fct> selectizeInput
#> dest <chr> selectizeInput
#> ● dep_delay <dbl> sliderInput
#> value = range(.x, na.rm = TRUE)
#> distance <dbl> sliderInput
#> delayed <lgl> selectizeInput
#>
#> ● Filter set by `with_filters()`Change multiple filters together
- Set multiple filters inside
with_filters():
filters |>
with_filters(
dep_delay ~ list(value = range(.x)),
distance = 1.609344 * distance
)
#> <shinyfilters> • 7 filters
#>
#> Filters
#> date <date> dateRangeInput
#> carrier <chr> selectizeInput
#> origin <fct> selectizeInput
#> dest <chr> selectizeInput
#> dep_delay <dbl> sliderInput
#> value = range(.x, na.rm = TRUE)
#> ^ distance <dbl> sliderInput
#> delayed <lgl> selectizeInput
#>
#> ^ Filter replaced by `with_filters()`Use a namespace
- Set the
nsargument ofshinyfilters():
shinyfilters(nyc_flights, ns = "sidebar-mod")
#> <shinyfilters> • 7 filters • namespace "sidebar-mod"
#>
#> Filters
#> date <date> dateRangeInput
#> carrier <chr> selectizeInput
#> origin <fct> selectizeInput
#> dest <chr> selectizeInput
#> dep_delay <dbl> sliderInput
#> distance <dbl> sliderInput
#> delayed <lgl> selectizeInput- Use
with_ns():
filters |>
with_ns("sidebar-mod")
#> <shinyfilters> • 7 filters • namespace "sidebar-mod"
#>
#> Filters
#> date <date> dateRangeInput
#> carrier <chr> selectizeInput
#> origin <fct> selectizeInput
#> dest <chr> selectizeInput
#> dep_delay <dbl> sliderInput
#> distance <dbl> sliderInput
#> delayed <lgl> selectizeInputUse a non-shiny input function
- Use a shinyWidgets input in
with_filters(). It comes with the function that updates it:
library(shinyWidgets)
filters |>
with_filters(dest = pickerInput)
#> <shinyfilters> • 7 filters
#>
#> Filters
#> date <date> dateRangeInput
#> carrier <chr> selectizeInput
#> origin <fct> selectizeInput
#> ● dest <chr> pickerInput
#> .update_fn = updatePickerInput {shinyWidgets}
#> dep_delay <dbl> sliderInput
#> distance <dbl> sliderInput
#> delayed <lgl> selectizeInput
#>
#> ● Filter set by `with_filters()`- For an input from anywhere else, name the function that updates it
with
.update_fn:
filters |>
with_filters(
origin ~ shiny::checkboxGroupInput ~
list(.update_fn = shiny::updateCheckboxGroupInput)
)
#> <shinyfilters> • 7 filters
#>
#> Filters
#> date <date> dateRangeInput
#> carrier <chr> selectizeInput
#> ● origin <fct> checkboxGroupInput {shiny}
#> .update_fn = updateCheckboxGroupInput {shiny}
#> dest <chr> selectizeInput
#> dep_delay <dbl> sliderInput
#> distance <dbl> sliderInput
#> delayed <lgl> selectizeInput
#>
#> ● Filter set by `with_filters()`Selecting filters
After creating your filters, you can select multiple filters or a single filter, allowing you to place the filters anywhere in an application
Select multiple filters
- Use
[:
filters[-c(carrier, origin)]
#> <shinyfilters> • 5 filters
#>
#> Filters
#> date <date> dateRangeInput
#> dest <chr> selectizeInput
#> dep_delay <dbl> sliderInput
#> distance <dbl> sliderInput
#> delayed <lgl> selectizeInput- Use
[with <[tidy-select][tidyselect::language]>:
library(tidyselect)
filters[starts_with("d")]
#> <shinyfilters> • 5 filters
#>
#> Filters
#> date <date> dateRangeInput
#> dest <chr> selectizeInput
#> dep_delay <dbl> sliderInput
#> distance <dbl> sliderInput
#> delayed <lgl> selectizeInput- Select and create with
[[:
filters[[c(carrier, origin)]]Use in a shiny app
UI
You can place the filters directly inside a UI.
library(bslib)
library(DT)
library(shiny)
ui <- page_sidebar(
sidebar = sidebar(
filters
),
DTOutput("data")
)Organizing
To organize filters, you can select them individually or by group.
library(bslib)
library(DT)
library(shiny)
ui <- page_sidebar(
sidebar = sidebar(
filters[date],
accordion(
accordion_panel(
"Airports",
filters[[c(origin, dest)]]
),
accordion_panel(
"Time",
filters[[contains("delay")]]
),
accordion_panel(
"Other",
filters[[!c(date, origin, dest, contains("delay"))]]
)
)
),
DTOutput("data")
)Server
In the server, use shinyfilters_server() to enable
interdependency:
server <- function(input, output, session) {
sidebar <- shinyfilters_server(filters)
output$data <- renderDT(datatable(sidebar$filtered))
}Notes
Bookmarking
Apps that use bookmarking need filterInput(filters)
inside their UI function instead, so the inputs restore their bookmarked
values. Placing filters in their UI directly is an
error.
Custom objects
If you’re filtering a custom object, you may need to extend
shinyfilters. See vignette("extending-shinyfilters") for
details.