Skip to content

Instantly share code, notes, and snippets.

@rothnic
Last active May 20, 2019 13:34
Show Gist options
  • Save rothnic/18371807da60b288166f to your computer and use it in GitHub Desktop.
Save rothnic/18371807da60b288166f to your computer and use it in GitHub Desktop.
Example Bokeh app that swaps axis and range out dynamically
from bokeh.models import GlyphRenderer, ColumnDataSource
from bokeh.models.plots import Plot
from bokeh.models import Circle, Range1d, LinearAxis, CategoricalAxis, Axis, FactorRange
from bokeh.models.widgets import HBox, VBoxForm, Select
from bokeh.io import curdoc
data = {'a': [1, 2, 3, 4],
'b': [3, 5, 4, 5],
'c': ['foo', 'bar', 'foo', 'bar']}
col_names = list(data.keys())
# because dimensions and attributes of chart are modeled, this could be auto generated
x_select = Select(
title='x', name='x_select',
options=col_names, value='a'
)
y_select = Select(
title='y', name='y_select',
options=col_names, value='b'
)
x_range = Range1d(start=0, end=10)
y_range = Range1d(start=0, end=10)
x_range_cat = FactorRange(factors=data['c'])
y_range_cat = FactorRange(factors=data['c'])
x_axis = LinearAxis()
y_axis = LinearAxis()
x_axis2 = CategoricalAxis()
y_axis2 = CategoricalAxis()
plot = Plot(x_range=x_range, y_range=y_range)
plot.add_layout(x_axis, 'below')
plot.add_layout(y_axis, 'left')
ds = ColumnDataSource(data)
glyph = Circle(x='a', y='b')
renderer = GlyphRenderer(data_source=ds, glyph=glyph)
plot.renderers.append(renderer)
selectors = [x_select, y_select]
inputs = VBoxForm(children=selectors)
hbox = HBox(children=[inputs, plot])
def update_data():
new_renderers = []
for renderer in plot.renderers:
if not isinstance(renderer, Axis):
new_renderers.append(renderer)
plot.renderers = new_renderers
plot.below = []
plot.left = []
if x_select.value == 'c':
this_x_axis = x_axis2
this_x_range = x_range_cat
else:
this_x_axis = x_axis
this_x_range = x_range
if y_select.value == 'c':
this_y_axis = y_axis2
this_y_range = y_range_cat
else:
this_y_axis = y_axis
this_y_range = y_range
this_y_axis.plot = None
this_x_axis.plot = None
plot.add_layout(this_x_axis, 'below')
plot.add_layout(this_y_axis, 'left')
plot.x_range = this_x_range
plot.y_range = this_y_range
glyph.x = x_select.value
glyph.y = y_select.value
def input_change(attrname, old, new):
update_data()
for selector in selectors:
selector.on_change('value', input_change)
curdoc().add_root(hbox)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment