Select - CustomJS - columndatasource - Filter

Hello, I am new to Bokeh and find it very interesting for my daily work. I have a small query.

I am currently using Bokeh Layout with 15 plots (kind of dashboard) and all the plots are coming from same columndatasource (different columns of panda dataframe).

My query : is there a way I can filter the whole columndatasource using customJS at once based on the input from Select Widget. as shown below

callback1 =  CustomJS(args=dict( cds_target1=cds_target,
                                cds_all_gB=cds_all_gB, cds_gB=cds_gB), code="""
                     var cds_target = cds_target1.data;
                     var cds_all_gB = cds_all_gB.data;
                     var cds_gB = cds_gB.data;        
                     
                     if(cb_obj.value=="All"){
                            cds_target = cds_all_gB;
                             }
                    else{
                           cds_target = ***cds_gB[cds_gB['xxxx']==cb_obj.value];***
                                                                          
                            }
                    console.log(cds_target)
                    cds_target1.change.emit();
                      """);

Please note that, I am already able to implement the same by using - For loop, iterating through rows, pushing the filtered data and source.change.emit().

But with large source (with many columns) my customJS function is becoming larger and larger.

If I could filter the columndatasource level based on select input something like I mentioned above will be of great help.

You could try using CDSView in this case:

https://docs.bokeh.org/en/latest/docs/user_guide/data.html#filtering-data

You would configure the glyphs with the same view then update the view in the callback.

But please be aware that CDSView may not play nicely with every combination of other features. You will have to try it in your specific use-case and see if it works for you.

Hello Bryan,

Could you share me an example of how to pass GroupFilter and CDSView to CustomJS. Or some instructions how it works

Because i did use CDSView as suggested. However, the glyphs are not updating and I could see below message in the console log
[bokeh] group filter: group ‘xxx’ did not match any values in column 'yyyy’

I am not sure…if i also need to update the source/am i mssing something??

Thanks Koti

@koti_maddala View can be passed to CustomJS in exactly the same way you are passing other things already, i.e as keys/values in the args dict.

The warning message you are seeing means that the column you are asking Bokeh to extract a specific group from doe does not have any values of that group. I in the docs e.g. there is an example that does this with the “iris” data set:

GroupFilter(column_name='species', group='versicolor')]

That says to return a view for all the indices corresponding to “versicolor” values in the “species” column. Now imagine changing to

GroupFilter(column_name='species', group='fasdfasdfasd')]

That will trigger the same warnign you are seeing, because the “species” column has no elements with the value “fasdfasdfasd” anywhere in it. You are asking Bokeh to return a group that does not exist. That said this is just a warning message, Bokeh will still return the empty view.

It’s not really possible to speculate more without some concrete details, e.g. actual code and data to reproduce what you are seeing.

Hello Bryan,

Below is the code that I am working on. As suggested by you, it is working as expected. However, it is working for circle,triangle,square. But not for line graph :frowning: . With line graph it doesnt show any thing and when i hove it shows hover tips (with un-filtered values)

cds_target = ColumnDataSource(cf_all_gB)
cds_all_gB = ColumnDataSource(cf_all_gB)
cds_xxx_gB = ColumnDataSource(cf_xxx_gB)

group_filter = GroupFilter(column_name=‘XXX’, group=‘All’)
view_all = CDSView(source = cds_target, filters = [group_filter])

p2.circle(x = ‘date_time’,y = ‘pmPdcpPktFwdDl’,line_width=2, source=cds_target, view=view_all)

callback1 = CustomJS(args=dict(cds_target1=cds_target,
cds_all_gB=cds_all_gB,
cds_xxx_gB=cds_xxx_gB,
view_all=view_all,
), code="""
var cds_target = cds_target1.data;
var cds_all_gB = cds_all_gB.data;
var cds_xxx_gB = cds_xxx_gB.data;
var view_all = view_all;

                 if(cb_obj.value=="All"){
                        view_all.source.data = cds_all_gB;
                        cds_target = cds_all_gB;
                        view_all.filters[0].column_name = 'XXX';
                        view_all.filters[0].group = 'All';
                         }
                else{
                        view_all.source.data = cds_xxx_gB;
                        cds_target = cds_xxx_gB;
                        view_all.filters[0].column_name = 'xxx';
                        view_all.filters[0].group = cb_obj.value;                                                                        
                        }

                view_all1.source.change.emit();
                cds_target1.change.emit();
                
                  """);

I didn’t realize you had line glyphs (or I could have saved you some trouble up front). CDSView is not useful/compatible with line glyphs. Due to their connected topology, line glyphs would need much more complicated logic added to handle partial internal segments with gaps, which would intersect with already very complicated logic for hit testing and decimation, and this work has never been undertaken.

[quote=“Bryan, post:2, topic:4047”]

hmmm…But its interesting that it is working with all other glyphs like vbar/step…but not with Line glyphs.

So the only method is to iterate through the rows one by one?

I explained exactly why this is the case above. Line glyphs are more complicated and different from every other glyph due to their connectedness between points, and the extra work for this special case has not ever been done by anyone.

So the only method is to iterate through the rows one by one?

It sounds like you you want a connected line segment to “straddle” any gaps left by filtered-out points? They you should definitely do things yourself “by hand” beause if/when support is added to Bokeh for lines and CDSView, thing will not behave in this way. Built-in bokeh support would break lines in to disconnected pieces leaving gaps where points are filtered out.