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

问题描述

我定义了两种绘图函数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,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_height=500
                )
    p.vbar_stack(['2015','2016'],'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)


解决方法

代替创建一个完整的新页面,只需使用layout(row / column)的children属性更改图表-

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,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_height=500)
    p.vbar_stack(['2015','2016'],'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)

如果只是更改图表后面的数据,将会更好(更无缝),但为此您需要使用基本字形制作图表。