如何替换交互式散景图中的图例,而不是扩大图例?

时间:2019-01-20 03:45:31

标签: 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
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)

1 个答案:

答案 0 :(得分:1)

您应该更新用于绘制矩形的ColumnDataSource,而不是使用新的颜色/图例名称再次绘制矩形。您可以通过编辑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)