答案 0 :(得分:8)
更新:现在很多更容易:见
http://bokeh.pydata.org/en/latest/docs/user_guide/annotations.html#color-bars
我害怕我没有一个好的答案,这在Bokeh中应该更容易。但我之前手动完成了这样的事情。
因为我经常希望这些不在我的情节中,所以我会制作一个新的情节,然后将它与hplot
或gridplot
一起组合。
这里有一个例子:https://github.com/birdsarah/pycon_2015_bokeh_talk/blob/master/washmap/washmap/water_map.py#L179
在你的情况下,情节应该非常简单。如果您创建了这样的数据源:
| value | color
| 1 | blue
.....
| 9 | red
然后你可以这样做:
legend = figure(tools=None)
legend.toolbar_location=None
legend.rect(x=0.5, y='value', fill_color='color', width=1, height=1, source=source)
layout = hplot(main, legend)
show(legend)
但是,这确实依赖于您知道值对应的颜色。您可以将调色板传递给热图图表调用 - 如下所示:http://bokeh.pydata.org/en/latest/docs/gallery/cat_heatmap_chart.html,这样您就可以使用它来构建新的数据源。
我非常确定彩色地图周围至少有一个未解决的问题。我知道我刚添加一个用于场外传说。
答案 1 :(得分:5)
由于0.12.3版本的Bokeh有ColorBar。
此文档对我非常有用: http://bokeh.pydata.org/en/dev/docs/user_guide/annotations.html#color-bars
答案 2 :(得分:3)
以下是一些代码松散地基于Birdsarah生成颜色条的响应:
AccountCreationVC
另外,如果您对模拟matplot lib色彩图感兴趣,请尝试使用:
def generate_colorbar(palette, low=0, high=15, plot_height = 100, plot_width = 500, orientation = 'h'):
y = np.linspace(low,high,len(palette))
dy = y[1]-y[0]
if orientation.lower()=='v':
fig = bp.figure(tools="", x_range = [0, 1], y_range = [low, high], plot_width = plot_width, plot_height=plot_height)
fig.toolbar_location=None
fig.xaxis.visible = None
fig.rect(x=0.5, y=y, color=palette, width=1, height = dy)
elif orientation.lower()=='h':
fig = bp.figure(tools="", y_range = [0, 1], x_range = [low, high],plot_width = plot_width, plot_height=plot_height)
fig.toolbar_location=None
fig.yaxis.visible = None
fig.rect(x=y, y=0.5, color=palette, width=dy, height = 1)
return fig
答案 3 :(得分:3)
由于此处的其他答案看起来非常复杂,这里有一段容易理解的代码,可以在散热图上生成颜色条。
import numpy as np
from bokeh.plotting import figure, show
from bokeh.models import LinearColorMapper, BasicTicker, ColorBar
data = np.random.rand(10,10)
color_mapper = LinearColorMapper(palette="Viridis256", low=0, high=1)
plot = figure(x_range=(0,1), y_range=(0,1))
plot.image(image=[data], color_mapper=color_mapper,
dh=[1.0], dw=[1.0], x=[0], y=[0])
color_bar = ColorBar(color_mapper=color_mapper, ticker= BasicTicker(),
location=(0,0))
plot.add_layout(color_bar, 'right')
show(plot)
答案 4 :(得分:2)
要做到这一点,我做了同样的@birdsarah。作为额外提示,如果您使用rect方法作为颜色贴图,则在颜色栏中再次使用rect方法并使用相同的源。最终结果是您可以选择颜色条的各个部分,并在图中选择。
尝试一下:
答案 5 :(得分:0)
这也是我的愿望清单。如果绘制的数据改变(例如,移动通过3D数据集的一个维度),则还需要自动调整范围。下面的代码做了一些人们可能会觉得有用的东西。诀窍是在颜色栏中添加一个额外的轴,当数据发生变化时,你可以通过数据源控制它。
import numpy
from bokeh.plotting import Figure
from bokeh.models import ColumnDataSource, Plot, LinearAxis
from bokeh.models.mappers import LinearColorMapper
from bokeh.models.ranges import Range1d
from bokeh.models.widgets import Slider
from bokeh.models.widgets.layouts import VBox
from bokeh.core.properties import Instance
from bokeh.palettes import RdYlBu11
from bokeh.io import curdoc
class Colourbar(VBox):
plot = Instance(Plot)
cbar = Instance(Plot)
power = Instance(Slider)
datasrc = Instance(ColumnDataSource)
cbarrange = Instance(ColumnDataSource)
cmap = Instance(LinearColorMapper)
def __init__(self):
self.__view_model__ = "VBox"
self.__subtype__ = "MyApp"
super(Colourbar,self).__init__()
numslices = 6
x = numpy.linspace(1,2,11)
y = numpy.linspace(2,4,21)
Z = numpy.ndarray([numslices,y.size,x.size])
for i in range(numslices):
for j in range(y.size):
for k in range(x.size):
Z[i,j,k] = (y[j]*x[k])**(i+1) + y[j]*x[k]
self.power = Slider(title = 'Power',name = 'Power',start = 1,end = numslices,step = 1,
value = round(numslices/2))
self.power.on_change('value',self.inputchange)
z = Z[self.power.value]
self.datasrc = ColumnDataSource(data={'x':x,'y':y,'z':[z],'Z':Z})
self.cmap = LinearColorMapper(palette = RdYlBu11)
r = Range1d(start = z.min(),end = z.max())
self.cbarrange = ColumnDataSource(data = {'range':[r]})
self.plot = Figure(title="Colourmap plot",x_axis_label = 'x',y_axis_label = 'y',
x_range = [x[0],x[-1]],y_range=[y[0],y[-1]],
plot_height = 500,plot_width = 500)
dx = x[1] - x[0]
dy = y[1] - y[0]
self.plot.image('z',source = self.datasrc,x = x[0]-dx/2, y = y[0]-dy/2,
dw = [x[-1]-x[0]+dx],dh = [y[-1]-y[0]+dy],
color_mapper = self.cmap)
self.generate_colorbar()
self.children.append(self.power)
self.children.append(self.plot)
self.children.append(self.cbar)
def generate_colorbar(self,cbarlength = 500,cbarwidth = 50):
pal = RdYlBu11
minVal = self.datasrc.data['z'][0].min()
maxVal = self.datasrc.data['z'][0].max()
vals = numpy.linspace(minVal,maxVal,len(pal))
self.cbar = Figure(tools = "",x_range = [minVal,maxVal],y_range = [0,1],
plot_width = cbarlength,plot_height = cbarwidth)
self.cbar.toolbar_location = None
self.cbar.min_border_left = 10
self.cbar.min_border_right = 10
self.cbar.min_border_top = 0
self.cbar.min_border_bottom = 0
self.cbar.xaxis.visible = None
self.cbar.yaxis.visible = None
self.cbar.extra_x_ranges = {'xrange':self.cbarrange.data['range'][0]}
self.cbar.add_layout(LinearAxis(x_range_name = 'xrange'),'below')
for r in self.cbar.renderers:
if type(r).__name__ == 'Grid':
r.grid_line_color = None
self.cbar.rect(x = vals,y = 0.5,color = pal,width = vals[1]-vals[0],height = 1)
def updatez(self):
data = self.datasrc.data
newdata = data
z = data['z']
z[0] = data['Z'][self.power.value - 1]
newdata['z'] = z
self.datasrc.trigger('data',data,newdata)
def updatecbar(self):
minVal = self.datasrc.data['z'][0].min()
maxVal = self.datasrc.data['z'][0].max()
self.cbarrange.data['range'][0].start = minVal
self.cbarrange.data['range'][0].end = maxVal
def inputchange(self,attrname,old,new):
self.updatez()
self.updatecbar()
curdoc().add_root(Colourbar())