Python 如何替换交互式Bokeh图中的图例,而不是增加图例?

Python 如何替换交互式Bokeh图中的图例,而不是增加图例?,python,bokeh,Python,Bokeh,我正在使用Bokeh中的选择下拉列表来更改图表显示的内容。我还希望图表的图例也相应地改变。但是,每次用户选择一个新的下拉值时,图例都会增加。最终,图例会同时显示每个可能下拉选项中的每个值。如何“清除”每个新下拉选择上的旧图例 import numpy as np import pandas as pd import os from bokeh.plotting import figure from bokeh.io import output_file, show, save, curdoc

我正在使用Bokeh中的选择下拉列表来更改图表显示的内容。我还希望图表的图例也相应地改变。但是,每次用户选择一个新的下拉值时,图例都会增加。最终,图例会同时显示每个可能下拉选项中的每个值。如何“清除”每个新下拉选择上的旧图例

import numpy as np
import pandas as pd
import os

from bokeh.plotting import figure
from bokeh.io import output_file, show, save, curdoc
from bokeh.models import HoverTool, CategoricalColorMapper, BoxSelectTool
from bokeh.models import ColumnDataSource, Select, Range1d
from bokeh.layouts import row, column, gridplot
from bokeh.models.widgets import Panel, Tabs
from bokeh.transform import factor_cmap

team = ['Bears', 'Bears', 'Bears', 'Bears', 'Bears']
player = ['Charles Leno', 'James Daniels', 'Cody Whitehair', 'Kyle Long', 'Bobby Massie']
position = ['LT', 'LG', 'C', 'RG', 'RT']
year_acquired = [2014, 2018, 2016, 2013, 2016]
round_drafted = [7, 2, 2, 1, np.NaN]
star=[False, False, False, True, False]

position_loc_x = [-4, -2, 0, 2, 4]
position_loc_y = [0, 0, 0, 0, 0]

year_acquired_color = ['green', 'yellow', 'blue', 'purple', 'blue']
round_drafted_color = ['grey', 'green', 'green', 'purple', np.NaN]
star_color = ['black', 'black', 'black', 'red', 'black']

df = pd.DataFrame({'team':team, 'player':player, 'position':position, 'year_acquired':year_acquired, 
                   'round_drafted':round_drafted, 'star':star, 'position_loc_x':position_loc_x, 
                   'position_loc_y':position_loc_y, 'year_acquired_color':year_acquired_color, 
                   'round_drafted_color':round_drafted_color, 'star_color':star_color})

p = figure(x_range=[-5,5], y_range=[-5, 5])

source = ColumnDataSource(data=df)

p.rect(source=source, x='position_loc_x', y=0, width=1, height=1, line_width=5, line_color=None,
       fill_color='round_drafted_color', legend='round_drafted')

hover = HoverTool(tooltips=[('Name', '@player'), ('Round', '@round_drafted'), ('Year', '@year_acquired')])
p.add_tools(hover)

def update():
    p.rect(source=source, x='position_loc_x', y=0, width=1, height=1, line_width=5, line_color=None, 
           fill_color=select.value, legend=select.value.rpartition('_')[0])

select = Select(title='choose an attribute', options=['round_drafted_color', 'year_acquired_color', 'star_color'], 
               value = 'round_drafted_color')

select.on_change('value', lambda attr, old, new: update())

p.legend.click_policy="hide"

layout = column(select, p)
curdoc().add_root(layout)

您应该更新用于绘制矩形的ColumnDataSource,而不是使用新颜色/legendname再次绘制矩形。您可以通过编辑
source.data
字典来实现这一点

#!/usr/bin/python3
import numpy as np
import pandas as pd
import os

from bokeh.plotting import figure
from bokeh.io import output_file, show, save, curdoc
from bokeh.models import HoverTool, CategoricalColorMapper, BoxSelectTool
from bokeh.models import ColumnDataSource, Select, Range1d
from bokeh.layouts import row, column, gridplot
from bokeh.models.widgets import Panel, Tabs
from bokeh.transform import factor_cmap

team = ['Bears', 'Bears', 'Bears', 'Bears', 'Bears']
player = ['Charles Leno', 'James Daniels', 'Cody Whitehair', 'Kyle Long', 'Bobby Massie']
position = ['LT', 'LG', 'C', 'RG', 'RT']
year_acquired = [2014, 2018, 2016, 2013, 2016]
round_drafted = [7, 2, 2, 1, np.NaN]
star=[False, False, False, True, False]

position_loc_x = [-4, -2, 0, 2, 4]
position_loc_y = [0, 0, 0, 0, 0]

year_acquired_color = ['green', 'yellow', 'blue', 'purple', 'blue']
round_drafted_color = ['grey', 'green', 'green', 'purple', np.NaN]
star_color = ['black', 'black', 'black', 'red', 'black']

df = pd.DataFrame({'team':team, 'player':player, 'position':position, 'year_acquired':year_acquired, 
                   'round_drafted':round_drafted, 'star':star, 'position_loc_x':position_loc_x, 
                   'position_loc_y':position_loc_y, 'year_acquired_color':year_acquired_color, 
                   'round_drafted_color':round_drafted_color, 'star_color':star_color, 'legend':round_drafted, 'color':round_drafted_color})

p = figure(x_range=[-5,5], y_range=[-5, 5])

source = ColumnDataSource(data=df)

glyph = p.rect(source=source, x='position_loc_x', y=0, width=1, height=1, line_width=5, line_color=None,
       fill_color='color', legend='legend')

hover = HoverTool(tooltips=[('Name', '@player'), ('Round', '@round_drafted'), ('Year', '@year_acquired')])
p.add_tools(hover)

def update():
    #Use select.value to get the right key from the dictionary and set its list as color/legend item
    source.data['color'] = source.data[select.value]
    source.data['legend'] = source.data[select.value.replace('_color', '')]


select = Select(title='choose an attribute', options=['round_drafted_color', 'year_acquired_color', 'star_color'], 
               value = 'round_drafted_color')

select.on_change('value', lambda attr, old, new: update())

p.legend.click_policy="hide"

layout = column(select, p)
curdoc().add_root(layout)

谢谢你,真管用!但还有一个我认为可以解决的问题:单击图例元素来隐藏它,而不是隐藏整个图例。有什么建议吗?我认为我的大脑没有掌握博克的基本工作原理,而且似乎也没有太多好的文档。官方文档只提供了最简单的示例,一旦我需要同时使用2+个Bokeh功能组合,我就迷路了~“交互式图例功能当前可用于“每字形”图例。通过指定列以自动分组创建的图例还不能用于下面描述的功能。”。可以使用一些CustomJ和复选框来解决此问题,如本问题中所述: