bokeh如何根据基础数据动态更改字形中的颜色

时间:2019-01-15 11:02:23

标签: python histogram data-visualization bokeh

我在bokeh中制作了以下仪表板。通过单击“更新数据”按钮,黄色直方图数据将更改。如果平均值大于或小于灰色直方图的平均值,我想将颜色更改为黄色直方图。

enter image description here

这是代码:

    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml"
            xmlns:th="http://www.thymeleaf.org">
    ....
    ....   
    <h1 class="text-primary">Featured Games</h1><a class="btn btn-flat btn-primary" th:href="@{/match/2944107874}">Game Info 2944107874</a>
    ....
.....
</html>

1 个答案:

答案 0 :(得分:0)

您可以将颜色添加到columndatasource中,并在调用回调函数且条件为true时更改颜色。在代码中添加了一些注释,以进一步说明我所做的更改。

from bokeh.plotting import figure
import numpy as np
import pandas as pd
from bokeh.io import curdoc
from bokeh.layouts import column


from bokeh.models import Button
from bokeh.layouts import widgetbox


from bokeh.plotting import ColumnDataSource

button = Button(label='Update Data')

def generate_time_differences(n=1000, skew_p=0.1, mean=0, std=1, skew_mean=1, skew_std=6):
    normal_dist = np.random.normal(loc=mean, scale=std, size=int(n * (1 - skew_p)))
    skewed_dist = np.random.normal(loc=skew_mean, scale=skew_std, size=int(n * skew_p))

    return np.append(normal_dist, skewed_dist)


def generate_plot_data(data, density=True, bins=50):
    hist, edges = np.histogram(data, density=density, bins=bins)

    df = pd.DataFrame({'top': hist,
                         'left': edges[:-1],
                         'right': edges[1:]}

                      )
    df['mean'] = [np.mean(data) for i in range(len(df))]
    df['std'] = [np.std(data) for i in range(len(df))]
    df['n'] = [len(data) for i in range(len(df))]

    return ColumnDataSource(df)


def create_histogram(plot_data_control, plot_data_observed, title, x_axis_label='Milliseconds',
                     y_axis_label='Frequency'):

    mean_control = np.mean(plot_data_control.data['mean'])
    mean_observed = np.mean(plot_data_observed.data['mean'])
    #Change color if mean_observed > mean_control
    if mean_observed > mean_control:
        color_observed = 'yellow'
    else:
        color_observed = 'green'
    #Generate a list with the right color
    colorlst = []
    for i in range(len(plot_data_observed.data['top'])):
        colorlst.append(color_observed)
    #Add color list to sourcedata
    plot_data_observed.data['color'] = colorlst

    p = figure(plot_height=150, plot_width=600,
               title=title,
               x_axis_label=x_axis_label,
               y_axis_label=y_axis_label)

    # Add a quad glyph for plot_data
    p.quad(source=plot_data_control, bottom=0, top='top', left='left', right='right',
           fill_color='gray', line_color='gray', fill_alpha=0.5, line_alpha=0.5, legend='Control')
    # Add another quad glyph for plot_data2
    #Get color from source
    p.quad(source=plot_data_observed, bottom=0, top='top', left='left', right='right',
           fill_color='color', line_color='color', fill_alpha=0.5, line_alpha=0.5, legend='Observed')
    p.legend.click_policy="hide"
    return p

def update():
    mean = np.random.randint(500,1500)
    std = 100
    skew_mean =  2000
    skew_std = 500
    new_plot_data = generate_time_differences(n=100, skew_p=0.1, mean=mean, std=std, skew_mean=skew_mean, skew_std=skew_std)
    obs_data = generate_plot_data(new_plot_data).data
    #Get means
    mean_control = plot_data.data['mean'][0]
    mean_observed = obs_data['mean'][0]
    #Change color if mean_observed > mean_control
    if mean_observed > mean_control:
        color_observed = 'yellow'
    else:
        color_observed = 'green'
    #Generate a list with the right color
    colorlst = []
    for i in range(len(obs_data['top'])):
        colorlst.append(color_observed)
    #Add list to dictionary
    obs_data['color'] = colorlst
    #Set dictionary as sourcedata
    plot_data2.data =  obs_data


data = generate_time_differences(n=1000, skew_p=0.1, mean=1000, std=100, skew_mean=2000, skew_std=500)
data2 = generate_time_differences(n=100, skew_p=0.1, mean=1050, std=100, skew_mean=2100, skew_std=500)


plot_data = generate_plot_data(data)
plot_data2 = generate_plot_data(data2)


p1 = create_histogram(plot_data, plot_data2, 'Status1 to Status2')

button.on_click(update)

layout = column(widgetbox(button), p1)

curdoc().add_root(layout)