Closed Jeff-Thompson12 closed 1 year ago
@AARON-CLARK what do you think of the approach outlined in this PR?
Things I like about it:
{tidyverse}
creates function mappers, so I think it will be intuitive for users (i.e. a user can specify function(x) x <= 100
or ~.x <= 100
)Things I don't like:
verbose
which makes the functions not as backwards compatible as I would like. This issue feels fairly unavoidable though.~ .x <= 100
might result with x <= 90
if 90 is the largest number less than or equal to 100)Here's a snippet to see the preselection in action:
ui <- fluidPage(
titlePanel("Filter Data Example"),
fluidRow(
column(8,
verbatimTextOutput("data_summary"),
verbatimTextOutput("data_filter_code")),
column(4, IDEAFilter::shiny_data_filter_ui("data_filter"))))
srv <- function(input, output, session) {
filtered_data <- callModule(
IDEAFilter::shiny_data_filter,
"data_filter",
data = airquality,
preselection = list(Ozone = list(filter_na = TRUE, filter_fn = ~.x <= 100),
Solar.R = list()),
verbose = FALSE)
output$data_filter_code <- renderPrint({
cat(gsub("%>%", "%>% \n ",
gsub("\\s{2,}", " ",
paste0(
capture.output(attr(filtered_data(), "code")),
collapse = " "))
))
})
output$data_summary <- renderPrint({
if (nrow(filtered_data())) show(filtered_data())
else "No data available"
})
}
shinyApp(ui, srv)
Why can't it be last? so it doesn't introduce breaking changes to users who may not be specifying the arg name with the module call?
It can be last. In my mind the verbose
argument makes sense as the last value, but at this point new arguments should be added to the end of functions already being exported.
I was playing around with the starwars example app in our
inst/
folder by adding the following code:filtered_data <- callModule( shiny_data_filter, "data_filter", data = starwars2, preselection = list(name = list(filter_na = TRUE, filter_fn = ~stringr::str_detect(.x, '[0-9]')), eye_color = list(filter_na = TRUE, filter_fn = ~ c("yellow","red") %in% .x), Solar.R = list()), verbose = FALSE)
I did notice that my filter on
eye_color
didn't really work. For some reason, it's still including "black" eye colors.
So I noticed that your filter is backwards (i.e. you have c("yellow", "red") %in% .x
instead of .x %in% c("yellow", "red")
). This is causing Filter()
to apply a logical vector of length 12 instead of 6 giving the bizarre results. I can't decide if this is a problem for the PR thought because R is behaving in the expected way.
Yes, it is slightly confusing if your a developer and you think your filtering to < 100. It's a shame the generated code doesn't reflect the
filter_fn
. Do you think it could some how?
Not really. I was going down that route at the start, but then you have to account for the different methods. We could allow for other arguments (e.g. if a user provides a max
or range
value it supersedes filter_fn
), but that type of processing is not very intuitive.
Plus since the filter has a waterfall type affect, you couldn't force the values anyways. I think the main thing is that the filtering code is meant to be reproducible on the same dataset, not across datasets.
Addresses #13