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