如何使用选择/下拉列表的on_change函数动态更改数据源?

时间:2019-05-22 15:14:54

标签: bokeh

我有一个图是从硬编码的ColumnDataSource生成的。

我的图形值需要根据用户从下拉菜单中选择的内容进行更改。

我的update()函数无法按我想要的方式工作。打印时,我的旧“源”和“新源”的格式相同,我只是无法将更改显示在绘图上。

from os.path import dirname, join
import pandas as pd
from bokeh.io import curdoc
from bokeh.layouts import row, column
from bokeh.models import ColumnDataSource
from bokeh.models.widgets import PreText, Select
from bokeh.plotting import figure

DEFAULT_TICKERS = ['giode', 'commerce_center', 'web_forms']

def load_data_depending_on_dropdown_value(ticker):
    ...

def get_data(ticker):
    ...data processing...
    return data

# Make my dropdown, aka. ticker
ticker = Select(value='giode', options=DEFAULT_TICKERS)

# ORIGINAL SOURCE - HARDCODED
source = ColumnDataSource(
    data=dict(
        message=['BPN Broken', 'BPN Off', 'BPN Faulty', 'BPN Rain', 'BPN Fire', 'BPN Tornado', 'BPN STAFF DAY OFF'],
        counts=[5, 3, 4, 2, 4, 6,2]
        )
    )
source_static = ColumnDataSource(
    data=dict(
        message=['BPN Broken', 'BPN Off', 'BPN Faulty', 'BPN Rain', 'BPN Fire', 'BPN Tornado', 'BPN STAFF DAY OFF'],
        counts=[5, 3, 4, 2, 4, 6,2]
        )
    )

# Make a plot
p = figure(x_range=source.data['message'], plot_height=250)
p.vbar(x='message', top='counts', width=0.9, source=source)
p.xgrid.grid_line_color = None
p.y_range.start = 0

# Called when ticker, aka. dropdown, gets changed
def ticker_changed(attrname, old, new):
    print(attrname, old, new)
    update()

# CONTAINING MY NEW SOURCE
def update(selected=None):
    t1_Value = ticker.value
    newData = get_data(t1_Value)
    newMessages = newData.message.tolist()
    newCounts = newData.counts.tolist()

    NEWsource = ColumnDataSource(data=dict(message=newMessages, counts=newCounts))

    # Compare the old source with my new source:
    print("Original source.data: " , source.data , "New data: " , NEWsource.data)

    source.data = NEWsource.data
    source_static.data = NEWsource.data
        # This part works fine
    p.title.text = '%s Plot' % (t1_Value)


ticker.on_change('value', ticker_changed)


widgets = column(ticker)
main_row = row(widgets, p)

update()

curdoc().add_root(main_row)
curdoc().title = "Stocks"

是什么阻止了NEWsource到达地块?

正确显示硬编码源的图:

enter image description here

当我尝试从动态NEWsource更新绘图时,在右上角添加了一些混乱的值:

enter image description here

1 个答案:

答案 0 :(得分:0)

您的代码在Bokeh v1.1.0中可以正常工作。备注:建议仅替换data对象的ColumnDataSource而不是每次都创建一个新的ColumnDataSource

def update():
    source.data = get_data(ticker.value)
    p.title.text = '%s Plot' % (ticker.value)

这是您的完整代码,其中up​​date()进行了很小的更改。从终端bokeh serve --show app.py

运行
from os.path import dirname, join
import pandas as pd
from bokeh.io import curdoc
from bokeh.layouts import row, column
from bokeh.models import ColumnDataSource
from bokeh.models.widgets import PreText, Select
from bokeh.plotting import figure

DEFAULT_TICKERS = ['giode', 'commerce_center', 'web_forms']

def load_data_depending_on_dropdown_value(ticker):
    pass

def get_data(ticker):
    if ticker == 'giode':
        return    dict(
            message=['BPN Broken', 'BPN Off', 'BPN Faulty', 'BPN Rain', 'BPN Fire', 'BPN Tornado', 'BPN STAFF DAY OFF'],
            counts=[5, 3, 4, 2, 4, 6,2]
            )
    elif ticker == 'commerce_center':
        return    dict(
            message=['BPN Broken', 'BPN Off', 'BPN Faulty', 'BPN Rain', 'BPN Fire', 'BPN Tornado', 'BPN STAFF DAY OFF'],
            counts=[1, 2, 3, 4, 5, 6, 7]
            )
    elif ticker == 'web_forms':
        return    dict(
            message=['BPN Broken', 'BPN Off', 'BPN Faulty', 'BPN Rain', 'BPN Fire', 'BPN Tornado', 'BPN STAFF DAY OFF'],
            counts=[7, 6, 5, 4, 3, 2, 1]
            )      

# Make my dropdown, aka. ticker
ticker = Select(value='giode', options=DEFAULT_TICKERS)

# ORIGINAL SOURCE - HARDCODED
source = ColumnDataSource(
    data=dict(
        message=['BPN Broken', 'BPN Off', 'BPN Faulty', 'BPN Rain', 'BPN Fire', 'BPN Tornado', 'BPN STAFF DAY OFF'],
        counts=[5, 3, 4, 2, 4, 6,2]
        )
    )
source_static = ColumnDataSource(
    data=dict(
        message=['BPN Broken', 'BPN Off', 'BPN Faulty', 'BPN Rain', 'BPN Fire', 'BPN Tornado', 'BPN STAFF DAY OFF'],
        counts=[5, 3, 4, 2, 4, 6,2]
        )
    )

# Make a plot
p = figure(x_range=source.data['message'], plot_height=250)
p.vbar(x='message', top='counts', width=0.9, source=source)
p.xgrid.grid_line_color = None
p.y_range.start = 0

# Called when ticker, aka. dropdown, gets changed
def ticker_changed(attrname, old, new):
    print(attrname, old, new)
    update()

# CONTAINING MY NEW SOURCE
# def update(selected=None):
#     t1_Value = ticker.value
#     newData = get_data(t1_Value)
#     newMessages = newData.message.tolist()
#     newCounts = newData.counts.tolist()
#  
#     NEWsource = ColumnDataSource(data=dict(message=newMessages, counts=newCounts))
# 
#     # Compare the old source with my new source:
#     print("Original source.data: " , source.data , "New data: " , NEWsource.data)
# 
#     source.data = NEWsource.data
#     source_static.data = NEWsource.data
#         
#     # This part works fine
#     p.title.text = '%s Plot' % (t1_Value)

def update(selected = None):
    newData = get_data(ticker.value)
    source.data = newData
    source_static.data = newData
    p.title.text = '%s Plot' % (ticker.value)

ticker.on_change('value', ticker_changed)

widgets = column(ticker)
main_row = row(widgets, p)

update()

curdoc().add_root(main_row)
curdoc().title = "Stocks"

enter image description here