Python Bokeh: обновить цвета графика рассеяния при обратном вызове - PullRequest
0 голосов
/ 18 декабря 2018

Я только начал использовать 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.

enter image description here

Затем у меня есть функция обратного вызова 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>

enter image description here

Должен ли я просто добавить «цветной» столбец во фрейм данных?Я чувствую, что есть более простой / более удобный способ сделать это.

РЕДАКТИРОВАТЬ : Вот минимальный рабочий пример с использованием ответа 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, будет красным.Вместо этого я ожидал бы, что все будет синим до последних трех кругов на вершинах, которые должны быть окрашены в зеленый, желтый и красный цвета соответственно.

1 Ответ

0 голосов
/ 18 декабря 2018

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

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

Вот полный рабочий пример (сделанный с помощью Bokeh 1.0.2), который демонстрирует цвета карты цветов глифаобновление в ответ на изменение столбца данных:

from bokeh.io import curdoc
from bokeh.layouts import column
from bokeh.plotting import figure
from bokeh.models import Button, ColumnDataSource, ColorBar
from bokeh.palettes import Spectral6
from bokeh.transform import linear_cmap

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]

#Use the field name of the column source
mapper = linear_cmap(field_name='z', palette=Spectral6 ,low=min(y) ,high=max(y))

source = ColumnDataSource(dict(x=x, y=y, z=z))

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_layout(color_bar, 'right')

b = Button()

def update():
    new_z = np.exp2(z)

    # update the existing transform
    mapper['transform'].low=min(new_z)
    mapper['transform'].high=max(new_z)

    source.data = dict(x=x, y=y, z=new_z)

b.on_click(update)

curdoc().add_root(column(b, p))

Вот исходный график:

enter image description here

А вот и обновлениеучасток после нажатия кнопки

enter image description here

...