Я пытаюсь создать приложение bokeh с потоковыми данными, которые отслеживают несколько «стратегий», поскольку они генерируются в модели, основанной на агенте дилерма-заключенный. Я столкнулся с проблемой, пытаясь заставить мои линейные графики НЕ соединять все точки данных в одну линию. Я собрал этот небольшой демонстрационный скрипт, который повторяет проблему. Я прочитал много документации по линейному и многострочному рендерингу на боке-графиках, но я просто не нашел того, что, кажется, соответствует моему простому случаю. Вы можете запустить этот код, и он автоматически откроет сервер bokeh на localhost: 5004 ...
from bokeh.server.server import Server
from bokeh.application import Application
from bokeh.application.handlers.function import FunctionHandler
from bokeh.plotting import figure, ColumnDataSource
from bokeh.models import Button
from bokeh.layouts import column
import random
def make_document(doc):
# Create a data source
data_source = ColumnDataSource({'step': [], 'strategy': [], 'ncount': []})
# make a list of groups
strategies = ['DD', 'DC', 'CD', 'CCDD']
# Create a figure
fig = figure(title='Streaming Line Plot',
plot_width=800, plot_height=400)
fig.line(x='step', y='ncount', source=data_source)
global step
step = 0
def button1_run():
global callback_obj
if button1.label == 'Run':
button1.label = 'Stop'
button1.button_type='danger'
callback_obj = doc.add_periodic_callback(button2_step, 100)
else:
button1.label = 'Run'
button1.button_type = 'success'
doc.remove_periodic_callback(callback_obj)
def button2_step():
global step
step = step+1
for i in range(len(strategies)):
new = {'step': [step],
'strategy': [strategies[i]],
'ncount': [random.choice(range(1,100))]}
fig.line(x='step', y='ncount', source=new)
data_source.stream(new)
# add on_click callback for button widget
button1 = Button(label="Run", button_type='success', width=390)
button1.on_click(button1_run)
button2 = Button(label="Step", button_type='primary', width=390)
button2.on_click(button2_step)
doc.add_root(column(fig, button1, button2))
doc.title = "Now with live updating!"
apps = {'/': Application(FunctionHandler(make_document))}
server = Server(apps, port=5004)
server.start()
if __name__ == '__main__':
server.io_loop.add_callback(server.show, "/")
server.io_loop.start()
Я надеялся, что, пройдя по 4 "стратегиям" в примере (после нажатия кнопки 2), Я мог бы транслировать новые данные, поступающие из симуляции, в линейный график только для этой одной стратегии и шага. Но то, что я получаю, это одна строка со всеми четырьмя значениями, соединенными вертикально, затем одно из них соединяется с первым на следующем этапе. Вот как это выглядит после нескольких шагов:
Я заметил, что если я переместу data_source.stream(new)
из для l oop, я получу хороший однолинейный сюжет , но, конечно, это только для последней стратегии, выходящей из l oop.
Во всех примерах с многострочным построением боке, которые я изучал (не глиф multi_line
, который я могу ' (и, похоже, у него есть некоторые проблемы с инструментом Hover), инструкции кажутся довольно ясными: если вы хотите визуализировать вторую строку, вы добавляете другой рендерер fig.line
к существующему figure
, и это dr aws строка с данными, указанными в source=data_source
для этой строки. Но хотя мой for-l oop собирает и добавляет данные отдельно для каждой стратегии, я не получаю 4 линейных графика, я получаю только один.
Надеюсь, я упускаю что-то очевидное! Заранее спасибо.