Demo: IPyWidgets
The following sections contain examples of some common widget types. Remix this notebook to play around with them.
Note: IPyWidget support is currently experimental. Check out IPyWidgets Support for more info.
Interactive Matplotlib Visualisations
In its simplest form, widgets enhance Python functions with interaction capabilities. The following example shows how to use a context manager to plot solutions to a SIR ODE model (see hidden code cell) whose parameters can be changed by dragging the slider for each input.
SIR Model
import numpy as npimport matplotlib.pyplot as pltfrom scipy.integrate import odeintN = 1 # Size of the population (so everything in proportions)I0 = 0.01 # Initial proportion of the population infectedS0 = N - I0 # Initial proportion of the population susceptibleR0 = 0.0 # Initial proportion of the population recoveredmaxT = 25 # max number of periods in simulationbeta = 0.5 # transmission rategamma = 0.1 # recovery ratedef SIR(y, t, beta, gamma): '''the SIR model''' S, I, R = y dSdt = -beta*S*I dIdt = beta*S*I - gamma*I dRdt = gamma*I return([dSdt, dIdt, dRdt])Input Sliders
from ipywidgets import interact(beta=(0,1,0.05), gamma=(0,1,0.05), maxT=(5,100,5))def plotSIR(beta = beta, gamma = gamma, maxT = maxT): '''Solve differential equations in SIR and plot''' t = np.linspace(0, maxT, 1000) soln = odeint(SIR, [S0,I0,R0], t, args=(beta, gamma)) soln = np.array(soln) plt.figure(figsize=[8,6]) plt.plot(t, soln[:,0], linewidth=3, label = 'S(t)') plt.plot(t, soln[:,1], linewidth=3, label = 'I(t)') plt.plot(t, soln[:,2], linewidth=3, label = 'R(t)') plt.title("SIR model") plt.xlabel("Time"); plt.ylabel("proportions") plt.grid(); plt.legend()Compound Widgets
This examples shows how you can use a compound widget for exploring data frames. Specifically, we will use VBox and HBox for more fine-grained control over the layout and how to combine update callbacks with the observe method:
import pandas as pdfrom ipywidgets import widgetsdf = pd.read_csv(cars.csv)Data Frame Explorer
table = widgets.HTML()html = widgets.HTML()min_sl = widgets.IntSlider(min= 0, max=40, value=7)max_sl = widgets.IntSlider(min=0, max=40, value=8)def draw(_ = None): min_mpg = min_sl.value max_mpg = max_sl.value cols = ['ID', 'City mpg'] selection = df.loc[df['City mpg'].between(min_mpg, max_mpg)] selection.reindex(columns=cols) table.value = f'<h3>Found: {len(selection)}</h3>' html.value = selection[cols].to_html()min_sl.observe(draw)max_sl.observe(draw)draw() # first draw widgets.VBox([table, widgets.HBox([min_sl, max_sl]), html])Plotly Figure Widgets
The following example shows how to set up a basic Plotly FigureWidget (based on the examples in Jon Mease's notebooks):
from sklearn import datasetsimport timeiris_data = datasets.load_iris()feature_names = [name.replace(' (cm)', '').replace(' ', '_') for name in iris_data.feature_names]iris_df = pd.DataFrame(iris_data.data, columns=feature_names)iris_class = iris_data.target + 1FigureWidgets behave almost identically to Plotly Figure objects. The major difference here is that they are also IPyWidgets that can be interacted with. If you execute all the cells following the next cell ("Commands ⌘/Ctrl+J → Run Cells Below") you’ll see the plot changing on each evaluation.
Mind you can always use "Commands ⌘/Ctrl+J → Outputs / Clear" to remove the plots.
import plotly.graph_objs as gofig = go.FigureWidget()figfig.add_scatter(x=iris_df.sepal_length, y=iris_df.petal_width)scatter = fig.data[0]Any change to the widget’s underlying data (which acts as traitlets) will automatically update the plot for you …
time.sleep(2)scatter.mode = 'markers'scatter.marker.size = 8scatter.marker.color = iris_classscatter.marker.cmin = 0.5scatter.marker.cmax = 3.5scatter.marker.colorscale = [[0, 'red'], [0.33, 'red'], [0.33, 'green'], [0.67, 'green'], [0.67, 'blue'], [1.0, 'blue']]… batch updates instead send a single message to the frontend, aggregating all changed attributes at once:
with fig.batch_update(): scatter.marker.colorbar.ticks = 'outside' scatter.marker.colorbar.tickvals = [1, 2, 3] scatter.marker.colorbar.ticktext = iris_data.target_names.tolist() scatter.marker.colorbar.title = 'Species' scatter.marker.colorbar.titlefont.size = 16 scatter.marker.colorbar.titlefont.family = 'Rockwell' fig.layout.xaxis.title = 'sepal_length' fig.layout.yaxis.title = 'petal_width'scatter.marker.showscale = TrueAnimating Changes
All changes to the data can also be animated …
with fig.batch_animate(duration=1500): scatter.marker.size = np.sqrt(iris_df.petal_length.values * 60)with fig.batch_animate(duration=1500): scatter.marker.size = 8… and Figure widgets can interact with any other kind of widget to be assembled into more complex visualisations:
from IPython.display import display, HTMLoutx = widgets.Output()outy = widgets.Output()fig2 = go.FigureWidget(data=fig.data)def report_extrema(trace, points, state): outx.clear_output(wait=True) outy.clear_output(wait=True) with outx: display(HTML(f"<em>Max x-value: {np.max(points.xs)}</em>")) display(HTML(f"<em>Min x-value: {np.min(points.xs)}</em>")) with outy: display(HTML(f"<em>Max y-value: {np.max(points.ys)}</em>")) display(HTML(f"<em>Min y-value: {np.min(points.ys)}</em>"))fig2.layout.dragmode = 'lasso' fig2.data[0].marker.showscale = Falsefig2.data[0].on_selection(report_extrema)In the following plot, every "lasso" selection performed by the cursor will populate HTML output widgets with minima and maxima values from the selected points:
widgets.VBox([fig2, widgets.HBox([outx, outy])])We hope this short overview has been useful and inspires creating more interactive notebooks.
Troubleshooting
If widget display goes out-of-sync with the backend kernel try to:
Clear outputs: Commands
⌘/Ctrl+J→ Outputs / ClearStop the runtime: Commands
⌘/Ctrl+J→ Runtime / Reset