Date

This notebook shows a bqplot example of an interactive linear regression.

The are several existing implementations of this interaction (Geogebra, d3js). This is using the bqplot library which allows for the straightforward creation of plots with interactive elements. This implementation could be easier for instructors to extend since it is in Python.

This can be used to have students explore the least-squares algorithm to gain a more intuitive understanding that available from the theory alone. Students can create examples in the spirit of Anscombe's Quartet or the updated Datasaurus that show indentical regressions for data that is non-linear in very different ways. They can explore the effect of outliers, of the presence of more data, or many other things.

In [1]:
from bqplot import *
import bqplot.marks as bqm
import bqplot.scales as bqs
import bqplot.axes as bqa
import numpy as np
import bqplot as bq
from IPython.display import display
import ipywidgets as widgets

print('ipywidgets version', widgets.__version__)
print('bqplot version', bq.__version__)
ipywidgets version 7.0.0a11
bqplot version 0.10.0a2
In [2]:
def update_line(change):
    # create line fit to data and display equation
    lin.x = [np.min(scat.x), np.max(scat.x)]
    poly = np.polyfit(scat.x, scat.y, 1)
    lin.y = np.polyval(poly, lin.x)
    label.value = 'y = {:.2f} + {:.2f}x'.format(poly[1], poly[0])   
    
# create initial data set
size = 10
np.random.seed(0)
x_data = np.random.randn(size) 
y_data = np.random.randn(size) 

# set up plot elements
sc_x = bqs.LinearScale()
sc_y = bqs.LinearScale()
ax_x = bqa.Axis(scale=sc_x)
ax_y = bqa.Axis(scale=sc_y, tick_format='0.2f', orientation='vertical')

# place data on scatter plot that allows point dragging
scat = bqm.Scatter(x=x_data, 
                   y=y_data, 
                   scales={'x': sc_x, 'y': sc_y}, 
                   enable_move=True)
# set up callback
scat.observe(update_line, names=['x', 'y'])

# linear fit line
lin = bqm.Lines(scales={'x': sc_x, 'y': sc_y})
# equation label
label = widgets.Label()
# containers
fig = bq.Figure(marks=[scat, lin], axes=[ax_x, ax_y])
box = widgets.VBox([label, fig])

# initialize plot and equation and display
update_line(None)
display(box)
A Jupyter Widget

This is a static image of the interaction.

In [3]:
from IPython.display import Image, display
display(Image(filename='bqplot-regression.png', embed=True))
In [ ]: