In Bokeh, how do I add tooltips to a Timeseries chart (hover tool)?
Asked Answered
B

4

35

Is it possible to add Tooltips to a Timeseries chart?

In the simplified code example below, I want to see a single column name ('a','b' or 'c') when the mouse hovers over the relevant line.

Instead, a "???" is displayed and ALL three lines get a tool tip (rather than just the one im hovering over)

enter image description here

Per the documentation ( http://docs.bokeh.org/en/latest/docs/user_guide/tools.html#hovertool), field names starting with “@” are interpreted as columns on the data source.

  1. How can I display the 'columns' from a pandas DataFrame in the tooltip?

  2. Or, if the high level TimeSeries interface doesn't support this, any clues for using the lower level interfaces to do the same thing? (line? multi_line?) or convert the DataFrame into a different format (ColumnDataSource?)

  3. For bonus credit, how should the "$x" be formatted to display the date as a date?

thanks in advance

    import pandas as pd
    import numpy as np
    from bokeh.charts import TimeSeries
    from bokeh.models import HoverTool
    from bokeh.plotting import show

    toy_df = pd.DataFrame(data=np.random.rand(5,3), columns = ('a', 'b' ,'c'), index = pd.DatetimeIndex(start='01-01-2015',periods=5, freq='d'))   

    p = TimeSeries(toy_df, tools='hover')  

    hover = p.select(dict(type=HoverTool))
    hover.tooltips = [
        ("Series", "@columns"),
        ("Date", "$x"),
        ("Value", "$y"),
        ]

    show(p)
Baba answered 18/7, 2015 at 23:43 Comment(3)
See #31226619Drusy
Many thanks Colin, thats really helpful and given me a few pointers.... will update question or post a work around in due courseBaba
This might be another helpful answer for Bokeh >= 0.12.4: https://mcmap.net/q/450447/-multi_line-hover-in-bokehGarver
B
20

Below is what I came up with.

Its not pretty but it works.

Im still new to Bokeh (& Python for that matter) so if anyone wants to suggest a better way to do this, please feel free.

enter image description here

import pandas as pd
import numpy as np
from bokeh.charts import TimeSeries
from bokeh.models import HoverTool
from bokeh.plotting import show

toy_df = pd.DataFrame(data=np.random.rand(5,3), columns = ('a', 'b' ,'c'), index = pd.DatetimeIndex(start='01-01-2015',periods=5, freq='d'))       

 _tools_to_show = 'box_zoom,pan,save,hover,resize,reset,tap,wheel_zoom'        

p = figure(width=1200, height=900, x_axis_type="datetime", tools=_tools_to_show)


# FIRST plot ALL lines (This is a hack to get it working, why can't i pass in a dataframe to multi_line?)   
# It's not pretty but it works. 
# what I want to do!: p.multi_line(df)
ts_list_of_list = []
for i in range(0,len(toy_df.columns)):
    ts_list_of_list.append(toy_df.index.T)

vals_list_of_list = toy_df.values.T.tolist()

# Define colors because otherwise multi_line will use blue for all lines...
cols_to_use =  ['Black', 'Red', 'Lime']
p.multi_line(ts_list_of_list, vals_list_of_list, line_color=cols_to_use)


# THEN put  scatter one at a time on top of each one to get tool tips (HACK! lines with tooltips not yet supported by Bokeh?) 
for (name, series) in toy_df.iteritems():
    # need to repmat the name to be same dimension as index
    name_for_display = np.tile(name, [len(toy_df.index),1])

    source = ColumnDataSource({'x': toy_df.index, 'y': series.values, 'series_name': name_for_display, 'Date': toy_df.index.format()})
    # trouble formating x as datestring, so pre-formating and using an extra column. It's not pretty but it works.

    p.scatter('x', 'y', source = source, fill_alpha=0, line_alpha=0.3, line_color="grey")     

    hover = p.select(dict(type=HoverTool))
    hover.tooltips = [("Series", "@series_name"), ("Date", "@Date"),  ("Value", "@y{0.00%}"),]
    hover.mode = 'mouse'

show(p)
Baba answered 21/7, 2015 at 21:27 Comment(0)
S
11

I’m not familiar with Pandas,I just use python list to show the very example of how to add tooltips to muti_lines, show series names ,and properly display date/time。Below is the result. Thanks to @bs123's answer and @tterry's answer in Bokeh Plotting: Enable tooltips for only some glyphs

my result

# -*- coding: utf-8 -*-

from bokeh.plotting import figure, output_file, show, ColumnDataSource
from bokeh.models import  HoverTool
from datetime import datetime

dateX_str = ['2016-11-14','2016-11-15','2016-11-16']
#conver the string of datetime to python  datetime object
dateX = [datetime.strptime(i, "%Y-%m-%d") for i in dateX_str]

v1= [10,13,5]
v2 = [8,4,14]
v3= [14,9,6]
v = [v1,v2,v3]

names = ['v1','v2','v3']
colors = ['red','blue','yellow']

output_file('example.html',title = 'example of add tooltips to multi_timeseries')
tools_to_show = 'hover,box_zoom,pan,save,resize,reset,wheel_zoom'
p = figure(x_axis_type="datetime", tools=tools_to_show)

#to show the tooltip for multi_lines,you need use the ColumnDataSource which define the data source of glyph
#the key is to use the same column name for each data source of the glyph
#so you don't have to add tooltip for each glyph,the tooltip is added to the figure

#plot each timeseries line glyph
for i in xrange(3):
# bokeh can't show datetime object in tooltip properly,so we use string instead
    source = ColumnDataSource(data={
                'dateX': dateX, # python datetime object as X axis
                'v': v[i],
                'dateX_str': dateX_str, #string of datetime for display in tooltip
                'name': [names[i] for n in xrange(3)]
            })
    p.line('dateX', 'v',source=source,legend=names[i],color = colors[i])
    circle = p.circle('dateX', 'v',source=source, fill_color="white", size=8, legend=names[i],color = colors[i])

    #to avoid some strange behavior(as shown in the picture at the end), only add the circle glyph to the renders of hover tool
    #so tooltip only takes effect on circle glyph
    p.tools[0].renderers.append(circle)

# show the tooltip
hover = p.select(dict(type=HoverTool))
hover.tooltips = [("value", "@v"), ("name", "@name"), ("date", "@dateX_str")]
hover.mode = 'mouse'
show(p)

tooltips with some strange behavior,two tips displayed at the same time

Stroganoff answered 19/11, 2016 at 7:36 Comment(0)
E
2

Here is my solution. I inspected the glyph render data source to see what are the names on it. Then I use those names on the hoover tooltips. You can see the resulting plot here.

import numpy as np
from bokeh.charts import TimeSeries
from bokeh.models import HoverTool
from bokeh.plotting import show

toy_df = pd.DataFrame(data=np.random.rand(5,3), columns = ('a', 'b' ,'c'), index = pd.DatetimeIndex(start='01-01-2015',periods=5, freq='d'))   
#Bockeh display dates as numbers so convert to string tu show correctly
toy_df.index = toy_df.index.astype(str) 
p = TimeSeries(toy_df, tools='hover')  

#Next 3 lines are to inspect how are names on gliph to call them with @name on hover
#glyph_renderers = p.select(dict(type=GlyphRenderer))
#bar_source = glyph_renderers[0].data_source
#print(bar_source.data)  #Here we can inspect names to call on hover


hover = p.select(dict(type=HoverTool))
hover.tooltips = [
        ("Series", "@series"),
        ("Date", "@x_values"),
        ("Value", "@y_values"),
        ]

show(p)
Etui answered 9/8, 2017 at 15:42 Comment(2)
Neat use case, however, how might this be used to access values that aren't present in the original chart? For example, say there's a 'description' column which isn't plotted, but you'd like it in the tooltip.Oleneolenka
Similar question, how do you display values in the tooltip that are, say, stored in a python list and not displayed by bokeh?Whitsun
O
1

The original poster's code doesn't work with the latest pandas (DatetimeIndex constructor has changed), but Hovertool now supports a formatters attribute that lets you specify a format as a strftime string. Something like

fig.add_tool(HoverTool(
    tooltip=[
        ('time', '@index{%Y-%m-%d}')
    ],
    formatters={
        '@index': 'datetime'
    }
))
Oven answered 4/5, 2020 at 14:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.