如何使用 RadioGroup 按钮更新绘图类型?

How do I update a plot type with RadioGroup buttons?

我定义了两种绘图函数:plt_percent和plt_number。我想使用 RadioGroup 按钮在它们之间切换。

现在我通过清除整个屏幕并从头开始在更新功能中执行此操作:

curdoc().clear()
layout = row(menu, p)
curdoc().add_root(layout)

我的仪表板也有其他图表,但更新功能只需更改此特定图表,而无需触及任何其他对象。

我怀疑 CustomJS 可以实现,但我不知道如何实现。

完整代码如下:

import pandas as pd
from bokeh.plotting import figure 
from bokeh.io import curdoc
from bokeh.layouts import row
from bokeh.models import ColumnDataSource, RadioGroup, PrintfTickFormatter


colors=['navy', 'red']
    
data = {'fruits' : ['Apples', 'Pears', 'Nectarines', 'Plums', 'Grapes', 'Strawberries'],
        '2015'   : [2, 1, 4, 3, 2, 4],
        '2016'   : [3, 2, 4, 4, 5, 3]}
df = pd.DataFrame(data)

def make_dataset(df):
    df['total'] = df.sum(axis=1)
    df['2015_%'] = round((df['2015'] * 100) / df.total)    
    df['2016_%'] = round((df['2016'] * 100) / df.total)
    print(df)
    return ColumnDataSource(df)

def plt_percent(src):
    p = figure(x_range=src.data['fruits'],
                plot_width=500, plot_height=500
                )
    p.vbar_stack(['2015_%', '2016_%'], 
                x='fruits', 
                width=0.5,
                source=src ,
                color=colors,
                legend_label=['2015', '2016']
                )
    p.yaxis[0].formatter = PrintfTickFormatter(format='%0.0f%%')    
    return p


def plt_number(src):
    p = figure(x_range=src.data['fruits'],
                plot_width=500, plot_height=500
                )
    p.vbar_stack(['2015', '2016'],
                x='fruits',
                width=0.5,
                source=src,
                color=colors,
                legend_label=['2015', '2016']
                )
    return p


def update(new): 
    count_type = menu.active
    if count_type == 0:
        p = plt_percent(source)
    elif count_type == 1:
        p = plt_number(source)
   
    layout = row(menu, p)
    curdoc().clear()
    curdoc().add_root(layout)


# menu 
menu = RadioGroup(labels=['percentage', 'number'], active = 0)
menu.on_click(update)

# initialise
source = make_dataset(df)
p = plt_percent(source)

layout = row(menu, p)
curdoc().add_root(layout)


不用创建一个完整的新页面,只需使用布局的子属性更改图表 (row/column) -

import pandas as pd
from bokeh.plotting import figure 
from bokeh.io import curdoc
from bokeh.layouts import row
from bokeh.models import ColumnDataSource, RadioGroup, PrintfTickFormatter


colors=['navy', 'red']
    
data = {'fruits' : ['Apples', 'Pears', 'Nectarines', 'Plums', 'Grapes', 'Strawberries'],
        '2015'   : [2, 1, 4, 3, 2, 4],
        '2016'   : [3, 2, 4, 4, 5, 3]}
df = pd.DataFrame(data)

def make_dataset(df):
    df['total'] = df.sum(axis=1)
    df['2015_%'] = ((df['2015'] * 100) / df.total).round()    
    df['2016_%'] = ((df['2016'] * 100) / df.total).round()
    print(df)
    return df , ColumnDataSource(df)

def plt_percent(src):
    p = figure(x_range=src.data['fruits'].tolist(), plot_width=500, plot_height=500)
    p.vbar_stack(['2015_%', '2016_%'], x='fruits', width=0.5, source=src , color=colors, legend_label=['2015', '2016'])
    p.yaxis[0].formatter = PrintfTickFormatter(format='%0.0f%%')    
    return p

def plt_number(src):
    p = figure(x_range=src.data['fruits'].tolist(),plot_width=500, plot_height=500)
    p.vbar_stack(['2015', '2016'], x='fruits', width=0.5, source=src, color=colors, legend_label=['2015', '2016'])
    return p


def update(new): 
    count_type = menu.active
    if count_type == 0:
        p = plt_percent(source)
    elif count_type == 1:
        p = plt_number(source)
    
    layout.children[1] = p

# menu 
menu = RadioGroup(labels=['percentage', 'number'], active = 0)
menu.on_click(update)

# initialise
source = make_dataset(df)
p = plt_percent(source)

layout = row(menu, p)
curdoc().add_root(layout)

如果您只更改图表背后的数据会更好(并且更无缝),但要做到这一点,您需要从基本字形制作图表。