How to activate the click_policy for group legends

Hi,

I think I might have asked this question before. I added the legend.click_policy as hide in the example below. If the user wants to hide one of the legend items. Not entirely sure if this was possible for circle method. Is there a way to be able to do it for p.circle of I might need to create a glyph?
Can anyone direct me to an example?

from bokeh.io import show
from bokeh.models import ColumnDataSource
from bokeh.palettes import RdBu3
from bokeh.plotting import figure

c1 = RdBu3[2] # red
c2 = RdBu3[0] # blue
source = ColumnDataSource(dict(
    x=[1, 2, 3, 4, 5, 6],
    y=[2, 1, 2, 1, 2, 1],
    color=[c1, c2, c1, c2, c1, c2],
    label=['hi', 'lo', 'hi', 'lo', 'hi', 'lo']
))

p = figure(x_range=(0, 7), y_range=(0, 3), height=300, tools='save')

# legend field matches the column in the source
p.circle( x='x', y='y', radius=0.5, color='color', legend_group='label', source=source)
p.legend.click_policy="hide"

show(p)

Unfortunately (as far as I know, happy to be corrected as this would help me a lot too), the legend grouping does not provide the ability to “filter” the data if it’s all within the same ColumnDataSource. So in the example you posted, you can only toggle the entire source on/off with the legend.

The workaround is to make multiple renderers from multiple datasources. Note that all the dictionary work (i.e. “p_dict”) is a practice I like to use to be able to have quick/convenient access to all the stuff I may need to manipulate via CustomJS for additional features etc. → it’s not necessary for this little sandbox example but has helped me in the long run.

from bokeh.io import show
from bokeh.models import ColumnDataSource
from bokeh.palettes import RdBu3
from bokeh.plotting import figure

#using pandas as a crutch for iteration purposes
import pandas as pd



c1 = RdBu3[2] # red
c2 = RdBu3[0] # blue

#make a dataframe of the data
df = pd.DataFrame(dict(
    x=[1, 2, 3, 4, 5, 6],
    y=[2, 1, 2, 1, 2, 1],
    color=[c1, c2, c1, c2, c1, c2],
    label=['hi', 'lo', 'hi', 'lo', 'hi', 'lo']
    ))

#making a dictionary storing everything for convenience/access
p_dict = {}

p = figure(x_range=(0, 7), y_range=(0, 3), height=300, tools='save')
#iterate through the unique legend items (in this case, just the two colors), and create a unique source and renderer for it
for i,c in enumerate(df['color'].unique()):
    p_dict[i] = {}
    p_dict[i]['src'] = ColumnDataSource(df[df['color']==c])
    p_dict[i]['rend'] = p.scatter(x='x', y='y', radius=0.5, color='color', legend_group='label',marker='circle', source=p_dict[i]['src'])

p.legend.click_policy='hide'
    
show(p)

Edit: Also as an aside, circle has been deprecated and scatter (with a marker arg) should be used.

2 Likes