Я только начал использовать Bokeh недавно.У меня есть точечная диаграмма, на которой я хотел бы раскрасить каждый маркер в соответствии с определенным третьим свойством (скажем, количеством, в то время как ось X является датой, а ось Y - заданным значением в данный момент времени).
Предполагая, что мои данные находятся во фрейме данных, мне удалось сделать это с помощью линейной карты цветов следующим образом:
min_q = df.quantity.min()
max_q = df.quantity.max()
mapper = linear_cmap(field_name='quantity', palette=palettes.Spectral6, low=min_q, high=max_q)
source = ColumnDataSource(data=get_data(df))
p = figure(x_axis_type="datetime")
p.scatter(x="date_column", y="value", marker="triangle", fill_color=mapper, line_color=None, source=source)
color_bar = ColorBar(color_mapper=mapper['transform'], width=8, location=(0,0))
p.add_layout(color_bar, 'right')
Кажется, это работает как ожидалось.Ниже приведен график, который я получаю при запуске сервера bokeh.
Затем у меня есть функция обратного вызова update () , запущенная приизменение значения в каком-то виджете (выбор или выбор времени).
def update():
# get new df (according to new date/select)
df = get_df()
# update min/max for colormap
min_q = df.quantity.min()
max_q = df.quantity.max()
# I think I should not create a new mapper but doing so I get closer
mapper = linear_cmap(field_name='quantity', palette=palettes.Spectral6 ,low=min_q, high=max_q)
color_bar.color_mapper=mapper['transform']
source.data = get_data(df)
# etc
Это самое близкое, что я мог получить.Карта цветов обновляется новыми значениями, но кажется, что цвета маркера по-прежнему соответствуют исходному шаблону.См. Рисунок ниже (учитывая то количество, которое я бы ожидал, зеленым, но оно синее, так как оно все еще выглядит как <4000, как на карте первого графика до обратного вызова). </p>
Должен ли я просто добавить «цветной» столбец во фрейм данных?Я чувствую, что есть более простой / более удобный способ сделать это.
РЕДАКТИРОВАТЬ : Вот минимальный рабочий пример с использованием ответа bigreddot:
from bokeh.io import curdoc
from bokeh.layouts import column
from bokeh.plotting import figure
from bokeh.models import Button, ColumnDataSource, ColorBar, HoverTool
from bokeh.palettes import Spectral6
from bokeh.transform import linear_cmap
import numpy as np
x = [1,2,3,4,5,7,8,9,10]
y = [1,2,3,4,5,7,8,9,10]
z = [1,2,3,4,5,7,8,9,10]
source = ColumnDataSource(dict(x=x, y=y, z=z))
#Use the field name of the column source
mapper = linear_cmap(field_name='z', palette=Spectral6 ,low=min(y) ,high=max(y))
p = figure(plot_width=300, plot_height=300, title="Linear Color Map Based on Y")
p.circle(x='x', y='y', line_color=mapper,color=mapper, fill_alpha=1, size=12, source=source)
color_bar = ColorBar(color_mapper=mapper['transform'], width=8, location=(0,0))
p.add_tools(HoverTool(tooltips="@z", show_arrow=False, point_policy='follow_mouse'))
p.add_layout(color_bar, 'right')
b = Button()
def update():
new_z = np.exp2(z)
mapper = linear_cmap(field_name='z', palette=Spectral6 ,low=min(new_z), high=max(new_z))
color_bar.color_mapper=mapper['transform']
source.data = dict(x=x, y=y, z=new_z)
b.on_click(update)
curdoc().add_root(column(b, p))
Пообновите, круги будут окрашены в соответствии с оригинальной шкалой: все, что больше 10, будет красным.Вместо этого я ожидал бы, что все будет синим до последних трех кругов на вершинах, которые должны быть окрашены в зеленый, желтый и красный цвета соответственно.