Reputation: 11
I have my data set up similar to the fruits example below. I have been trying to add a slider that controls for example the year '2015' and when I change the slider value, the stacked chart updates according to this new value.
Example:
Current value: 2015:[2, 1, 4, 3, 2, 4]
Slider value: 2
New value = Current value + slider value
---> 2015: [4,3,6,5,4,6]
Slider value:0
---> 2015:[2, 1, 4, 3, 2, 4]
(back to original value)
I hope someone can help me.
Thank you!
from bokeh.palettes import GnBu3, OrRd3
output_notebook()
years = ['2015', '2016', '2017']
exports = {'fruits' : fruits,
'2015' : [2, 1, 4, 3, 2, 4],
'2016' : [5, 3, 4, 2, 4, 6],
'2017' : [3, 2, 4, 4, 5, 3]}
p = figure(x_range=fruits, plot_height=250, y_range=(0, 16), title="Fruit import/export, by year")
p.vbar_stack(years, x='fruits', width=0.9, color=GnBu3, source=ColumnDataSource(exports))
p.x_range.range_padding = 0.1
p.xgrid.grid_line_color = None
slider = Slider(start=0, end=5, value=0, step=1, title="2015 exports")
show(column(p,slider))
Upvotes: 0
Views: 229
Reputation: 11
Here's a solution that works by replacing the whole object.
def plot_stack_slider():
years = ['2015', '2016', '2017']
fruits = ['Apples', 'Pears', 'Nectarines', 'Plums', 'Grapes', 'Strawberries']
exports = {'fruits' : fruits,
'2015' : [2, 1, 4, 3, 2, 4],
'2016' : [5, 3, 4, 2, 4, 6],
'2017' : [3, 2, 4, 4, 5, 3]
}
source = ColumnDataSource(data={
'fruits' : fruits,
'2015' : [2, 1, 4, 3, 2, 4],
'2016' : [5, 3, 4, 2, 4, 6],
'2017' : [3, 2, 4, 4, 5, 3]
})
display = ColumnDataSource(data={'fruits' : fruits,
'2015' : [2, 1, 4, 3, 2, 4],
'2016' : [5, 3, 4, 2, 4, 6],
'2017' : [3, 2, 4, 4, 5, 3]
})
p = figure(x_range=fruits, plot_height=250, y_range=(0, 16), title="Fruit import/export, by year")
p.vbar_stack(years, x='fruits', width=0.9, color=GnBu3, source=display)
# p.Bar(test_display,fruits,stacked=True)
p.x_range.range_padding = 0.1
p.xgrid.grid_line_color = None
slider = Slider(start=0, end=5, value=0, step=1, title="2015 exports")
slider2 = Slider(start=0, end=5, value=0, step=1, title="2016 exports")
callback = CustomJS(
args=dict(source=source, display=display, slider=slider, slider2=slider2),
code="""
display.data = {
...source.data,
'2015': source.data['2015'].map((c) => c + slider.value ),
'2016': source.data['2016'].map((c) => c + slider2.value ),
};
""")
slider.js_on_change('value', callback)
slider2.js_on_change('value', callback)
show(column(p,slider, slider2))
plot_stack_slider()
Upvotes: 1
Reputation: 6337
This should be possible with a CustomJS
block and an aditional row to store the original value.
from bokeh.plotting import figure, show, output_notebook
from bokeh.models import CustomJS,ColumnDataSource, Slider
from bokeh.layouts import column
from bokeh.palettes import GnBu3, OrRd3
output_notebook()
years = ['2015', '2016', '2017']
fruits = ['Apples', 'Pears', 'Nectarines', 'Plums', 'Grapes', 'Strawberries']
exports = {'fruits' : fruits,
'2015' : [2, 1, 4, 3, 2, 4],
'2015_org' : [2, 1, 4, 3, 2, 4],
'2016' : [5, 3, 4, 2, 4, 6],
'2017' : [3, 2, 4, 4, 5, 3]
}
source = ColumnDataSource(exports)
p = figure(x_range=fruits, plot_height=250, y_range=(0, 16), title="Fruit import/export, by year")
p.vbar_stack(years, x='fruits', width=0.9, color=GnBu3, source=source)
p.x_range.range_padding = 0.1
p.xgrid.grid_line_color = None
slider = Slider(start=0, end=5, value=0, step=1, title="2015 exports")
callback = CustomJS(
args=dict(source=source, slider=slider),
code="""
let y = source.data['2015'];
let y_org = source.data['2015_org']
for (let i = 0; i < y.length; i++) {
y[i] = y_org[i] + slider.value
}
source.change.emit();
""")
slider.js_on_change('value', callback)
show(column(p,slider))
Upvotes: 0