Bokeh Slider Stacked Bar Chart

非 Y 不嫁゛ 提交于 2021-02-11 14:41:23

问题


I want to be able to only show the initial top 3 bars and then show more or less bars using the slider. I don't know if this is possible using the slider widget of bokeh or if there is a better method.

from bokeh.models.widgets import Slider
from bokeh.layouts import widgetbox, column
from bokeh.models import CustomJS, Slider


fruits = ['Apples', 'Pears', 'Nectarines', 'Plums', 'Grapes', 'Strawberries']
years = ["2015", "2016", "2017"]
colors = ["#c9d9d3", "#718dbf", "#e84d60"]

data = {'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=data)

p = figure(x_range=fruits, plot_height=350, title="Fruit Counts by Year",
           toolbar_location=None, tools="")

p.vbar_stack(years, x='fruits', width=0.9, color=colors, source=source,
                         legend=[value(x) for x in years], name=years)

callback = CustomJS(args=dict(source = source), code="""
var data = source.data;
var start = slider.value;
var x = data['OOC_EQP'];
x_range.setv({"start":start, "end":start+10});
""")

p.y_range.start = 0
p.x_range.range_padding = 0.1
p.xgrid.grid_line_color = None
p.axis.minor_tick_line_color = None
p.outline_line_color = None
p.legend.location = "top_left"
p.legend.orientation = "horizontal"

slider = Slider(start=1, end=6, value=3, step=1, title="Range")
callback.args["slider"] = slider

layout = column(p, widgetbox(slider))

show(layout)

回答1:


I don't see a need to use javascript callback here. A native python on_change function can be used here. The function will change the x-axis range without changing any back-end data, and will be really fast -

from bokeh.models.widgets import Slider
from bokeh.layouts import widgetbox, column
from bokeh.models import Slider, ColumnDataSource
from bokeh.plotting import figure, curdoc
from bokeh.core.properties import value
from bokeh.models.ranges import FactorRange


fruits = ['Apples', 'Pears', 'Nectarines', 'Plums', 'Grapes', 'Strawberries']
years = ["2015", "2016", "2017"]
colors = ["#c9d9d3", "#718dbf", "#e84d60"]

data = {'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=data)

## Note [0:3] for first 3 fruits only in default graph
p = figure(x_range=fruits[0:3], plot_height=350, title="Fruit Counts by Year",
           toolbar_location=None, tools="")

renderers= p.vbar_stack(years, x='fruits', width=0.9, color=colors, source=source, \
                         legend=[value(x) for x in years], name=years)


p.y_range.start = 0
p.x_range.range_padding = 0.1
p.xgrid.grid_line_color = None
p.axis.minor_tick_line_color = None
p.outline_line_color = None
p.legend.location = "top_left"
p.legend.orientation = "horizontal"

slider = Slider(start=1, end=6, value=3, step=1, title="Range")

#function to update axis range
def update_axis(attrname, old, new):
    a=slider.value
    p.x_range.factors=fruits[0:a]

#Adding fucntion to on_change
slider.on_change('value', update_axis)
layout = column(p, widgetbox(slider))

#use curdoc to be used with bokeh server - use 'bokeh serve --show <filename>.py'
curdoc().add_root(layout)

Call this using Bokeh serve, as it need python backend to run the function

In case you want to use Javascript only, and not the bokeh server, even in that case, I will suggest to change only x_range, and not the data. See code below -

from bokeh.models.widgets import Slider
from bokeh.layouts import widgetbox, column
from bokeh.models import Slider, ColumnDataSource, CustomJS
from bokeh.plotting import figure, curdoc
from bokeh.core.properties import value
from bokeh.models.ranges import FactorRange
from bokeh.plotting import figure, output_file, show, ColumnDataSource



fruits = ['Apples', 'Pears', 'Nectarines', 'Plums', 'Grapes', 'Strawberries']
years = ["2015", "2016", "2017"]
colors = ["#c9d9d3", "#718dbf", "#e84d60"]

data = {'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=data)

## Note [0:3] for first 3 fruits only in default graph
p = figure(x_range=fruits[0:3], plot_height=350, title="Fruit Counts by Year",
           toolbar_location=None, tools="")

renderers= p.vbar_stack(years, x='fruits', width=0.9, color=colors, source=source, \
                         legend=[value(x) for x in years], name=years)


p.y_range.start = 0
p.x_range.range_padding = 0.1
p.xgrid.grid_line_color = None
p.axis.minor_tick_line_color = None
p.outline_line_color = None
p.legend.location = "top_left"
p.legend.orientation = "horizontal"

print(renderers[0].data_source.data['fruits'])

callback = CustomJS(args=dict(fig=p, xr=renderers[0].data_source.data['fruits']), code="""
    var A = slider.value;
    fig.x_range.factors = [];
    for (i = 0; i < A; i++) {
      fig.x_range.factors.push(xr[i])
    }
""")

p.x_range.js_on_change('factors', callback)
slider = Slider(start=1, end=6, value=3, step=1, title="Range", callback=callback)
callback.args["slider"] = slider
layout = column(p, widgetbox(slider))

output_file("ChangenumCat.html")

show(layout) 


来源:https://stackoverflow.com/questions/50681244/bokeh-slider-stacked-bar-chart

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!