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

bs123 picture bs123 · Jul 19, 2015 · Viewed 34.1k times · Source

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)

Answer

bs123 picture bs123 · Jul 21, 2015

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)