I'd like to use multiple Hovertools in one plot together with Hovertool's names attribute to selectivly apply each tool. Take for instance
hover1 = HoverTool(tooltips=[("group", "1")], names = ['line1'])
hover2 = HoverTool(tooltips=[("group", "2")], names = ['lines2'])
and the two data sources:
source1 = ColumnDataSource(data=dict(
xs=[[1, 3, 2], [3, 4, 6, 6]],
ys=[[2, 1, 4], [4, 7, 8, 5]],
))
source2 = ColumnDataSource(data=dict(
xs=[[1, 3, 2], [6, 7, 9, 8]],
ys=[[-1, 0, 1], [1, 1, 2, 1]]
))
I'd though the following (using the bokeh.models API) should do what I want
p = figure(plot_width=400, plot_height=400)
l1 = MultiLine(xs='xs', ys='ys', name='lines1')
l2 = MultiLine(xs='xs', ys='ys', name='lines2')
p.add_tools(hover)
p.add_tools(hover2)
p.add_glyph(source1, l1)
p.add_glyph(source2, l2)
show(p)
Alas the Hovertools in the resulting plot do not work (i.e. no tooltips are shown). Using the bokeh.plotting API as follows and everything works as expected:
p = figure(plot_width=400, plot_height=400, tools=[hover, hover2])
p.multi_line(xs='xs', ys='ys', source=source1, name='lines1')
p.multi_line(xs='xs', ys='ys', source=source2, name='lines2')
show(p)
Question: How does one replicate the result of the bokeh.plotting API with the bokeh.models API?
The names attribute of the HoverTool model in the Bokeh Documentation:
names: property type: List ( String )
A list of names to query for. If set, only renderers that have a matching value for their name attribute will be used.
With this
l1 = MultiLine(xs='xs', ys='ys', name='lines1')
You are assigning the name to the Multiline object and that is a glyph, not a renderer. So try this instead
from bokeh.io import output_notebook, show
output_notebook()
import numpy as np
from bokeh.plotting import figure
from bokeh.models.sources import ColumnDataSource
from bokeh.models.glyphs import MultiLine
from bokeh.layouts import row
from bokeh.models.tools import HoverTool
source = ColumnDataSource(data=dict(
xs1=[[1, 2, 3], [5, 6, 7]],
ys1=[[1, 2, 3], [6, 5, 7]],
xs2=[[7, 8, 9], [1, 2, 3]],
ys2=[[4, 5, 7], [6, 7, 2]],
)
)
hover1 = HoverTool(tooltips=[("group", "1")], names = ['lines1'])
hover2 = HoverTool(tooltips=[("group", "2")], names = ['lines2'])
p = figure(plot_width=400, plot_height=400)
l1 = MultiLine(xs='xs1', ys='ys1')
l2 = MultiLine(xs='xs2', ys='ys2')
r1 = p.add_glyph(source, l1, name='lines1') # the name is assigned to the renderer
r2 = p.add_glyph(source, l2, name='lines2')
# r1.name = 'lines1' # or you could assign the name like this as well
# r2.name = 'lines2'
p.add_tools(hover1)
p.add_tools(hover2)
# p = figure(plot_width=400, plot_height=400, tools=[hover1, hover2])
# p.multi_line(xs='xs1', ys='ys1', source=source, name='lines1')
# p.multi_line(xs='xs2', ys='ys2', source=source, name='lines2')
show(p)
Related
I am trying to create a simple area chart in bokeh (1 layer)
My attempt
df_example = pd.DataFrame(data= [['01-01-2018',10],['02-01-2018', 5 ], ['03-01-2018',7]], columns = ['date', 'value'] )
p = figure(plot_width=600, plot_height=400, x_range = df_example['date'])
p.Area(df_example, x='date', y='value')
show(p)
I get an error
AttributeError: 'Figure' object has no attribute 'Area'
Is the Area chart seems to be not available in bokeh anymore
Can anybody demonstrate how to get this type of chart please?
Bokeh recently added a varea_stack glyph method:
from bokeh.models import ColumnDataSource
from bokeh.plotting import figure, show
source = ColumnDataSource(data=dict(
x=[1, 2, 3, 4, 5],
y1=[1, 2, 4, 3, 4],
y2=[1, 4, 2, 2, 3],
))
p = figure(plot_width=400, plot_height=400)
p.varea_stack(['y1', 'y2'], x='x', color=("grey", "lightgrey"), source=source)
show(p)
I plot lines from some columns of a dataframe. I would like the hover tool to display the name of the column that originated that data and also some information from other columns not plotted.
For example, in the code below I would like the hover tool to display "Name = A; Aux = 0.1" when the mouse is over the central point on line A. This value is stored in column A1. Conversely, when over the central point on line B the tool should display "Name = B; Aux = 0.3"
from bokeh.io import show
from bokeh.models import HoverTool, ColumnDataSource
from bokeh.plotting import figure
import pandas as pd
df = pd.DataFrame({'x': [1, 2, 3], 'A' : [1, 5, 3], 'A1': [0.2, 0.1, 0.2],
'B' : [2, 4, 3], 'B1':[0.1, 0.3, 0.2]})
tools_to_show = 'box_zoom,save,hover,reset'
p = figure(plot_height =300, plot_width = 1200,
toolbar_location='above',
tools=tools_to_show)
columns = ['A', 'B']
source = ColumnDataSource(df)
for col in columns:
p.line('x', col, source=source)
hover = p.select(dict(type=HoverTool))
hover.tooltips = [("Name","#col"), ("Aux", "#col1")]
hover.mode = 'mouse'
show(p)
Thanks!
There is a recent feature to support this. With Bokeh 0.13.0 or newer, you can set the name on a glyph and refer to that name in a tooltip with $name. Additionally, you can refer to a column with that name with #$name. However, the "indirection" column has to be the one specified in name, so you will have to re-arrange your column names to this expectation:
from bokeh.io import show
from bokeh.models import ColumnDataSource
from bokeh.plotting import figure
import pandas as pd
df = pd.DataFrame({'x': [1, 2, 3], 'A_y' : [1, 5, 3], 'A': [0.2, 0.1, 0.2],
'B_y' : [2, 4, 3], 'B':[0.1, 0.3, 0.2]})
tools_to_show = 'box_zoom,save,hover,reset'
p = figure(plot_height =300, plot_width = 1200,
toolbar_location='above', tools=tools_to_show,
# "easy" tooltips in Bokeh 0.13.0 or newer
tooltips=[("Name","$name"), ("Aux", "#$name")])
columns = ['A', 'B']
source = ColumnDataSource(df)
for col in columns:
# have to use different colnames for y-coords so tooltip can refer to #$name
p.line('x', col + "_y", source=source, name=col)
show(p)
You can easily remove Bokeh logo from a single figure doing the following:
from bokeh.plotting import figure, show
from bokeh.models.tools import PanTool, SaveTool
p = figure()
p.line([1, 2, 3, 4],[1, 4, 3, 0])
p.toolbar.logo = None
p.tools = [SaveTool(), PanTool()]
show(p)
or just using p.toolbar_location = None
I, however, didn't manage to hide it when having multiple figures:
from bokeh.plotting import figure, show
from bokeh.models.tools import PanTool, SaveTool
from bokeh.layouts import gridplot
from bokeh.models import ColumnDataSource, BoxZoomTool, WheelZoomTool, LassoSelectTool, BoxSelectTool, ResetTool, \
PanTool, TapTool, SaveTool
tools = [PanTool(), BoxZoomTool(match_aspect=True), WheelZoomTool(), BoxSelectTool(),
ResetTool(), TapTool(), SaveTool()]
figures = [figure(plot_width=800, plot_height=800,
tools=tools, output_backend="webgl", match_aspect=True) for i in range(2)]
figures[0].line([1, 2, 3, 4], [1, 4, 3, 0])
figures[0].toolbar.logo = None
figures[1].line([1, 2, 3, 4], [1, 4, 3, 0])
figures[1].toolbar.logo = None
show(gridplot([figures], merge_tools=True, sizing_mode='scale_height'))
I've also tried figures.toolbar.logo = None but of course it doesn't work as it's a list and it has no such attribute. How can i do that?
You can configured toolbar options to gridplot by passing a toolbar_options argument to gridplot:
grid = gridplot([figures], merge_tools=True, sizing_mode='scale_height',
toolbar_options=dict(logo=None))
show(grid)
This is documented in the Reference Guide entry for gridplot
logo=None didn't work for me. This css declaration did however:
<style>
.bk-logo {
display:none !important;
}
</style>
I am trying to make Bokeh Panels that have relatively complex layouts, so I tried moving half of my current layout into one Panel and half into another just to play around, like so:
selects = HBox(top_users_select, new_users_select, t1_users_select, t2_users_select, top_recent_users_select)
tab1 = Panel(inputs)
tab2 = Panel(VBox(HBox(plot2, plot1, plot3, plot4), HBox(plot5, plot6, plot7, plot8), data_table))
tabs = tabs(tab1, tab2)
show(tabs)
However this is giving me the following error:
File "main_panel.py", line 589, in <module>:
tab1 = Panel(inputs) Traceback (most recent call last):
File "/Users/joe/anaconda3/lib/python3.5/site-packages/bokeh/application/handlers/code_runner.py", line 71, in run
exec(self._code, module.__dict__)
File "/Users/joe/Desktop/scripts/src/main/python/Bokeh apps/insights/main_panel.py", line 589, in <module>
tab1 = Panel(inputs)
TypeError: __init__() takes 1 positional argument but 2 were given
I am fairly new to Bokeh, and looking at the docs I don't know exactly how to parse this error and get around it. Can someone point me to an example of laying out fairly complex grids in a Bokeh panel or tell me what the error means and how I can address it?
You can use row or column to create complex layouts within tabs.
You can even mix them like row(column(button1, button2), button3)
Example:
from bokeh.models.widgets import Panel, Tabs, Toggle, TextInput
from bokeh.io import output_notebook, show
from bokeh.plotting import figure
from bokeh.layouts import column, row
p1 = figure(plot_width=300, plot_height=300)
p1.circle([1, 2, 3, 4, 5], [6, 7, 2, 4, 5], size=20, color="navy", alpha=0.5)
p2 = figure(plot_width=300, plot_height=300)
p2.line([1, 2, 3, 4, 5], [6, 7, 2, 4, 5], line_width=3, color="navy", alpha=0.5)
toggle1 = Toggle(label="Foo", button_type="success")
toggle2 = Toggle(label="Foo", button_type="warning")
text_input = TextInput(value="default", title="Label:")
tab1 = Panel(child=row(p1,toggle2), title="circle")
tab2 = Panel(child=column(p2,toggle1, text_input), title="line")
tabs = Tabs(tabs=[ tab1, tab2 ])
output_notebook()
show(tabs)
See https://docs.bokeh.org/en/latest/docs/user_guide/layout.html for more details
I think you want to write selects instead of inputs, but there are basically some things wrong with your declaration.
Look at the examples at http://docs.bokeh.org/en/latest/docs/user_guide/interaction/widgets.html#tabs
from bokeh.models.widgets import Panel, Tabs
from bokeh.io import output_file, show
from bokeh.plotting import figure
output_file("slider.html")
p1 = figure(plot_width=300, plot_height=300)
p1.circle([1, 2, 3, 4, 5], [6, 7, 2, 4, 5], size=20, color="navy", alpha=0.5)
tab1 = Panel(child=p1, title="circle")
p2 = figure(plot_width=300, plot_height=300)
p2.line([1, 2, 3, 4, 5], [6, 7, 2, 4, 5], line_width=3, color="navy", alpha=0.5)
tab2 = Panel(child=p2, title="line")
tabs = Tabs(tabs=[ tab1, tab2 ])
show(tabs)
Your input in Panel should be assigned to child= and a Panel needs a title=.
Also change
tabs = tabs(tab1, tab2)
to
tabs = Tabs(tabs=[tab1,tab2,tab3,tab4])
Note from maintainers: The specifics of this question concern the bokeh.charts API which is obsolete and was removed several years ago. In modern Bokeh, specify toolbar_location:
p = figure(toolbar_location=None)
OBSOLETE:
I don't seem to be able to remove the toolbar from a bokeh Bar chart. Despite setting the tools argument to None (or False or '') I always end up with the bokeh logo and a grey line, e.g. with this code:
from bokeh.charts import Bar, output_file, show
# prepare some data
data = {"y": [6, 7, 2, 4, 5], "z": [1, 5, 12, 4, 2]}
# output to static HTML file
output_file("bar.html")
# create a new line chat with a title and axis labels
p = Bar(data, cat=['C1', 'C2', 'C3', 'D1', 'D2'], title="Bar example",
xlabel='categories', ylabel='values', width=400, height=400,
tools=None)
# show the results
show(p)
However, when I try the same with a bokeh plot, it works perfectly fine and the toolbar is gone, e.g. with this code:
from bokeh.plotting import figure, output_file, show
output_file("line.html")
p = figure(plot_width=400, plot_height=400, toolbar_location=None)
# add a line renderer
p.line([1, 2, 3, 4, 5], [6, 7, 2, 4, 5], line_width=2)
show(p)
Does anyone know what I'm doing wrong?
If you want to remove the logo and the toolbar you can do:
p.toolbar.logo = None
p.toolbar_location = None
Hope this resolves your problem
On any Bokeh plot object you can set:
p.toolbar_location = None