I am trying to add a single label at a specific spot on a bokeh chart. I know this easy but I can't seem to find the code that works for me.
I am trying to use the Label in bokeh.models but it isn't working.
I know the exact x and y coordinates, text and text color but it isn't working.
Any help will be greatly appreciated.
from bokeh.plotting import figure, output_file, show
from bokeh.io import output_notebook
from bokeh.models.tools import HoverTool
from bokeh.models import Label
output_notebook()
graph = figure(title = "Average Yearly Temperature per US State",)
for state in us_state_temps.columns:
if state == 'California':
graph.line(us_state_temps.index, us_state_temps[state], line_width = 2, color = "red")
else:
graph.line(us_state_temps.index, us_state_temps[state], line_width = 0.5, color = 'gray')
graph.xaxis.axis_label = 'Year'
graph.yaxis.axis_label = "Average Yearly Temperature °C"
graph.toolbar_location = None
graph.toolbar.active_drag = None
california = Label(x=70, y=1960, x_units='screen', y_units='screen', text='California')
graph.add_layout(california)
hover = HoverTool()
hover.tooltips = [('Year', '#x'), ('Average temp.', '#y')]
graph.add_tools(hover)
show(graph)
Related
I'm trying to highlight last value of a time series plot by plot its value on yaxis, as shown in this question. I prefer using LabelSet over Legend because you can precisely control the text positions and also using a data source to update it. But unfortunately, I can not find out how to draw label text outside the plot box.
Here is some code to plot LabelSet and notice how the text is only shown inside the box (66.1x is partially blocked by yaxis):
import pandas as pd
from bokeh.io import output_notebook
output_notebook()
from bokeh.plotting import figure, show
from bokeh.models import LabelSet, ColumnDataSource
#import bokeh.sampledata
#bokeh.sampledata.download()
from bokeh.sampledata.stocks import MSFT
df = pd.DataFrame(MSFT)[:50]
df["date"] = pd.to_datetime(df["date"])
p = figure(
x_axis_type="datetime", width=1000, toolbar_location='left',
title = "MSFT Candlestick", y_axis_location="right")
p.line(df.date, df.close)
ds = ColumnDataSource({'x': [df.date.iloc[-1]], 'y': [df.close.iloc[-1]], 'text': [' ' + str(df.close.iloc[-1])]})
ls = LabelSet(x='x', y='y', text='text', source=ds)
p.add_layout(ls)
show(p)
Please let me know how to show LabelSet outside the box, Thanks
My goal is to add an HoverTool to my figure which displays the weekday by name. The date is defined by the x-axis values. I want to display this information at a fixed position even if the visible section is changed by a tool like BoxZoom.
Since the HoverTool needs at least one renderer I first tried to define a line but I did not find a way to define the position relative to the figure. In fact if I zoom it can happen, that this line is not in the visible part and the HoverTool isn't working anymore (or in an area which is not visible).
My second attempt was to define an extra_y_range to draw the line relative. But I did not find a way to unselect the BoxZoom for this axis.
import pandas as pd
from bokeh.plotting import figure, output_notebook, show
from bokeh.models import (
HoverTool,
LinearAxis,
Range1d,
)
output_notebook()
dr = pd.date_range('2020-01-01', '2020-01-05', freq='D')
p = figure(title="line", plot_width=300, plot_height=300, x_axis_type='datetime')
p.line(x=dr, y=[6, 7, 2, 4, 5])
p.extra_y_ranges.update({"extra": Range1d(0, 1)})
p.add_layout(LinearAxis(y_range_name="extra", axis_label=''), "right")
l = p.line(x=dr, y=0.8, color='gray', **{"y_range_name":"extra"})
p.add_tools(
HoverTool(
tooltips=[("", "#x{%A}")],
renderers=[l],
mode="vline",
formatters={"#x": "datetime"},
))
show(p)
Is there a way to add an HoverTool which stays at the same position in the visible area even if this area is effected by tools?
You can try this solution which works for Bokeh v2.1.1. In the code below the tooltip is fixed at absolute position on the screen. You can add yourself more generic solution independent of the plot position on the screen.
from bokeh.models import CustomJS
from bokeh.models import HoverTool
from bokeh.plotting import show, figure
import numpy as np
p = figure(plot_width = 300, plot_height = 300, tooltips = [('value X', '#x'), ('value Y', '#y')])
circles = p.circle(x=np.random.rand(10)*10, y=np.random.rand(10)*10, size=10)
callback = CustomJS(args={'p': p}, code="""
var tooltips = document.getElementsByClassName("bk-tooltip");
const tw = 100;
for (var i = 0; i < tooltips.length; i++) {
tooltips[i].style.top = '5px';
tooltips[i].style.left = p.width/2 - tw/2 + 'px';
tooltips[i].style.width = tw + 'px';
} """)
hover = p.select_one(HoverTool)
hover.renderers = [circles]
hover.callback = callback
hover.show_arrow = False
show(p)
Result:
I want to display xaxis in below format. It should include hr,min,secs,msecs format
14:38:21:701, 14:38:21:702..
Below is the code I have written
#!/usr/bin/python3
from bokeh.plotting import figure, output_file, show
import pandas as pd
from bokeh.models import DatetimeTickFormatter, ColumnDataSource, PrintfTickFormatter
from pandas import ExcelWriter, ExcelFile
weight = pd.read_excel('file_name.xlsx')
source = ColumnDataSource(weight)
#Take data and present in a graph
output_file("test.html")
p = figure(plot_width=1500, plot_height=400)
p.left[0].formatter.use_scientific = False
p.xaxis[0].formatter.use_scientific = False
#Need to modify this format to display hours,minutes,seconds,msecs
p.xaxis[0].formatter = PrintfTickFormatter(format="%sms")
p.scatter(x='Time',y='Bearer ID 5 WM Low', color = "navy",source=source,legend_label='Bearer ID 5 WM Low')
p.scatter(x='Time',y='Bearer ID 5 VM Count', color = "red",source=source,legend_label='Bearer ID 5 VM Count')
show(p)
Below is the output for it.
You could use DatetimeFormatter instead of PrintfTickFormatter.
Visit DatetimeTickFormatter for the documentation
I'm using the Bokeh package to plot a line chart.
I want a given line to bolden (alpha to increase) when I hover over it.
I added a hover tool and then added "hover_line_alpha = 0.6" in my line chart.
However when I hover over points on a given line, the line disappears altogether!
Can you help me fix this?
Code below so you can see my logic.
Thanks,
Ross
# Code in Question
from bokeh.io import output_notebook, show, output_file
from bokeh.plotting import figure
from bokeh.models import ColumnDataSource, HoverTool
output_notebook()
# set out axes
x = 'time_rnd'
y = 'count'
# set colour palette
col_brew = ['#8dd3c7','#ffffb3','#bebada','#fb8072','#80b1d3','#fdb462','#b3de69','#fccde5','#d9d9d9','#bc80bd','#ccebc5','#ffed6f']
# map out figure
plot = figure(tools='box_select, lasso_select, save' ,x_axis_type='datetime')
# add HoverTool
hover_info = [('time', '#hover_time'),
('word', '#word'),
('count', '#count')]
hover = HoverTool(names=['use'],tooltips=hover_info,
mode='mouse',
show_arrow=True
)
plot.add_tools(hover)
### FOR LOOP OF PLOT [THIS IS WHERE THE ISSUE MANIFESTS]
for i in top_wds_test:
df_eng_word = df_eng_timeline[df_eng_timeline['word']==i]
source = ColumnDataSource(df_eng_word)
plot.line(x, y, line_width = 3,
line_alpha = 0.1, line_color=col_brew[top_wds.index(i)],
hover_line_alpha = 0.6,
#hover_line_color = 'black',
#hover_line_color = col_brew[top_wds.index(i)],
source = source, legend=i, name = 'use'
)
plot.circle(x, y, fill_color='white', size=5,
selection_color='green',
nonselection_fill_color='grey',nonselection_fill_alpha=0.4,
hover_color='red',
source = source, name = 'use')
# add legend
plot.legend.location = "top_left"
plot.legend.label_text_font_style = 'bold'
# materialize the plot
show(plot)
There seems to be an issue when the renderers share a data source. However, this works (with Bokeh >= 0.13.0) if you let Bokeh create a new separate source for each glyph:
from bokeh.models import ColumnDataSource
from bokeh.plotting import figure, show
p = figure(tools="hover", tooltips="$name: #$name")
data=dict(x=[1,2,3], y1=[2,6,5], y2=[6,2,3])
p.line('x', 'y1', color="navy", line_width=3, source=data,
alpha=0.1, hover_color="navy", hover_alpha=0.6, name="y1")
p.line('x', 'y2',color="firebrick", line_width=3, source=data,
alpha=0.1, hover_color="firebrick", hover_alpha=0.6, name="y2")
show(p)
I have the following code:
from bokeh.plotting import figure, show, output_file
from bokeh.sampledata.iris import flowers
from bokeh.models import LinearColorMapper
from bokeh.models import ColumnDataSource
from bokeh.models import ColorBar
from bokeh.palettes import Reds9
p = figure(title = "Iris Morphology")
p.xaxis.axis_label = "Petal Length"
p.yaxis.axis_label = "Petal Width"
source = ColumnDataSource(flowers)
# Reverse the color and map it
Reds9.reverse()
exp_cmap = LinearColorMapper(palette=Reds9,
low = min(flowers["petal_length"]),
high = max(flowers["petal_length"]))
p.circle("petal_length", "petal_width", source=source, line_color=None,
fill_color={"field":"petal_length", "transform":exp_cmap})
bar = ColorBar(color_mapper=exp_cmap, location=(0,0))
p.add_layout(bar, "left")
show(p)
Which produces the following plot:
Notice that I use Brewer's Red palette which is limited to 9 colors.
from bokeh.palettes import Reds9
How can I expand it to 256?
Bokeh's palettes are simply a list of HTML colors. You can create your own one. For example, picking the list from https://www.w3schools.com/colors/colors_shades.asp:
myReds = [
'#000000',
'#080000',
'#100000',
'#180000',
'#200000',
'#280000',
'#300000',
'#380000',
'#400000',
'#480000',
'#500000',
'#580000',
'#600000',
'#680000',
'#700000',
'#780000',
'#800000',
'#880000',
'#900000',
'#980000',
'#A00000',
'#A80000',
'#B00000',
'#B80000',
'#C00000',
'#C80000',
'#D00000',
'#D80000',
'#E00000',
'#E80000',
'#F00000',
'#F80000',
'#FF0000']
Then replace Reds9 by myReds:
[...]
exp_cmap = LinearColorMapper(palette=myReds,
low = min(flowers["petal_length"]),
high = max(flowers["petal_length"]))
[...]