Bokeh, how do I add the "?" in the configuring plot tool - bokeh

I could not find the information regarding the helptool on the bokeh documentation. There is an explanation for all other tools but not this one. I am talking about these tools from the toolbar:
http://docs.bokeh.org/en/latest/docs/user_guide/tools.html
I can choose most of the plot tools I want to use with no problem. I want to include the helptool, which is clearly visible just before the bokeh logo, however I cannot find any direct reference to it.
I just tested it(!), if you want the Helptool, which has a "?" sybmol, it will only be included by default if you do not specify the tools displayed with the plot. OK I will go with this but I will have no "?" if I choose the tools.

I understand your problem I think. You are saying that by default the tool panel will include the help tool. When you specify all the tools from scratch, help tool is not included as default.
If you generate the plot without specifying any tools, then list all tools on the plot:
p.tools
>>>>
[PanTool(id='450f2e26-e0e5-4d90-89c4-44d20f2f688b', ...),
WheelZoomTool(id='84011ce1-4f73-4abb-abd1-26a830b70635', ...),
BoxZoomTool(id='adbfb29a-aa7d-4883-8f8f-d12b7c5af139', ...),
SaveTool(id='ff6ba8bb-c487-418d-82e5-28ff0402e2d6', ...),
ResetTool(id='dfac2559-da4c-4902-829d-f795ee0bfd56', ...),
HelpTool(id='1141330c-e9ff-4e5b-a737-3517c24f263e', ...)]
so you can see there is a helptool. Also it is in the documents
http://docs.bokeh.org/en/latest/docs/reference/models/tools.html#bokeh.models.tools.HelpTool
Therefore you can import this tool and add it to the plot in two ways:
from bokeh.plotting import figure, output_file, show
from bokeh.models import HelpTool
output_file("toolbar.html")
# create a new plot with the toolbar below
p = figure(plot_width=400, plot_height=400,
title=None, toolbar_location="below", tools="pan,wheel_zoom,box_zoom,reset")
p.add_tools(HelpTool())
p.circle([1, 2, 3, 4, 5], [2, 5, 8, 2, 7], size=10)
show(p)
Or more simply:
from bokeh.plotting import figure, output_file, show
output_file("toolbar.html")
# create a new plot with the toolbar below
p = figure(plot_width=400, plot_height=400,
title=None, toolbar_location="right",tools = "pan,wheel_zoom,box_zoom,reset,help")
p.circle([1, 2, 3, 4, 5], [2, 5, 8, 2, 7], size=10)
show(p)

Related

Bokeh manual stack bar plot missing level in display

I try to manually create a stacked bar plot in bokeh as I can do in matplotlib. The code works but the output plot shows some issues I cannot explain or solve. To me, it seems like the error always appear at the second level, no matter if I have two levels (i.e. number of bars) or three levels stacked. In the three levels plot, the color is miss matched due to the missing second level.
from bokeh.models import ColumnDataSource
from bokeh.plotting import figure, show
from bokeh.io import output_notebook
import numpy as np
output_notebook()
test_data = {
'index' : np.array([1, 2, 3, 4, 5]),
'a' : np.array([10, 20, 30, 40, 50]),
'b' : np.array([10, 10, 10, 10, 10]),
'c' : np.array([10, 10, 10, 10, 10])
}
s = ColumnDataSource(test_data)
alpha_lst = [1, 0.5, 0.1]
keys = list(s.data.keys())[1:-1] # stack 2 levels/bars
# keys = list(s.data.keys())[1:] # stack 3 levels/bars
w_bar = 0.9
level = 0
p = figure(plot_width=600, plot_height=360)
for j in range(len(keys)):
p.vbar(x=s.data['index'], bottom=level,
top=level+s.data[keys[j]], width=w_bar, color='#43a2ca',
line_color='#3A5785', fill_alpha=alpha_lst[j], legend_label=keys[j])
level += s.data[keys[j]]
p.legend.location = 'top_left'
show(p)
Stacked Bar 2 Levels:
Stacked Bar 3 Levels:
Two reasons why level += s.data[keys[j]] is bad:
You change the variable type from int to numpy.array. I maaaaybe OK in this case, but generally it makes it harder to make sense of and debug later on
After it becomes an array (i.e. at the end of the very first loop iteration), the next execution of that line mutates the array in place. Meaning, the VBar that was created by the second call to p.vbar now has bottom with the same value as top.
It's up to you how (and whether) you fix #1. And to fix #2, which will solve your main problem, just replace level += s.data[keys[j]] with level = level + s.data[keys[j]].

How does one show the cdf from histogram data using holoviews?

I'm using holoviews with bokeh backend for interactive visualizations. I have a histogram with edges and frequency data. What is an elegant way of overlaying my histogram with the cumulative distribution (cdf) curve?
I tried using the cumsum option in hv.dim but don't think i'm doing it right. The help simply says,
Help on function cumsum in module holoviews.util.transform:
cumsum(self, **kwargs)
My code looks something like,
df_hist = pd.DataFrame(columns=['edges', 'freq'])
df_hist['edges'] = [-2, -1, 0, 1, 2]
df_hist['freq'] = [1, 3, 5, 3, 1]
hv.Histogram((df_hist.edges, df_hist.freq))
The result is a histogram plot.
Is there something like a...
hv.Histogram((df_hist.edges, df_hist.freq), type='cdf')
... to show the cumulative distribution?
One possible solution is by using histogram(cumulative=True) as follows:
from holoviews.operation import histogram
histogram(hv.Histogram((df_hist.edges, df_hist.freq)), cumulative=True)
More info on transforming elements here:
http://holoviews.org/user_guide/Transforming_Elements.html
Or a more general solution by turning the original data into a hv.Dataset():
import holoviews as hv
import seaborn as sns
hv.extension('bokeh')
iris = sns.load_dataset('iris')
hv_data = hv.Dataset(iris['petal_width'])
histogram(hv_data, cumulative=True)
But I like using library hvplot, which is built on top of Holoviews, even more:
import hvplot
import hvplot.pandas
iris['petal_width'].hvplot.hist(cumulative=True)

Bokeh Hovertool for patch

Is the hover tool for patch different than other glyphs? The plot can see the index for circle but not for patch.
output_file("patch.html")
TOOLTIPS = [
("index", "$index"),
]
p = figure(plot_width=400, plot_height=400, tooltips=TOOLTIPS, tools='hover,help')
# add a patch renderer with an alpha an line width
p.patch([1, 2, 3, 4, 5], [6, 7, 8, 7, 3], alpha=0.5, line_width=2)
p.circle([2], [4],size=20, line_width=2)
show(p)
As of Bokeh 1.0.2, hit testing has not been implemented for Patch, i.e. it is invisible as far as the Hover tool is concerned. You could use the vectorized patches glyph method instead:
p.patches([[1, 2, 3, 4, 5]], [[6, 7, 8, 7, 3]], alpha=0.5, line_width=2)
However, this will always only return 0 as the value of $index since there is only just the one patch (whose index is 0). If you are looking to get "index" values for the vertices of the patch, you will need to do something like plot invisible circles at the same locations as the vertices, that are only there for hit-testing purposes (to drive the hover tool)

Bokeh simple bar chart

I'm new to the method. I created the following input, but it gives me an empty output. What did I miss? Thank you.
import pandas as pd
from bokeh.charts import Bar
import pandas as pd
from bokeh.plotting import figure, output_file, show
mortality_age = pd.read_csv("mortality_by_age.csv")
x=mortality_age["Age Range"]
y=mortality_age["Deaths per 100,000 Live Births:"]
plot = figure(title="Example of a vertical bar chart")
plot.vbar(x, top=y, width=0.5,color="#CAB2D6")
output_file("vertical_bar.html", mode="inline")
show(plot)
what version of Bokeh are you using?
Using 12.10, I have managed to get a plot to show using the code below, using the example contained in the documentation.
# import pandas as pd
from bokeh.plotting import figure, output_file, show
# from bokeh.charts import Bar # I had issues with this line working
# mortality_age = pd.read_csv("mortality_by_age.csv")
# x=mortality_age["Age Range"]
# y=mortality_age["Deaths per 100,000 Live Births:"]
x=[1, 2, 3, 4, 5]
y=[6, 7, 6, 4, 5]
plot = figure(title="Example of a vertical bar chart")
plot.vbar(x=[1, 2, 3, 4, 5], top=y, width=0.5, color="#CAB2D6")
output_file("vertical_bar.html", mode="inline")
show(plot)
My recommendations would be to check the version of bokeh you are using, and then check the data contained in your csv file, it might be possible there is nothing in there.

Bokeh how to add legend to figure created by multi_line method?

I'm trying to add legend to a figure, which contains two lines created by multi_line method.
Example:
p = figure(plot_width=300, plot_height=300)
p.multi_line(xs=[[4, 2, 5], [1, 3, 4]], ys=[[6, 5, 2], [6, 5, 7]], color=['blue','yellow'], legend="first")
In this case the legend is only for the first line. When the legend is defined as a list there is an error:
p.multi_line(xs=[[4, 2, 5], [1, 3, 4]], ys=[[6, 5, 2], [6, 5, 7]], color=['blue','yellow'], legend=["first","second"])
Is it possible to add legend to many lines?
Maintainer Note : PR #8218 which will be merged for Bokeh 1.0, allows legends to be created directly for multi line and patches, without any looping.
To make it faster, when you have a lot of data or a big table etc. You can make a for loop:
1) Make a list of colors and legends
You can always import bokeh paletts for your colors
from bokeh.palettes import "your palett"
Check this link: bokeh.palets
colors_list = ['blue', 'yellow']
legends_list = ['first', 'second']
xs=[[4, 2, 5], [1, 3, 4]]
ys=[[6, 5, 2], [6, 5, 7]]
2) Your figure
p = figure(plot_width=300, plot_height=300)
3) Make a for loop throgh the above lists and show
for (colr, leg, x, y ) in zip(colors_list, legends_list, xs, ys):
my_plot = p.line(x, y, color= colr, legend= leg)
show(p)
Maintainer Note: PR #8218 which will be merged for Bokeh 1.0, allows legends to be created directly for multi line and patches, without any looping or using separate line calls.
multi_line is intended for conceptually single things, that happen to have multiple sub-components. Think of the state of Texas, it is one logical thing, but it has several distinct (and disjoint) polygons. You might use Patches to draw all the polys for "Texas" but you'd only want one legend overall. Legends label logical things. If you want to label several lines as logically distinct things, you will have to draw them all separately with p.line(..., legend_label="...")
On more recent releases (since 0.12.15, I think) its possible to add legends to multi_line plots. You simple need to add a 'legend' entry to your data source. Here is an example taken from the Google Groups discussion forum:
data = {'xs': [np.arange(5) * 1, np.arange(5) * 2],
'ys': [np.ones(5) * 3, np.ones(5) * 4],
'labels': ['one', 'two']}
source = ColumnDataSource(data)
p = figure(width=600, height=300)
p.multi_line(xs='xs', ys='ys', legend='labels', source=source)

Resources