Время прочтения: 3 мин.

Инструменты и способы решения задач меняются со временем и боевые скрипты могут подвести, даже если они были протестированы и внедрены. С этой проблемой пришлось столкнуться и нам. Ранее я писала статью о способе визуализации данных в реальном времени с использованием api plotly. Но недавно снова возникла необходимость запустить эту программу Каким же было удивлением увидеть вместо красивого графика – ошибку! Оказалось, что plotly перестали давать бесплатный доступ к сервису для стриминга (работа с данными в реальном времени) через свой api. Что же делать? Решение было найдено, и хотелось бы поделиться им с людьми, которые так же столкнулись с этой проблемой.

            На помощь пришла библиотека для визуализации данных Bokeh, которая бесплатно поддерживает возможность стриминга данных. Для начала нам нужно создать приложение ansver_app.py, которое мы будем позже запускать на сервере bokeh.

            Повторю задачу: «На гугл диске лежит динамическая таблица *.xlsx с результатами опроса. Нам необходимо визуализировать полученные данные в виде bar-диаграммы, которая будет иметь метки количества и окрашивать в отдельный цвет столбец, который набрал большее количество голосов». Приступим к реализации приложения на языке python.

            У нас уже есть функция data_set(), которая скачивает файл и формирует из него набор данных для визуализации. Теперь необходимо написать код отрисовки фигуры и функцию в которой будет непосредственно происходить стриминг данных в созданный график. Импортируем сначала необходимые модули.

from bokeh.io import curdoc

from bokeh.plotting import figure

from bokeh.models import ColumnDataSource, LabelSet, Title

Для работы со словарями и pandas Data Frame у bokeh есть метод ColumnDataSource, в него мы передаем данные. Для начала необходимо просто нарисовать диаграмму, поэтому стартовый датасет делаем пустым.

source_data = ColumnDataSource({'Data': [], 'Val': [],'col':[],'index' : [] })
value = ['1', '2','3', '4'] # названия меток оси x
data_bar = figure(x_range=team, sizing_mode = "stretch_both,          toolbar_location=None, tools="") 
lab = LabelSet(x='index', y='Vol',text = 'Vol',x_offset = 50 ,source=source_data,render_mode = 'canvas') #массив меток данных
data_bar.vbar(x='Data', top='Val', width=0.9,color='col',source=source_data) Далее рисуем диаграмму, добавляем на нее метки данных и редактируем стили заголовков и меток.
data_bar.add_layout(lab) 
data_bar.xgrid.grid_line_color = None
data_bar.y_range.start = 0
data_bar.xaxis.axis_label_text_font_size = "20pt"
data_bar.xaxis.axis_label_text_font = "Arial Black"
data_bar.title.text_font_size = '20pt'
data_bar.title.text_font = 'Arial Black'
data_bar.title.align = "right"
data_bar.yaxis.visible = False #скрываем ось y

Так как мне было важно создать заголовок графика в 2 строки, с этим пришлось помучиться, но в итоге я решила вопрос созданием двух новых меток данных, содержащих в себе заголовки и расположенных друг под другом над диаграммой.

data_bar.add_layout(Title(text="Результаты опроса", text_font_size="16pt",text_font = 'Arial Black'), 'above')
data_bar.add_layout(Title(text="2020 г.", text_font_size="20pt",text_font = 'Arial Black'), 'above')

Приступим к написанию функции для стриминга данных update.

def update():
    array=data_set()
    labels = list(array.keys())
    values = list(array.values())
    clrs  = ["darkorange" if x == max(values) else 'yellowgreen' for x in values]
    idx=[x for x in range(12)]
    new_bar = {'Data':labels, 'Val':values,'col':clrs,'index' :idx}
    source_data.stream(new_bar)

Добавляем вызов нашей функции в add_periodic_callback с необходимым временным интервалом.

curdoc().add_periodic_callback(update, 3000)
curdoc().add_root(data_bar)

После того, как наш файл .py готов, его необходимо запустить через сервер bokeh с помощью командной строки.

bokeh serve —show ansver_app.py

Вызов этой строки откроет браузер и будет визуализировать вашу диаграмму в реальном времени, обновляя график согласно заданному вами в приложении интервалу времени.