【问题标题】:bokeh how to dynamically change color in glyph based on underlying data散景如何根据基础数据动态更改字形中的颜色
【发布时间】:2019-06-09 09:20:30
【问题描述】:

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

这是代码:

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'])

    color_observed = 'yellow' if mean_observed > mean_control else 'green'


    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
    p.quad(source=plot_data_observed, bottom=0, top='top', left='left', right='right',
           fill_color=color_observed, line_color=color_observed, fill_alpha=0.5, line_alpha=0.5, legend='Observed')
    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)

    plot_data2.data =  generate_plot_data(new_plot_data).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)

【问题讨论】:

    标签: python histogram data-visualization bokeh


    【解决方案1】:

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

    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)
    

    【讨论】:

      猜你喜欢
      • 2013-09-03
      • 1970-01-01
      • 2019-09-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多