Interactive 1D time-scale plot with hovertool using Python and Bokeh


The result (static image) is:

Interactive 1D time-scale plot with hovertool using Python and Bokeh

This page shows how to generate interactive time-scale 1D line plot with hovertool (stock data) using Python and Bokeh.

See also:

Python Matplotlib Tips: Interactive plot using Bokeh - first step -

I firstly thought that Bokeh uses matplotlib. We generate figure using matplotlib then convert the figure to the Bokeh compatible. However, it seems Bokeh works stand alone without matplotlib (is it true?) Anyway, let's check whether Bokeh works in my environment or not.

Python Matplotlib Tips: Interactive time-scale stock price figure using Python, matplotlib.pyplot and mpld3

This page shows how to generate interactive figure using python, matplotlib.pyplot and mpld3. The stock information of the apple.inc is used as the example to plot.


FIrstly, define data to plot and save as external data file. In this page, Apple's stock information is used as the time scale data. The source of the stock data is Yahoo Finance (URL: https://finance.yahoo.com/quote/aapl/history/)

In [1]:
data = """Nov 16, 2018 190.50 194.97 189.46 193.53 193.53 36,208,500
Nov 15, 2018 188.39 191.97 186.90 191.41 191.41 46,478,800
Nov 14, 2018 193.90 194.48 185.93 186.80 186.80 60,801,000
Nov 13, 2018 191.63 197.18 191.45 192.23 192.23 46,882,900
Nov 12, 2018 199.00 199.85 193.79 194.17 194.17 51,135,500
Nov 09, 2018 205.55 206.01 202.25 204.47 204.47 34,365,800
Nov 08, 2018 209.98 210.12 206.75 208.49 208.49 25,362,600
Nov 07, 2018 205.97 210.06 204.13 209.95 209.22 33,424,400
Nov 06, 2018 201.92 204.72 201.69 203.77 203.06 31,882,900
Nov 05, 2018 204.30 204.39 198.17 201.59 200.89 66,163,700
Nov 02, 2018 209.55 213.65 205.43 207.48 206.76 91,328,700
Nov 01, 2018 219.05 222.36 216.81 222.22 221.45 58,323,200
Oct 31, 2018 216.88 220.45 216.62 218.86 218.10 38,358,900
Oct 30, 2018 211.15 215.18 209.27 213.30 212.56 36,660,000
Oct 29, 2018 219.19 219.69 206.09 212.24 211.50 45,935,500
Oct 26, 2018 215.90 220.19 212.67 216.30 215.55 47,258,400
Oct 25, 2018 217.71 221.38 216.75 219.80 219.04 29,855,800
Oct 24, 2018 222.60 224.23 214.54 215.09 214.34 40,925,500
Oct 23, 2018 215.83 223.25 214.70 222.73 221.96 38,767,800
Oct 22, 2018 219.79 223.36 218.94 220.65 219.88 28,792,100
Oct 19, 2018 218.06 221.26 217.43 219.31 218.55 33,078,700
Oct 18, 2018 217.86 219.74 213.00 216.02 215.27 32,581,300
Oct 17, 2018 222.30 222.64 219.34 221.19 220.42 22,885,400
Oct 16, 2018 218.93 222.99 216.76 222.15 221.38 29,184,000
Oct 15, 2018 221.16 221.83 217.27 217.36 216.60 30,791,000
Oct 12, 2018 220.42 222.88 216.84 222.11 221.34 40,337,900
Oct 11, 2018 214.52 219.50 212.32 214.45 213.70 53,124,400
Oct 10, 2018 225.46 226.35 216.05 216.36 215.61 41,990,600
Oct 09, 2018 223.64 227.27 222.25 226.87 226.08 26,891,000
Oct 08, 2018 222.21 224.80 220.20 223.77 222.99 29,663,900
Oct 05, 2018 227.96 228.41 220.58 224.29 223.51 33,580,500
Oct 04, 2018 230.78 232.35 226.73 227.99 227.20 32,042,000
Oct 03, 2018 230.05 233.47 229.78 232.07 231.26 28,654,800
Oct 02, 2018 227.25 230.00 226.63 229.28 228.48 24,788,200
Oct 01, 2018 227.95 229.42 226.35 227.26 226.47 23,600,800
Sep 28, 2018 224.79 225.84 224.02 225.74 224.96 22,929,400
Sep 27, 2018 223.82 226.44 223.54 224.95 224.17 30,181,200
Sep 26, 2018 221.00 223.75 219.76 220.42 219.65 23,984,700
Sep 25, 2018 219.75 222.82 219.70 222.19 221.42 24,554,400
Sep 24, 2018 216.82 221.26 216.63 220.79 220.02 27,693,400
Sep 21, 2018 220.78 221.36 217.29 217.66 216.90 96,246,700
Sep 20, 2018 220.24 222.28 219.15 220.03 219.26 26,608,800
Sep 19, 2018 218.50 219.62 215.30 218.37 217.61 27,123,800
Sep 18, 2018 217.79 221.85 217.12 218.24 217.48 31,571,700
Sep 17, 2018 222.15 222.95 217.27 217.88 217.12 37,195,100
Sep 14, 2018 225.75 226.84 222.52 223.84 223.06 31,999,300
Sep 13, 2018 223.52 228.35 222.57 226.41 225.62 41,706,400
Sep 12, 2018 224.94 225.00 219.84 221.07 220.30 49,278,700
Sep 11, 2018 218.01 224.30 216.56 223.85 223.07 35,749,000
Sep 10, 2018 220.95 221.85 216.47 218.33 217.57 39,516,500
Sep 07, 2018 221.85 225.37 220.71 221.30 220.53 37,619,800
Sep 06, 2018 226.23 227.35 221.30 223.10 222.32 34,290,000
Sep 05, 2018 228.99 229.67 225.10 226.87 226.08 33,333,000
Sep 04, 2018 228.41 229.18 226.63 228.36 227.57 27,390,100
Aug 31, 2018 226.51 228.87 226.00 227.63 226.84 43,340,100
Aug 30, 2018 223.25 228.26 222.40 225.03 224.25 48,793,800
Aug 29, 2018 220.15 223.49 219.41 222.98 222.20 27,254,800
Aug 28, 2018 219.01 220.54 218.92 219.70 218.94 22,776,800
Aug 27, 2018 217.15 218.74 216.33 217.94 217.18 20,525,100
Aug 24, 2018 216.60 216.90 215.11 216.16 215.41 18,476,400
Aug 23, 2018 214.65 217.05 214.60 215.49 214.74 18,883,200
Aug 22, 2018 214.10 216.36 213.84 215.05 214.30 19,018,100
Aug 21, 2018 216.80 217.19 214.03 215.04 214.29 26,159,800
Aug 20, 2018 218.10 219.18 215.11 215.46 214.71 30,287,700
Aug 17, 2018 213.44 217.95 213.16 217.58 216.82 35,427,000
Aug 16, 2018 211.75 213.81 211.47 213.32 212.58 28,500,400
Aug 15, 2018 209.22 210.74 208.33 210.24 209.51 28,807,600
Aug 14, 2018 210.16 210.56 208.26 209.75 209.02 20,748,000
Aug 13, 2018 209.31 210.95 207.70 208.87 208.14 25,890,900
Aug 10, 2018 207.36 209.10 206.67 207.53 206.81 24,611,200
Aug 09, 2018 209.53 209.78 207.20 208.88 207.43 23,492,600
Aug 08, 2018 206.05 207.81 204.52 207.25 205.81 22,525,500
Aug 07, 2018 209.32 209.50 206.76 207.11 205.67 25,587,400
Aug 06, 2018 208.00 209.25 207.07 209.07 207.61 25,425,400
Aug 03, 2018 207.03 208.74 205.48 207.99 206.54 33,447,400
Aug 02, 2018 200.58 208.38 200.35 207.39 205.95 62,404,000
Aug 01, 2018 199.13 201.76 197.31 201.50 200.10 67,935,700
Jul 31, 2018 190.30 192.14 189.34 190.29 188.97 39,373,000
Jul 30, 2018 191.90 192.20 189.07 189.91 188.59 21,029,500
Jul 27, 2018 194.99 195.19 190.10 190.98 189.65 24,024,000
Jul 26, 2018 194.61 195.96 193.61 194.21 192.86 19,076,000
Jul 25, 2018 193.06 194.85 192.43 194.82 193.46 16,709,900
Jul 24, 2018 192.45 193.66 192.05 193.00 191.66 18,697,900
Jul 23, 2018 190.68 191.96 189.56 191.61 190.28 15,989,400
Jul 20, 2018 191.78 192.43 190.17 191.44 190.11 20,676,200
Jul 19, 2018 189.69 192.55 189.69 191.88 190.54 20,286,800
Jul 18, 2018 191.78 191.80 189.93 190.40 189.07 16,393,400
Jul 17, 2018 189.75 191.87 189.20 191.45 190.12 15,534,500
Jul 16, 2018 191.52 192.65 190.42 190.91 189.58 15,043,100
Jul 13, 2018 191.08 191.84 190.90 191.33 190.00 12,513,900
Jul 12, 2018 189.53 191.41 189.31 191.03 189.70 18,041,100
Jul 11, 2018 188.50 189.78 187.61 187.88 186.57 18,831,500
Jul 10, 2018 190.71 191.28 190.18 190.35 189.03 15,939,100
Jul 09, 2018 189.50 190.68 189.30 190.58 189.25 19,756,600
Jul 06, 2018 185.42 188.43 185.20 187.97 186.66 17,485,200
Jul 05, 2018 185.26 186.41 184.28 185.40 184.11 16,604,200
Jul 03, 2018 187.79 187.95 183.54 183.92 182.64 13,954,800
Jul 02, 2018 183.82 187.30 183.42 187.18 185.88 17,731,300
Jun 29, 2018 186.29 187.19 182.91 185.11 183.82 22,737,700
Jun 28, 2018 184.10 186.21 183.80 185.50 184.21 17,365,200
Jun 27, 2018 185.23 187.28 184.03 184.16 182.88 25,285,300
Jun 26, 2018 182.99 186.53 182.54 184.43 183.15 24,569,200
Jun 25, 2018 183.40 184.92 180.73 182.17 180.90 31,663,100
Jun 22, 2018 186.12 186.15 184.70 184.92 183.63 27,200,400
Jun 21, 2018 187.25 188.35 184.94 185.46 184.17 25,711,900
Jun 20, 2018 186.35 187.20 185.73 186.50 185.20 20,628,700
Jun 19, 2018 185.14 186.33 183.45 185.69 184.40 33,578,500
Jun 18, 2018 187.88 189.22 187.20 188.74 187.43 18,484,900
Jun 15, 2018 190.03 190.16 188.26 188.84 187.53 61,719,200
Jun 14, 2018 191.55 191.57 190.22 190.80 189.47 21,610,100
Jun 13, 2018 192.42 192.88 190.44 190.70 189.37 21,638,400
Jun 12, 2018 191.39 192.61 191.15 192.28 190.94 16,911,100
Jun 11, 2018 191.35 191.97 190.21 191.23 189.90 18,308,500
Jun 08, 2018 191.17 192.00 189.77 191.70 190.37 26,656,800
Jun 07, 2018 194.14 194.20 192.34 193.46 192.11 21,347,200
Jun 06, 2018 193.63 194.08 191.92 193.98 192.63 20,933,600
Jun 05, 2018 193.07 193.94 192.36 193.31 191.96 21,566,000
Jun 04, 2018 191.64 193.42 191.35 191.83 190.49 26,266,200
Jun 01, 2018 187.99 190.26 187.75 190.24 188.92 23,442,500
May 31, 2018 187.22 188.23 186.14 186.87 185.57 27,482,800
May 30, 2018 187.72 188.00 186.78 187.50 186.20 18,690,500
May 29, 2018 187.60 188.75 186.87 187.90 186.59 22,514,100
May 25, 2018 188.23 189.65 187.65 188.58 187.27 17,461,000
May 24, 2018 188.77 188.84 186.21 188.15 186.84 23,234,000
May 23, 2018 186.35 188.50 185.76 188.36 187.05 20,058,400
May 22, 2018 188.38 188.88 186.78 187.16 185.86 15,240,700
May 21, 2018 188.00 189.27 186.91 187.63 186.32 18,400,800
May 18, 2018 187.19 187.81 186.13 186.31 185.01 18,297,700
May 17, 2018 188.00 188.91 186.36 186.99 185.69 17,294,000
May 16, 2018 186.07 188.46 186.00 188.18 186.87 19,183,100
May 15, 2018 186.78 187.07 185.10 186.44 185.14 23,695,200
May 14, 2018 189.01 189.53 187.86 188.15 186.84 20,778,800
May 11, 2018 189.49 190.06 187.45 188.59 187.28 26,212,200
May 10, 2018 187.74 190.37 187.65 190.04 187.99 27,989,300
May 09, 2018 186.55 187.40 185.22 187.36 185.34 23,211,200
May 08, 2018 184.99 186.22 183.67 186.05 184.05 28,402,800
May 07, 2018 185.18 187.67 184.75 185.16 183.17 42,451,400
May 04, 2018 178.25 184.25 178.17 183.83 181.85 56,201,300
May 03, 2018 175.88 177.50 174.44 176.89 174.98 34,068,200
May 02, 2018 175.23 177.75 173.80 176.57 174.67 66,539,400
May 01, 2018 166.41 169.20 165.27 169.10 167.28 53,569,400
Apr 30, 2018 162.13 167.26 161.84 165.26 163.48 42,427,400
Apr 27, 2018 164.00 164.33 160.63 162.32 160.57 35,655,800
Apr 26, 2018 164.12 165.73 163.37 164.22 162.45 27,963,000"""
with open('apple_stock_data.dat', mode='w') as f: f.writelines(data)

Load libraries and check the versions

In [2]:
import platform
print('python: '+platform.python_version())
import pandas as pd
print('pandas: '+pd.__version__)
from dateutil import parser
python: 3.6.3
pandas: 0.23.4

Load Bokeh

In [3]:
from bokeh.plotting import figure, output_file, show
from bokeh.io import output_notebook
output_notebook()
Loading BokehJS ...

Load the stock data

In [4]:
df = pd.read_csv('apple_stock_data.dat', delim_whitespace=True, header=None, thousands=',')
df.head(10)
Out[4]:
0 1 2 3 4 5 6 7 8
0 Nov 16 2018 190.50 194.97 189.46 193.53 193.53 36208500
1 Nov 15 2018 188.39 191.97 186.90 191.41 191.41 46478800
2 Nov 14 2018 193.90 194.48 185.93 186.80 186.80 60801000
3 Nov 13 2018 191.63 197.18 191.45 192.23 192.23 46882900
4 Nov 12 2018 199.00 199.85 193.79 194.17 194.17 51135500
5 Nov 9 2018 205.55 206.01 202.25 204.47 204.47 34365800
6 Nov 8 2018 209.98 210.12 206.75 208.49 208.49 25362600
7 Nov 7 2018 205.97 210.06 204.13 209.95 209.22 33424400
8 Nov 6 2018 201.92 204.72 201.69 203.77 203.06 31882900
9 Nov 5 2018 204.30 204.39 198.17 201.59 200.89 66163700

Modify the index of the Dataframe so as to become time-scale friendly

In [5]:
xx = [parser.parse("%s %s %s"%(mm,dd,yyyy)) for mm,dd,yyyy in zip(df.loc[:,0],df.loc[:,1],df.loc[:,2])]
df.index=xx
df.head(10)
Out[5]:
0 1 2 3 4 5 6 7 8
2018-11-16 Nov 16 2018 190.50 194.97 189.46 193.53 193.53 36208500
2018-11-15 Nov 15 2018 188.39 191.97 186.90 191.41 191.41 46478800
2018-11-14 Nov 14 2018 193.90 194.48 185.93 186.80 186.80 60801000
2018-11-13 Nov 13 2018 191.63 197.18 191.45 192.23 192.23 46882900
2018-11-12 Nov 12 2018 199.00 199.85 193.79 194.17 194.17 51135500
2018-11-09 Nov 9 2018 205.55 206.01 202.25 204.47 204.47 34365800
2018-11-08 Nov 8 2018 209.98 210.12 206.75 208.49 208.49 25362600
2018-11-07 Nov 7 2018 205.97 210.06 204.13 209.95 209.22 33424400
2018-11-06 Nov 6 2018 201.92 204.72 201.69 203.77 203.06 31882900
2018-11-05 Nov 5 2018 204.30 204.39 198.17 201.59 200.89 66163700

Check the type of index

In [6]:
type(df.index[0])
Out[6]:
pandas._libs.tslibs.timestamps.Timestamp
In [7]:
from bokeh.models.tools import HoverTool

# define figure
p = figure(x_axis_type="datetime", x_axis_label='Date', y_axis_label='Price',
           plot_width=600, plot_height=300)

# add hover tools to the figure
p.add_tools(HoverTool(
    tooltips=[('Date','@x{%F}'),('Price', '@y'),],
    formatters={'x':'datetime',},
    # display a tooltip whenever the cursor is vertically in line with a glyph
    mode='vline'
    ))

# plot a line to the figure
p.line(df.index, df.iloc[:,7], line_width=2)

# display the figure in the notebook
show(p)