simple 1 layer area chart in bokeh - python

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)

Related

Plotly: Annotate marker at the last value in line chart

I am trying to mark the last value of the line chart with a big red dot in plotly express python, could someone please help me?
I am successful in building the line chart but not able to annotate the dot.
Below is my dataframe and I want the last value in the dataframe to be annotated.
Below is the line chart created and I want my chart to be similar to the second image in the screenshot
Code I am working with:
fig = px.line(gapdf, x='gap', y='clusterCount', text="clusterCount")
fig.show()
The suggestion from gflavia works perfectly well.
But you can also set up an extra trace and associated text by addressing the elements in the figure directly instead of the data source like this:
fig.add_scatter(x = [fig.data[0].x[-1]], y = [fig.data[0].y[-1]])
Plot 1
Complete code:
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
gapdf = pd.DataFrame({
'clusterCount': [1, 2, 3, 4, 5, 6, 7, 8],
'gap': [-15.789, -14.489, -13.735, -13.212, -12.805, -12.475, -12.202, -11.965]
})
fig = px.line(gapdf, x='gap', y='clusterCount')
fig.add_scatter(x = [fig.data[0].x[-1]], y = [fig.data[0].y[-1]],
mode = 'markers + text',
marker = {'color':'red', 'size':14},
showlegend = False,
text = [fig.data[0].y[-1]],
textposition='middle right')
fig.show()
You could overlay an additional trace for the last data point with plotly.graph_objects:
import pandas as pd
import plotly.express as px
import plotly.graph_objects as go
gapdf = pd.DataFrame({
'clusterCount': [1, 2, 3, 4, 5, 6, 7, 8],
'gap': [-15.789, -14.489, -13.735, -13.212, -12.805, -12.475, -12.202, -11.965]
})
fig = px.line(gapdf, x='gap', y='clusterCount')
fig.add_trace(go.Scatter(x=[gapdf['gap'].iloc[-1]],
y=[gapdf['clusterCount'].iloc[-1]],
text=[gapdf['clusterCount'].iloc[-1]],
mode='markers+text',
marker=dict(color='red', size=10),
textfont=dict(color='green', size=20),
textposition='top right',
showlegend=False))
fig.update_layout(plot_bgcolor='white',
xaxis=dict(linecolor='gray', mirror=True),
yaxis=dict(linecolor='gray', mirror=True))
fig.show()

Using multiple bokeh HoverTool instances together with the models API

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)

Bokeh: tools='reset' makes the graph fixed

I wanted to put only reset toolbar on by the graph, so I was trying to like
logo=None, tools='reset'
The reset button is actually placed but instead the graph is fixed and cannot move from original position.
How can I improve it?
To move the plot you just need to add the PanTool. Check this minimal example:
from bokeh.models import ColumnDataSource
from bokeh.plotting import figure
from bokeh.io import curdoc
plot = figure(
width=300,
height=300,
tools='pan,reset',
logo=None,
)
x = [1, 2, 3, 4]
y = [4, 3, 2, 1]
source = ColumnDataSource(data=dict(x=x, y=y))
plot.circle(
x='x',
y='y',
source=source,
size=5,
fill_alpha=1.0,
fill_color='green',
line_color=None,
)
curdoc().add_root(plot)
Run this with bokeh serve --show example.py

Turn Bokeh Glyph into a link

I would like to turn all of the Bokeh glyphs on a certain plot into links to other pages. Is this possible?
For example if I had a map of countries, each country as a patch, if a user were to click on a country I would like to redirect them to that wikipedia page.
There also a simpler example in the User's Guide:
from bokeh.models import ColumnDataSource, OpenURL, TapTool
from bokeh.plotting import figure, output_file, show
output_file("openurl.html")
p = figure(plot_width=400, plot_height=400,
tools="tap", title="Click the Dots")
source = ColumnDataSource(data=dict(
x=[1, 2, 3, 4, 5],
y=[2, 5, 8, 2, 7],
color=["navy", "orange", "olive", "firebrick", "gold"]
))
p.circle('x', 'y', color='color', size=20, source=source)
url = "http://www.colors.commutercreative.com/#color/"
taptool = p.select(type=TapTool)
taptool.callback = OpenURL(url=url)
show(p)

Python Bokeh: remove toolbar from chart

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

Categories

Resources