I have the following simple example, and I would like to reset the colour property of one of the circles to be red, as a separate process, after the renderer is initialised.
from bokeh.plotting import show
x = [2, 4, 8, 5, 9, 3]
y = [4, 8, 2, 7, 4, 6]
id = ['1001', '1002', '1003', '1004', '1005', '1006']
cds = ColumnDataSource(data={'x': x, 'y': y, 'id': id})
p = figure(width=300, height=200)
p.circle(x='x', y='y', source=cds, size=5, color='green')
# This is my issue?!
#p.circle[0].color = 'red'
show(p)
I'm aware that I can use the following API to achieve the result, but that is not an option considering what I would like to do next.
selected_circle = Circle(fill_alpha=1, fill_color="firebrick", line_color=None)
nonselected_circle = Circle(fill_alpha=0.2, fill_color="blue", line_color="firebrick")
If you want to change the color in a separate step, you can just hide the previous circle with a new one:
x = [2, 4, 8, 5, 9, 3]
y = [4, 8, 2, 7, 4, 6]
id_ = ['1001', '1002', '1003', '1004', '1005', '1006']
cds = ColumnDataSource(data={'x': x, 'y': y, 'id': id_})
p = figure(width=300, height=200)
p.circle(x='x', y='y', source=cds, size=5, color='green')
# Coordinate of the red circle that will hide the first one:
red_x = x[0]
red_y = y[0]
p.circle(x=red_x, y=red_y, size=5, color='red')
show(p)
But tbh I would prefer to specify the color from the beginning, like the option below.
x = [2, 4, 8, 5, 9, 3]
y = [4, 8, 2, 7, 4, 6]
id_ = ['1001', '1002', '1003', '1004', '1005', '1006']
color = ['red'] + ['green']*5 # add a color flag
cds = ColumnDataSource(data={'x': x, 'y': y, 'id': id_, 'color': color})
p = figure(width=300, height=200)
p.circle(x='x', y='y', size=5, source=cds, color='color')
show(p)
EDIT
In the example below, you can change the color of a circle with a button. It can be tested in a jupyter notebook.
# Modified to work with Bokeh (v3.2.0) and JupyterLab (v3.3.2)
from bokeh.layouts import column
from bokeh.models import ColumnDataSource, CheckboxButtonGroup, CustomJS
from bokeh.plotting import show, figure, output_notebook
import pandas as pd
output_notebook()
def create_plot(doc):
# create fake data
x = [2, 4, 8, 5, 9, 3]
y = [4, 8, 2, 7, 4, 6]
id_ = ['1001', '1002', '1003', '1004', '1005', '1006']
color = ['red'] + ['green']*5
df = pd.DataFrame({'x': x, 'y': y, 'ids': id_, 'color': color})
# create column data source
cds = ColumnDataSource(data=df)
# create figure
p = figure(width=300, height=200)
p.circle(x='x', y='y', size=5, source=cds, color='color')
# Create widget (checkbox button)
checkbox_button_group = CheckboxButtonGroup(labels=id_, active=[0])
# Update the colors after a click on an id
checkbox_button_group.js_on_change("active", CustomJS(code="""
console.log('checkbox_button_group: active=' + this.active, this.toString())
"""))
def set_col(row, red_ids):
color = 'red' if row in red_ids else 'green'
return color
def update_data(df, red_ids=None):
if red_ids is None:
red_ids = []
df['color'] = df['ids'].apply(lambda x: set_col(x, red_ids))
cds.data = df
def update(attr, old, new):
red_ids = [checkbox_button_group.labels[i] for i in checkbox_button_group.active]
update_data(df, red_ids)
checkbox_button_group.on_change('active', update)
# display button & plot in a column
doc.add_root(column(checkbox_button_group, p))
show(create_plot, notebook_url="localhost:8891")