Bokeh Slider Stacked Bar Chart - PullRequest
0 голосов
/ 04 июня 2018

Я хочу иметь возможность показывать только первые три верхних бара, а затем показывать больше или меньше баров с помощью ползунка.Я не знаю, возможно ли это с помощью виджета-слайдера боке или есть лучший метод.

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 Ответ

0 голосов
/ 05 июня 2018

Я не вижу необходимости использовать javascript callback здесь.Здесь можно использовать встроенную функцию python on_change.Функция изменит диапазон оси X без изменения каких-либо внутренних данных и будет очень быстрой -

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)

Вызовите это с помощью Bokeh serve, так как для запуска функции

необходим бэкэнд Python

Если вы хотите использовать только Javascript, а не сервер bokeh, даже в этом случае я предлагаю изменить только x_range, а не данные.Смотрите код ниже -

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) 
...