View/filter ergonomics clunky #12668
Replies: 5 comments 2 replies
-
gf.group = cb_obj.value
view.setv({filter: gf}, {check_eq: false}) However, given that all the filters are manipulated only in JS, then perhaps it would have been easier to just construct them in JS, i.e.: select.js_on_change("value", CustomJS(args=dict(view=view, column_name="species"), code="""
const AllIndices = Bokeh.Models.get("AllIndices")
const GroupFilter = Bokeh.Models.get("GroupFilter")
const {value} = cb_obj
if (value == "All") {
view.filter = new AllIndices()
} else {
view.filter = new GroupFilter({column_name, group: value})
}
""")) Though currently importing bokeh's models is a bit tedious, but nothing that can't be improved.
What did previously
I think that select.js_on_change("value", CustomJS(args=dict(view=view), code="""
view.filter.group = cb_obj.value
""")) |
Beta Was this translation helpful? Give feedback.
-
I'm not sure you are suggesting as much, but FWIW just to be clear I think this level of internal detail is fairly unreasonable for users to have to know about. And I think the "import and create filter objects" is too much code to expect for what should be a very simple operation due to its common-ness.
Why? A filter is not a list of indices, a filter is a thing that produces a list of indices that are a subset of a previous list of indices. I agree that whether the list was a union or an intersection was up to convention, and that's not great. But an empty list has a clear meaning to me: there are no filters to apply to the original list of indices. I understand how re: select.js_on_change("value", CustomJS(args=dict(view=view), code="""
view.filter.group = cb_obj.value
""")) I forgot that labels and values can differ for select.js_link('value', filter, 'group') That, I think would be ideal. As an aside I do actually still think that
|
Beta Was this translation helpful? Give feedback.
-
@mattpap BTW what is your proposal for "group subsets"? Would you change |
Beta Was this translation helpful? Give feedback.
-
I have a few thoughts. First, a question: if I were to say put two GroupFilters on a view:
Internally, is src being iterated through twice to apply the filters? Thought 1: to throw another suggestion/idea out there, maybe modifying GroupFilter to accomodate a list of groups or a singular group would greatly improve its usability. @bryevdv 's example would become a bit less janky, more flexible, and more straightforward (to me at least):
It would also become intuitively obvious that GroupFilter is the best filter for multiselect widgets (e.g. CheckboxGroups etc,) callbacks would just have retrieve the selected groups and update the filter's group property to that. Thought number 2: In general my user experience with filters has been to avoid putting more than one filter on a view as I inevitably end up being slayed by unpredictable rerender behaviour (unpredictable to me the humble user at least). I have been confounded by this many times, see #7273 , https://discourse.bokeh.org/t/filtering-cdsviewing-streaming/9359 , and this https://discourse.bokeh.org/t/understanding-change-emit-with-filters-sources-glyphs/7070/2 . So in general my approach has been when in doubt, make an IndexFilter, make it the only filter on the view, and update its indices property in CustomJS according to the state of all widgets etc. This is not what you're trying to bring to the table (I have to write a lot of CustomJS etc), but I inevitably find it's the only thing that works consistently, and if the answer to my first question about iterating through the dataset twice is "yes", then it's more computationally efficient. |
Beta Was this translation helpful? Give feedback.
-
Yes. Every filter works independently. |
Beta Was this translation helpful? Give feedback.
-
I was prompted by this question: https://discourse.bokeh.org/t/best-way-to-use-widgets-in-jupyter-notebooks-in-2022-2023/9828 to try and create a simple example that filtered based on a Select, and was not happy with the result:
view.filter = af
hack. I tried at least a half a dozen other ways withemit
, etc. The problem is that in that branch sometimes the view is assigned a new value, and sometimes only the group is assigned a new value but the code has to happen in one order.AllIndicies
to mean "empty filter" (and thus also be forced to manually manage the group filter too) is very clunky and tedious. This is whyfilters
was nice in the past — an empty list meant "no filtering".So, questions:
E.g. group filter group could be None to indicate "no filter" and
js_link
could get and optionalmap
arg, then perhaps theCustomJS
could be avoided entirely:As an aside I also think that the group filter only accepting one group is also super clunky. I guess the idea is that users use
UnionFilter
for everything? That is really very over-verbose. But maybe even with that, amap
param would go a long way:But now users have to create N group filters up front instead of just setting one group filters
group
. Still seems like a lot of work for users to just be able to filter data based on a select. Anyway, ideas welcome.cc @bokeh/dev
Beta Was this translation helpful? Give feedback.
All reactions