bqplot https://github.com/bloomberg/bqplot

A Jupyter - d3.js bridge

bqplot is a jupyter interactive widget library bringing d3.js visualization to the Jupyter notebook.

  • Apache Licensed

bqplot implements the abstractions of Wilkinson’s “The Grammar of Graphics” as interactive Jupyter widgets.

bqplot provides both

  • high-level plotting procedures with relevant defaults for common chart types,
  • lower-level descriptions of data visualizations meant for complex interactive visualization dashboards and applications involving mouse interactions and user-provided Python callbacks.

Installation:

conda install -c conda-forge bqplot

In [1]:
from __future__ import print_function
from IPython.display import display
from ipywidgets import *
from traitlets import *

import numpy as np
import pandas as pd
import bqplot as bq
import datetime as dt

In [2]:
np.random.seed(0)
size = 100
y_data = np.cumsum(np.random.randn(size) * 100.0)
y_data_2 = np.cumsum(np.random.randn(size))
y_data_3 = np.cumsum(np.random.randn(size) * 100.)

x = np.linspace(0.0, 10.0, size)

price_data = pd.DataFrame(np.cumsum(np.random.randn(150, 2).dot([[0.5, 0.8], [0.8, 1.0]]), axis=0) + 100,
                          columns=['Security 1', 'Security 2'],
                          index=pd.date_range(start='01-01-2007', periods=150))

symbol = 'Security 1'
dates_all = price_data.index.values
final_prices = price_data[symbol].values.flatten()

A simple plot with the pyplot API


In [3]:
from bqplot import pyplot as plt

In [4]:
plt.figure(1)
n = 100
plt.plot(np.linspace(0.0, 10.0, n), np.cumsum(np.random.randn(n)), 
         axes_options={'y': {'grid_lines': 'dashed'}})
plt.show()


Scatter Plot


In [5]:
plt.figure(title='Scatter Plot with colors')
plt.scatter(y_data_2, y_data_3, color=y_data)
plt.show()


Histogram


In [6]:
plt.figure()
plt.hist(y_data, colors=['OrangeRed'])
plt.show()


Every component of the figure is an independent widget


In [7]:
xs = bq.LinearScale()
ys = bq.LinearScale()
x = np.arange(100)
y = np.cumsum(np.random.randn(2, 100), axis=1) #two random walks

line = bq.Lines(x=x, y=y, scales={'x': xs, 'y': ys}, colors=['red', 'green'])
xax = bq.Axis(scale=xs, label='x', grid_lines='solid')
yax = bq.Axis(scale=ys, orientation='vertical', tick_format='0.2f', label='y', grid_lines='solid')

fig = bq.Figure(marks=[line], axes=[xax, yax], animation_duration=1000)
display(fig)



In [11]:
# update data of the line mark
line.y = np.cumsum(np.random.randn(2, 100), axis=1)

In [12]:
xs = bq.LinearScale()
ys = bq.LinearScale()
x, y = np.random.rand(2, 20)
scatt = bq.Scatter(x=x, y=y, scales={'x': xs, 'y': ys}, default_colors=['blue'])
xax = bq.Axis(scale=xs, label='x', grid_lines='solid')
yax = bq.Axis(scale=ys, orientation='vertical', tick_format='0.2f', label='y', grid_lines='solid')

fig = bq.Figure(marks=[scatt], axes=[xax, yax], animation_duration=1000)
display(fig)



In [19]:
#data updates
scatt.x = np.random.rand(20) * 10
scatt.y = np.random.rand(20)

The same holds for the attributes of scales, axes


In [20]:
xs.min = 4

In [21]:
xs.min = None

In [22]:
xax.label = 'Some label for the x axis'

Use bqplot figures as input widgets


In [23]:
xs = bq.LinearScale()
ys = bq.LinearScale()
x = np.arange(100)
y = np.cumsum(np.random.randn(2, 100), axis=1) #two random walks

line = bq.Lines(x=x, y=y, scales={'x': xs, 'y': ys}, colors=['red', 'green'])
xax = bq.Axis(scale=xs, label='x', grid_lines='solid')
yax = bq.Axis(scale=ys, orientation='vertical', tick_format='0.2f', label='y', grid_lines='solid')

Selections


In [24]:
def interval_change_callback(change):
    db.value = str(change['new'])

intsel = bq.interacts.FastIntervalSelector(scale=xs, marks=[line])
intsel.observe(interval_change_callback, names=['selected'] )

db = widgets.Label()
db.value = str(intsel.selected)
display(db)



In [25]:
fig = bq.Figure(marks=[line], axes=[xax, yax], animation_duration=1000, interaction=intsel)
display(fig)



In [26]:
line.selected


Out[26]:
[22,
 23,
 24,
 25,
 26,
 27,
 28,
 29,
 30,
 31,
 32,
 33,
 34,
 35,
 36,
 37,
 38,
 39,
 40,
 41,
 42,
 43,
 44,
 45,
 46,
 47,
 48,
 49,
 50,
 51,
 52,
 53,
 54,
 55,
 56,
 57,
 58,
 59,
 60,
 61]

Handdraw


In [27]:
handdraw = bq.interacts.HandDraw(lines=line)
fig.interaction = handdraw

In [22]:
line.y[0]


Out[22]:
array([ 0.72310049,  0.74771262,  1.46769635,  0.36479014,  0.26309286,
        0.28237225,  2.13196349,  1.91779684,  1.4187802 ,  1.44013142,
        0.52101798,  0.71377183,  0.34871661, -1.44261094, -1.50119749,
       -1.81874058, -3.45116389, -3.51829804, -2.02894208, -1.50763833,
       -0.89571114, -2.23720786, -1.76030949, -1.61185991, -1.08281467,
       -0.66018605, -2.01996678, -2.06136759, -2.81923845, -2.86932254,
       -3.76672347, -2.4542531 , -3.31322549, -4.21216765, -4.13758124,
       -5.21468031, -5.63934361, -6.46930821, -5.05813615, -4.27233232,
       -4.32980184, -4.72101889, -3.78010128, -3.3748972 , -2.87684479,
       -2.90303703, -4.59126706, -4.70373304, -5.23622296, -4.59116768,
       -3.57932525, -4.2372763 , -3.76889106, -2.03301206, -2.70072479,
       -1.01880305, -1.87138889, -1.84842914, -1.85957475, -1.84807585,
       -2.68575389, -3.27693699, -3.94465728, -3.61769469, -3.28765957,
       -1.06171524,  0.30927377, -0.20056947,  0.12430014,  1.12141812,
        1.15201995,  1.08237837,  1.13395331,  2.00122994,  1.15290942,
        0.82723995,  1.29767309,  1.60912016,  1.84870292,  1.47890176,
        2.45143755,  4.58530579,  4.99172129,  4.79854459,  5.55428487,
        5.01515224,  4.26546189,  4.29827064,  1.71547401,  0.56152364,
        0.21356179, -1.13982707, -2.17247017, -2.60921851, -4.2521838 ,
       -4.6582556 , -5.19352576, -5.16812055, -4.01393652, -3.84143211])

Moving points around


In [28]:
from bqplot import *

size = 100
np.random.seed(0)
x_data = range(size)
y_data = np.cumsum(np.random.randn(size) * 100.0)

## Enabling moving of points in scatter. Try to click and drag any of the points in the scatter and 
## notice the line representing the mean of the data update

sc_x = LinearScale()
sc_y = LinearScale()

scat = Scatter(x=x_data[:10], y=y_data[:10], scales={'x': sc_x, 'y': sc_y}, default_colors=['blue'],
               enable_move=True)
lin = Lines(scales={'x': sc_x, 'y': sc_y}, stroke_width=4, line_style='dashed', colors=['orange'])
m = Label(value='Mean is %s'%np.mean(scat.y))

def update_line(change):
    with lin.hold_sync():
        lin.x = [np.min(scat.x), np.max(scat.x)]
        lin.y = [np.mean(scat.y), np.mean(scat.y)]
        m.value='Mean is %s'%np.mean(scat.y)
        

update_line(None)

# update line on change of x or y of scatter
scat.observe(update_line, names='x')
scat.observe(update_line, names='y')

ax_x = Axis(scale=sc_x)
ax_y = Axis(scale=sc_y, tick_format='0.2f', orientation='vertical')

fig = Figure(marks=[scat, lin], axes=[ax_x, ax_y])

## In this case on drag, the line updates as you move the points.
with scat.hold_sync():
    scat.enable_move = True
    scat.update_on_move = True
    scat.enable_add = False

display(m, fig)


Label(colors=['#1f77b4', '#ff7f0e', '#2ca02c', '#d62728', '#9467bd', '#8c564b', '#e377c2', '#7f7f7f', '#bcbd22', '#17becf'], interactions={'hover': 'tooltip'}, scales_metadata={'x': {'orientation': 'horizontal', 'dimension': 'x'}, 'y': {'orientation': 'vertical', 'dimension': 'y'}, 'color': {'dimension': 'color'}, 'size': {'dimension': 'size'}, 'opacity': {'dimension': 'opacity'}, 'rotation': {'dimension': 'rotation'}}, tooltip_style={'opacity': 0.9})

In [ ]: