仅显示散景图例中的主要类别
Show only major category in bokeh legend
我想让 bokeh 显示分类条形图数据的图例,但要控制图例中显示的类别级别。
例如使用下面的散景示例代码,我希望图例仅显示年份。所以“2015”、“2016”、“2017”,而不是现在的"Apples, 2015"等等
此外,我试图隐藏 x 轴上显示的年份,因此它只显示水果。
我已经在 bokeh 的文档中搜索了一段时间,但看不到如何执行此操作。我想我需要在创建 vbar 时将图例属性设置为某种格式字符串,但我不知道允许使用哪些格式。执行此操作的正确方法是什么?
from bokeh.io import show, output_file
from bokeh.models import ColumnDataSource, FactorRange
from bokeh.plotting import figure
from bokeh.transform import factor_cmap
output_file("bars.html")
fruits = ['Apples', 'Pears', 'Nectarines', 'Plums', 'Grapes', 'Strawberries']
years = ['2015', '2016', '2017']
data = {'fruits' : fruits,
'2015' : [2, 1, 4, 3, 2, 4],
'2016' : [5, 3, 3, 2, 4, 6],
'2017' : [3, 2, 4, 4, 5, 3]}
# this creates [ ("Apples", "2015"), ("Apples", "2016"), ("Apples", "2017"), ("Pears", "2015), ... ]
x = [ (fruit, year) for fruit in fruits for year in years ]
counts = sum(zip(data['2015'], data['2016'], data['2017']), ()) # like an hstack
source = ColumnDataSource(data=dict(x=x, counts=counts))
p = figure(x_range=FactorRange(*x), plot_height=250, title="Fruit Counts by Year",
toolbar_location=None, tools="")
palette = ["Red", "Green", "Blue"]
#p.vbar(x='x', top='counts', width=0.9, source=source)
p.vbar(x='x', top='counts', width=0.9, source=source, line_color="white",
fill_color=factor_cmap('x', palette=palette, factors=years, start=1, end=2),
# legend='x[0]'
legend='x',
)
p.y_range.start = 0
p.x_range.range_padding = 0.1
p.xaxis.major_label_orientation = 1
p.xgrid.grid_line_color = None
p.legend.location = "top_right"
show(p)
如果您不需要层次轴标签,则需要使用用户指南Visual Dodge section of the Handling Categorical Data 章节中描述的方法。
除非我记错了,上面的例子正是你要问的:
from bokeh.core.properties import value
from bokeh.io import show, output_file
from bokeh.models import ColumnDataSource
from bokeh.plotting import figure
from bokeh.transform import dodge
output_file("dodged_bars.html")
fruits = ['Apples', 'Pears', 'Nectarines', 'Plums', 'Grapes', 'Strawberries']
years = ['2015', '2016', '2017']
data = {'fruits' : fruits,
'2015' : [2, 1, 4, 3, 2, 4],
'2016' : [5, 3, 3, 2, 4, 6],
'2017' : [3, 2, 4, 4, 5, 3]}
source = ColumnDataSource(data=data)
p = figure(x_range=fruits, y_range=(0, 10), plot_height=250,
title="Fruit Counts by Year", toolbar_location=None, tools="")
p.vbar(x=dodge('fruits', -0.25, range=p.x_range), top='2015', width=0.2,
source=source, color="#c9d9d3", legend=value("2015"))
p.vbar(x=dodge('fruits', 0.0, range=p.x_range), top='2016', width=0.2,
source=source, color="#718dbf", legend=value("2016"))
p.vbar(x=dodge('fruits', 0.25, range=p.x_range), top='2017', width=0.2,
source=source, color="#e84d60", legend=value("2017"))
p.x_range.range_padding = 0.1
p.xgrid.grid_line_color = None
p.legend.location = "top_left"
p.legend.orientation = "horizontal"
show(p)
下面是一些动态构建图表的快速代码。单独定义increment
,然后从上面的figure
中提取:
def incrementer(labels, base_inc=0.25):
num_labels = len(labels)
midpoint = num_labels / 2 if num_labels % 2 == 0 else num_labels / 2 - 0.5
offset = base_inc * midpoint
even_offset = base_inc / 2 if num_labels % 2 == 0 else 0
return [i * base_inc - offset + even_offset for i in range(num_labels)]
.....
from bokeh.palettes import Category20
palette = Category20[20]
increments = incrementer(regions, base_inc=0.125)
for i, region in enumerate(regions):
p.vbar(
x=dodge('x', increments[i], range=p.x_range), top=region, width=0.1,
source=source, color=palette[i], legend_label=region
)
这可以通过向 ColumnDataSource
添加另一列来实现,该列映射到感兴趣的类别级别。在问题代码中,将以下内容添加到 ColumnDataSource
:
legend_names = [level1 for level0, level1 in x]
source = ColumnDataSource(data=dict(x=x, counts=counts, legend_name=legend_names))
然后更改 vbar
以将该字段用作图例(与普通图例参数相反):
p.vbar(<other arguments>, legend_field='legend_name')
这样可以轻松选择任何级别用作图例。
结果:
完整代码:
from bokeh.io import show
from bokeh.models import ColumnDataSource, FactorRange
from bokeh.plotting import Figure
from bokeh.transform import factor_cmap
fruits = ['Apples', 'Pears', 'Nectarines', 'Plums', 'Grapes', 'Strawberries']
years = ['2015', '2016', '2017']
data = {'fruits': fruits,
'2015': [2, 1, 4, 3, 2, 4],
'2016': [5, 3, 3, 2, 4, 6],
'2017': [3, 2, 4, 4, 5, 3]}
x = [(fruit, year) for fruit in fruits for year in years]
counts = sum(zip(data['2015'], data['2016'], data['2017']), ())
legend_names = [level1 for level0, level1 in x]
source = ColumnDataSource(data=dict(x=x, counts=counts, legend_name=legend_names))
figure = Figure(x_range=FactorRange(*x), plot_height=250, title="Fruit Counts by Year",
toolbar_location=None, tools="")
palette = ["Red", "Green", "Blue"]
figure.vbar(x='x', top='counts', width=0.9, source=source, line_color="white",
fill_color=factor_cmap('x', palette=palette, factors=years, start=1, end=2),
legend_field='legend_name')
figure.y_range.start = 0
figure.x_range.range_padding = 0.1
figure.xaxis.major_label_orientation = 1
figure.xgrid.grid_line_color = None
figure.legend.location = "top_right"
show(figure)
我想让 bokeh 显示分类条形图数据的图例,但要控制图例中显示的类别级别。
例如使用下面的散景示例代码,我希望图例仅显示年份。所以“2015”、“2016”、“2017”,而不是现在的"Apples, 2015"等等
此外,我试图隐藏 x 轴上显示的年份,因此它只显示水果。
我已经在 bokeh 的文档中搜索了一段时间,但看不到如何执行此操作。我想我需要在创建 vbar 时将图例属性设置为某种格式字符串,但我不知道允许使用哪些格式。执行此操作的正确方法是什么?
from bokeh.io import show, output_file
from bokeh.models import ColumnDataSource, FactorRange
from bokeh.plotting import figure
from bokeh.transform import factor_cmap
output_file("bars.html")
fruits = ['Apples', 'Pears', 'Nectarines', 'Plums', 'Grapes', 'Strawberries']
years = ['2015', '2016', '2017']
data = {'fruits' : fruits,
'2015' : [2, 1, 4, 3, 2, 4],
'2016' : [5, 3, 3, 2, 4, 6],
'2017' : [3, 2, 4, 4, 5, 3]}
# this creates [ ("Apples", "2015"), ("Apples", "2016"), ("Apples", "2017"), ("Pears", "2015), ... ]
x = [ (fruit, year) for fruit in fruits for year in years ]
counts = sum(zip(data['2015'], data['2016'], data['2017']), ()) # like an hstack
source = ColumnDataSource(data=dict(x=x, counts=counts))
p = figure(x_range=FactorRange(*x), plot_height=250, title="Fruit Counts by Year",
toolbar_location=None, tools="")
palette = ["Red", "Green", "Blue"]
#p.vbar(x='x', top='counts', width=0.9, source=source)
p.vbar(x='x', top='counts', width=0.9, source=source, line_color="white",
fill_color=factor_cmap('x', palette=palette, factors=years, start=1, end=2),
# legend='x[0]'
legend='x',
)
p.y_range.start = 0
p.x_range.range_padding = 0.1
p.xaxis.major_label_orientation = 1
p.xgrid.grid_line_color = None
p.legend.location = "top_right"
show(p)
如果您不需要层次轴标签,则需要使用用户指南Visual Dodge section of the Handling Categorical Data 章节中描述的方法。
除非我记错了,上面的例子正是你要问的:
from bokeh.core.properties import value
from bokeh.io import show, output_file
from bokeh.models import ColumnDataSource
from bokeh.plotting import figure
from bokeh.transform import dodge
output_file("dodged_bars.html")
fruits = ['Apples', 'Pears', 'Nectarines', 'Plums', 'Grapes', 'Strawberries']
years = ['2015', '2016', '2017']
data = {'fruits' : fruits,
'2015' : [2, 1, 4, 3, 2, 4],
'2016' : [5, 3, 3, 2, 4, 6],
'2017' : [3, 2, 4, 4, 5, 3]}
source = ColumnDataSource(data=data)
p = figure(x_range=fruits, y_range=(0, 10), plot_height=250,
title="Fruit Counts by Year", toolbar_location=None, tools="")
p.vbar(x=dodge('fruits', -0.25, range=p.x_range), top='2015', width=0.2,
source=source, color="#c9d9d3", legend=value("2015"))
p.vbar(x=dodge('fruits', 0.0, range=p.x_range), top='2016', width=0.2,
source=source, color="#718dbf", legend=value("2016"))
p.vbar(x=dodge('fruits', 0.25, range=p.x_range), top='2017', width=0.2,
source=source, color="#e84d60", legend=value("2017"))
p.x_range.range_padding = 0.1
p.xgrid.grid_line_color = None
p.legend.location = "top_left"
p.legend.orientation = "horizontal"
show(p)
下面是一些动态构建图表的快速代码。单独定义increment
,然后从上面的figure
中提取:
def incrementer(labels, base_inc=0.25):
num_labels = len(labels)
midpoint = num_labels / 2 if num_labels % 2 == 0 else num_labels / 2 - 0.5
offset = base_inc * midpoint
even_offset = base_inc / 2 if num_labels % 2 == 0 else 0
return [i * base_inc - offset + even_offset for i in range(num_labels)]
.....
from bokeh.palettes import Category20
palette = Category20[20]
increments = incrementer(regions, base_inc=0.125)
for i, region in enumerate(regions):
p.vbar(
x=dodge('x', increments[i], range=p.x_range), top=region, width=0.1,
source=source, color=palette[i], legend_label=region
)
这可以通过向 ColumnDataSource
添加另一列来实现,该列映射到感兴趣的类别级别。在问题代码中,将以下内容添加到 ColumnDataSource
:
legend_names = [level1 for level0, level1 in x]
source = ColumnDataSource(data=dict(x=x, counts=counts, legend_name=legend_names))
然后更改 vbar
以将该字段用作图例(与普通图例参数相反):
p.vbar(<other arguments>, legend_field='legend_name')
这样可以轻松选择任何级别用作图例。
结果:
完整代码:
from bokeh.io import show
from bokeh.models import ColumnDataSource, FactorRange
from bokeh.plotting import Figure
from bokeh.transform import factor_cmap
fruits = ['Apples', 'Pears', 'Nectarines', 'Plums', 'Grapes', 'Strawberries']
years = ['2015', '2016', '2017']
data = {'fruits': fruits,
'2015': [2, 1, 4, 3, 2, 4],
'2016': [5, 3, 3, 2, 4, 6],
'2017': [3, 2, 4, 4, 5, 3]}
x = [(fruit, year) for fruit in fruits for year in years]
counts = sum(zip(data['2015'], data['2016'], data['2017']), ())
legend_names = [level1 for level0, level1 in x]
source = ColumnDataSource(data=dict(x=x, counts=counts, legend_name=legend_names))
figure = Figure(x_range=FactorRange(*x), plot_height=250, title="Fruit Counts by Year",
toolbar_location=None, tools="")
palette = ["Red", "Green", "Blue"]
figure.vbar(x='x', top='counts', width=0.9, source=source, line_color="white",
fill_color=factor_cmap('x', palette=palette, factors=years, start=1, end=2),
legend_field='legend_name')
figure.y_range.start = 0
figure.x_range.range_padding = 0.1
figure.xaxis.major_label_orientation = 1
figure.xgrid.grid_line_color = None
figure.legend.location = "top_right"
show(figure)