Bokeh的最新版本允许程序员将图例放在图表区域之外。这可以像描述here:
那样完成p = figure(toolbar_location="above")
r0 = p.circle(x, y)
legend = Legend(items=[
("sin(x)" , [r0]),),
], location=(0, -30))
p.add_layout(legend, 'right')
show(p)
注意:图例对象通过add_layout附加到绘图上。图例对象本身由元组和字符串以及字形列表组成。
问题是当你只是绘制一个"数据"系列与下面的代码一样,改编自here:
from bokeh.io import show
from bokeh.models import ColumnDataSource, HoverTool, LinearColorMapper
from bokeh.plotting import figure
col = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16]
row = ['A', 'B', 'C' , 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M',
'N', 'O', 'P']
# this is the colormap from the original NYTimes plot
colors = ["#75968f", "#a5bab7", "#c9d9d3", "#e2e2e2", "#dfccce",
"#ddb7b1", "#cc7878", "#933b41", "#550b1d"]
mapper = LinearColorMapper(palette=colors)
source = ColumnDataSource(data = dict (
row = test['plate_row'],
col = test['plate_col'],
values = test['Melt Temp']
))
TOOLS = "hover,save,pan,box_zoom,wheel_zoom"
p = figure(title="Plate Heatmap", x_range = (0.0,25.0), y_range =
list(reversed(row)), x_axis_location="above", tools=TOOLS)
r1 = p.rect(x="col", y="row", width=1, height=1,
source=source,
fill_color={'field': 'values', 'transform': mapper},
line_color=None)
legend = Legend(items=[
("test" , [r1]),
], location=(0, -30))
p.add_layout(legend, 'left')
show(p) # show the plot
这里的问题是只有一个字形。我真正需要的是解释不同颜色包含的值范围。显然,这是可能的,因为定义的here图表显示它是可能的。
更新
现在我正在写这个问题,我开始想,也许我可以只绘制多个系列,每个颜色一个......并且只绘制那些落在一定范围内的坐标......虽然看起来很笨重。所以任何想法都值得赞赏!
答案 0 :(得分:1)
我找到了使用CategoricalColorMapper然后不创建显式图例对象的方法。 可能有一种方法可以使用相同的布局显式创建图例对象,稍后我会看一下。
import numpy as np
from bokeh.io import show
from bokeh.models import Legend
from bokeh.models import ColumnDataSource, HoverTool,CategoricalColorMapper
from bokeh.plotting import figure
from bokeh.palettes import Blues8
# values to assign colours on
values = np.arange(100,107)
# values that will appear in the legend!!!
legend_values = ['100-101','101-102','102-103','103-04','104-05','105-06',
'106-07']
source = ColumnDataSource(data = dict (
row = np.arange(100,107),
col = np.arange(100,107),
values = np.arange(100,107),
legend_values = legend_values
))
mapper = CategoricalColorMapper(factors=list(values),palette=Blues8)
TOOLS = "hover,save,pan,box_zoom,wheel_zoom"
p = figure(title="Plate Heatmap", x_range = (100,107), y_range =
[90,107], x_axis_location="above", tools=TOOLS)
r1 = p.rect(x="col", y="row", width=1, height=1,
source=source,
fill_color={'field': 'values', 'transform': mapper},
line_color=None,legend='legend_values')
p.legend.location = "bottom_right"
show(p) # show the plot
请在此处查看图片1
答案 1 :(得分:1)
在研究了这一点之后,我发现了两种创建图例的方法,这些图例显示了每种颜色在热图上的含义:
首先,我将数字范围分成像这样的箱子:
min_value = test['Melt Temp'].min()
max_value = test['Melt Temp'].max()
increment = round((max_value - min_value)/9)
num_bins = [(lower, lower+increment) for lower in
range(int(floor(min_value)), int(round(max_value)),
int(round(increment)))]
然后,我从主表中创建子表,如下所示:
source_dict = {}
for range_tuple in num_bins:
range_data = test[(test['Melt Temp'] > int(range_tuple[0])) &
(test['Melt Temp'] <= int(range_tuple[1]))]
source = ColumnDataSource(data = dict (
row = range_data['x'],
col = range_data['y'],
values = range_data['Value']))
source_dict[range_tuple] = source
然后我用列数据源子表压缩颜色:
colors = RdYlBu9
glyph_list = []
for color, range_tuple in zip(colors, num_bins):
r1 = p.rect(x="col", y="row", width=1, height=1,
source=source_dict[range_tuple],
fill_color=color,
line_color=None)
glyph_list.append(r1)
最后,我创建了一个显式的图例对象,它需要字符串字形元组。然后,图例对象将附加到图中:
legend_list = [("{0}<={1}".format(bin[0], bin[1]), [glyph]) for bin,
glyph in zip(num_bins, glyph_list)]
legend = Legend(items=legend_list, location=(0, -50))
p.add_layout(legend, 'left')
show(p)
这种方法的缺点:
第二种方法使用上面的@ Okonomiyaki评论,并且更加简单。基本要点是您使用颜色映射器来确定字形的颜色。您还可以在Okonomiyaki指出的情况下创建ColorBar:
mapper = LogColorMapper(palette="Viridis256", low=min_value,
high=max_value)
source = ColumnDataSource(data = dict (
row = test['x'], col = test['y'], values = test['value']))
p = figure(title="Plate Heatmap", x_range = (0.0,25.0), y_range =
list(reversed(row)),
x_axis_location="above", plot_width=650, plot_height=400)
r1 = p.rect(x="col", y="row", width=1, height=1,
source=source,
fill_color={'field': 'values', 'transform': mapper},
line_color=None)
color_bar = ColorBar(color_mapper=mapper, ticker=LogTicker(),
label_standoff=12, border_line_color=None,
location(0,0))
p.add_layout(color_bar, 'left')
layout = p
show(layout)
我喜欢这种方法的优雅。这种方法的唯一缺点是,您无法获得定义给定颜色的清晰数字。
如果其他人想出更优雅的方法,请 共享!