Reputation: 828
I have a dataset and am building a shiny flexdashboard with multiple user inputs which filter the data down to a subset. I am struggling with just one of the filters, where if the user chooses 'ALL' in selectInput
, I want that filter function not to do anything and just return the data as is. Below is one of my attempts:
library(flexdashboard)
library(DT)
library(lubridate)
library(readr)
library(tidyverse)
...
qry <- read_file("some_query.sql")
Data_df <- con %>% tbl(sql(qry)) %>% collect()
doctors_to_choose <- unique(pull(Data_df, 'Doctor')) %>%append('ALL')
Column {data-width=200 .sidebar}
-----------------------------------------------------------------------
```{r}
checkboxGroupInput("drug_classes",
label = "Choose the classes of drugs",
choices = c("II", "III", "IV", "V"),
selected = c("V"),
)
selectInput(
inputId="chosen_doctor",
label="Choose Doctor",
choices=doctors_to_choose,
selected = "ALL",
multiple = FALSE,
size = NULL
)
show_data_df <- reactive({
Data_df %>%
filter(`Drug Class` %in% input$drug_classes) %>%
{if (input$chosen_doctor != "ALL") filter(Doctor == input$chosen_doctor )
else filter(`Drug Class` %in% input$drug_classes) }
} )
```
I tried to use an if-else statement as above but failed. because In the original code, I have a long list of filters applied so ideally I would like to use something that does not require me to retype all the previous filters/actions like I did in the else part above.
Upvotes: 0
Views: 269
Reputation: 12461
@TimTeaFan has given you a very good answer. I am not suggesting you should change your acceptance of his answer.
In response to your question in comment about placeholders, here's a demonstration of the technqiue. I've used Shiny rather than flexdashboard because it's easier to see changes in action, but the principle will carry over into dashboard directly. Also, because I don't have access to your input data, I've used mtcars
as a data source.
The method I've demonstrated works for any number of potential filters without the need to retype any of the filter code.
And to answer your direct question: yes, I did mean ""
. That was something I didn't notice when using an unfamiliar keyboard.
library(shiny)
library(tidyverse)
cylChoices <- c("", sort(unique(mtcars$cyl)))
names(cylChoices) <- c("- All -", sort(unique(mtcars$cyl)))
gearChoices <- c("", sort(unique(mtcars$gear)))
names(gearChoices) <- c("- All -", sort(unique(mtcars$gear)))
ui <- fluidPage(
selectInput(
"cylCount",
"Cylinder count:",
multiple=TRUE,
selected="- All -",
choices=cylChoices
),
selectInput(
"gearCount",
"Gear count:",
multiple=TRUE,
selected="- All -",
choices=gearChoices
),
tableOutput("table")
)
server <- function(input, output, session) {
filteredData <- reactive({
df <- as_tibble(mtcars, rownames="Model")
if (!is.null(input$gearCount)) df <- df %>% filter(gear %in% input$gearCount)
if (!is.null(input$cylCount)) df <- df %>% filter(cyl %in% input$cylCount)
df
})
output$table <- renderTable({ filteredData() })
}
shinyApp(ui, server)
Upvotes: 1
Reputation: 18541
One option is to use purrr::when
to apply a case_when
like statement within the pipe logic for data.frame
s:
library(dplyr)
library(purrr)
Data_df %>%
filter(`Drug Class` %in% input$drug_classes) %>%
when(input$chosen_doctor != "ALL" ~ filter(., Doctor == input$chosen_doctor),
TRUE ~ filter(., `Drug Class` %in% input$drug_classes))
Upvotes: 0