3. Widgets
If you are like a lot of data scientists, you are using Jupyter
to manage and code your experiments and analyses. Instead of presenting static content generated by your notebooks, you can also make your notebooks interactive by using Jupyter Widgets. Let’s dive into widgets and see how they work.
3.1. Interact
The @interact
decorator may be placed around functions to create
sliders
checkboxes
input text boxes
select dropdowns
[1]:
%matplotlib inline
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
np.random.seed(37)
plt.style.use('ggplot')
Here are two arguments, mean
\(\mu\) and std
\(\sigma\), that are associated with sliders. The sliders control the mean and standard deviation values that we used to sample from the \(X \sim \mathcal{N}(\mu, \sigma)\). Sliders are controlled by a tuple: (start, stop, step)
.
[2]:
from ipywidgets import interact
@interact(mean=(-40, 40, 2), std=(1, 5, 0.5))
def f(mean=10, std=1):
fig, ax = plt.subplots(figsize=(5, 3))
s = pd.Series(np.random.normal(mean, std, 5000))
_ = s.plot(kind='kde', ax=ax)
_ = ax.set_title('Slider Demo, change distribution')
An argument that is associated with checkbox must have boolean value. In the example below, we toggle the color of positive bars to blue (True
) or red (False
).
[3]:
@interact
def f(pos_blue=True):
s = pd.Series([10, 15, -8, 7, -15])
fig, ax = plt.subplots(figsize=(10, 3))
color_map = {True: 'b', False: 'r'} if pos_blue else {True: 'r', False: 'b'}
_ = s.plot(kind='bar', ax=ax, color=(s > 0).map(color_map))
_ = ax.set_title('Bar plot, toggle colors')
A string argument will always create an input text box. In this example below, we convert each character to the integer representation in Unicode using ord()
and plot out a line graph.
[4]:
@interact
def f(text='one-off coder is the best!'):
if len(text.strip()) == 0:
text = 'one-off coder is the best!'
s = pd.Series([ord(l) for l in list(text)])
fig, ax = plt.subplots(figsize=(10, 3))
_ = s.plot(kind='line', ax=ax)
_ = ax.set_title(f'Line plot, {text}')
Select dropdown boxes are created with a list of values. If the list is of tuples, each tuple must be of size two, where the first element is the display value and the second element is the backing value.
[5]:
df = pd.DataFrame(
[('left', np.random.normal(5, 1)) for _ in range(100)] +
[('right', np.random.normal(10, 1)) for _ in range(100)],
columns=['handedness', 'score'])
@interact(handedness=[('left', 0), ('right', 1)])
def f(handedness=0):
h = 'left' if handedness == 0 else 'right'
s = df[df.handedness == h].score
fig, ax = plt.subplots(figsize=(5, 3))
_ = s.plot(kind='box', ax=ax)
_ = ax.set_title(f'Box plot, {h} handedness, mean={s.mean():.2f}')
3.2. interactive()
You can use interactive()
to create multiple widgets. Below, we create two sliders, one select dropdown box and one checkbox.
[6]:
from ipywidgets import interactive
def f(mean=3, std=2.5, color='red', small_sample=False):
n = 100 if small_sample else 5000
s = pd.Series(np.random.normal(mean, std, n))
fig, ax = plt.subplots(figsize=(5, 3))
_ = s.plot(kind='box', ax=ax, color=color)
_ = ax.set_title(f'Box plot, mean={s.mean():.2f}')
w = interactive(f, mean=(-10, 10, 1), std=(1, 10, 0.5), color=['red', 'blue'], small_sample=False)
display(w)
3.3. interact_manual()
Using interact_manual()
will display a button to execute the attached function only if the button is executed.
[7]:
from ipywidgets import interact_manual
w = interact_manual(f, mean=(-10, 10, 1), std=(1, 10, 0.5), color=['red', 'blue'], small_sample=False)
_ = display(w)
<function __main__.f(mean=3, std=2.5, color='red', small_sample=False)>
3.4. interactive_output()
With interactive_output()
you can associate widgets to parameters of a function.
[8]:
import ipywidgets as widgets
mean_slider = widgets.IntSlider(min=-10, max=10, step=1, value=3, description='mean')
std_slider = widgets.FloatSlider(min=0.01, max=10.0, step=0.01, value=1.0, description='standard deviation')
small_checkbox = widgets.Checkbox(description='small sample?')
color_dropdown = widgets.Dropdown(options=['red', 'blue'], value='red', description='color')
ui = widgets.HBox([mean_slider, std_slider, small_checkbox, color_dropdown])
out = widgets.interactive_output(f, {'mean': mean_slider, 'std': std_slider, 'color': color_dropdown, 'small_sample': small_checkbox})
display(ui, out)
3.5. Other widgets
There are just too many widgets. Let’s look at the fun ones. Here’s the FloatProgress
widget.
[9]:
import time
def do_it(fp):
for i in range(1, 10):
fp.value = i
time.sleep(1)
fp = widgets.FloatProgress(
value=0.0,
min=0.0,
max=10.0,
step=1.0,
description='progress:',
bar_style='info',
orientation='horizontal'
)
display(fp)
do_it(fp)
Sometimes we need to pick dates.
[10]:
dp = widgets.DatePicker(
description='date:',
disabled=False
)
display(dp)
At other times, colors.
[11]:
cp = widgets.ColorPicker(
concise=False,
description='color:',
value='red',
disabled=False
)
display(cp)
[12]:
btn = widgets.Button(
description='Click me',
disabled=False,
button_style='danger',
tooltip='Click me',
icon='check'
)
display(btn)
3.6. Layouts
There’s four basic layouts.
box
horizontal box
vertical box
grid box (advanced, but seems to be experimental at the moment)
[13]:
widgets.Box([fp, dp, cp, btn])
[14]:
widgets.HBox([fp, dp, cp, btn])
[15]:
widgets.VBox([fp, dp, cp, btn])
You can use these layouts together.
[16]:
row_0 = widgets.HBox([fp, dp])
row_1 = widgets.HBox([cp, btn])
col = widgets.VBox([row_0, row_1])
display(col)
Out of the box layouts are also available.