Как я могу динамически изменить свой источник данных с помощью функции on_change элемента select / dropdown? - PullRequest
0 голосов
/ 22 мая 2019

У меня есть график, генерируемый из жестко закодированного ColumnDataSource.

Значения моего графика должны меняться в зависимости от того, что мой пользователь выбирает из выпадающего списка.

Моя функция update () неработать так, как я хочу.Мои старые 'source' и 'NEWsource' в распечатанном виде имеют одинаковый формат, я просто не могу получить изменения, отображаемые на графике.

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"

Что мешает источнику NEWs достичь графика?

График правильно отображает жестко запрограммированный источник:

enter image description here

Когда я пытаюсь обновить график из моего динамического источника NEWS с несколькими путанными значениями вверхний угол:

enter image description here

1 Ответ

0 голосов
/ 22 мая 2019

Ваш код отлично работает в Bokeh v1.1.0. Одно замечание: рекомендуется заменять только data объекта ColumnDataSource вместо создания нового ColumnDataSource каждый раз.

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

Вот ваш полный код с этим небольшим изменением в обновлении (). Запустите его из терминала: 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

...