I am using IPython Notebook and Matplotlib to visualise some data, with inline display mode (i.e. I want to display and interact with my plots on the web interface of IPython Notebook).
I have a plot showing several different graphs and I would like to have an interactive interface (a set of checkboxes for example) that allow me to hide or show the graphs.
My plot looks like this:
I another word: I have a plot where I display many different graphs, each graph is a line and it has its own legend. I would like to add a set of check-boxes to the plot, each one for a graph. When the checkpoint is checked the graph will be visible, when unchecked the graph will disappear.
To do this you need references to the artists created by your plotting routine. The plotting methods attached to the DataFrame objects return the Axes
object they plotted to instead (this is useful for simple things, but makes complex things impossible) so, some plotting code:
%matplotlib notebook
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import matplotlib
def pandas_plot(ax, df, style_cycle, **kwargs):
"""
Plot a pandas DataFrame
Parameters
----------
ax : matplotlib.axes.Axes
The axes to plot to
df : pd.DataFrame
The data to plot
style_cycle : Cycler
Something that when iterated over yields style dict
Returns
-------
ret : dict
Dictionary of line2d artists added
"""
ret = {}
x = df.index
for n, sty in zip(df.columns, style_cycle):
sty.update(kwargs)
ln, = ax.plot(x, df[n], label=n, **sty)
ret[n] = ln
ax.legend()
return ret
Now some code to set up the widget interface (this is doing more than you asked for, but this is what I have pre-made from my scipy talk):
from IPython.html.widgets import *
from IPython.display import display
def widget_function_factory(arts):
"""
Generate fulnction + args to pass to interactive
Parameters
----------
arts : dict
dictionary of Line2D
"""
name = Dropdown(options=list(arts.keys()))
def set_all(_, old_line, new_line):
ln = arts[new_line]
lw.value = ln.get_lw()
alph.value = ln.get_alpha() or 1
visible.value = ln.get_visible()
markevery.value = ln.get_markevery()
marker.value = ln.get_marker()
def set_lw(_, old_lw, new_lw):
ln = arts[name.value]
arts[name.value].set_lw(new_lw)
arts[name.value].axes.legend()
def set_alpha(_, old_value, new_value):
ln = arts[name.value]
ln.set_alpha(new_value)
ln.axes.legend()
def set_visible(_, old_value, new_value):
ln = arts[name.value]
ln.set_visible(new_value)
ln.axes.legend()
def set_markevery(_, old_value, new_value):
ln = arts[name.value]
ln.set_markevery(new_value)
def set_marker(_, old_value, new_value):
ln = arts[name.value]
ln.set_marker(new_value)
ln.axes.legend()
lw = FloatSlider(min=1, max=5, description='lw: ')
alph = FloatSlider(min=0, max=1, description='alpha: ')
visible = Checkbox(description='visible: ')
markevery = IntSlider(min=1, max=15, description='markevery: ')
marker = Dropdown(options={v:k for k, v in matplotlib.markers.MarkerStyle.markers.items()},
description='marker: ')
name.on_trait_change(set_all, 'value')
lw.on_trait_change(set_lw, 'value')
alph.on_trait_change(set_alpha, 'value')
visible.on_trait_change(set_visible, 'value')
markevery.on_trait_change(set_markevery, 'value')
marker.on_trait_change(set_marker, 'value')
display(name, lw, alph, marker, markevery, visible)
set_all(None, None, name.value)
do the plotting:
th = np.linspace(0, 2*np.pi, 128)
df = pd.DataFrame({'sin': np.sin(th),
'shift +': np.sin(th + np.pi / 3),
'shift -': np.sin(th - np.pi / 3)}, index=th)
fig, ax = plt.subplots()
from cycler import cycler
style_cycle = cycler('color',['r', 'black', 'pink']) + cycler('marker', 'sxo')
#style_cycle = [{'color': 'r', 'marker': 's'},
# {'color': 'black', 'marker': 'x'},
# {'color': 'pink', 'marker': 'o'}]
arts = pandas_plot(ax, df, style_cycle, markevery=10)
vlns = []
for x in np.arange(1, 7) * np.pi/3:
vlns.append(plt.axvline(x, color='k', linestyle=':'))
plt.axhline(0, color='k', linestyle=':')
and create the controls
widget_function_factory(arts)
cycler
is a side project that spun off of mpl (and will be a required dep for 1.5). It is currently pip installable.
See https://gist.github.com/tacaswell/7a0e5e76fb3cafa3b7cd#file-so_interactive_demo-ipynb for a demo notebook.
There is on-going work to make this easier (so that mpl Artists can auto-construct their UI elements). The infrastructure that will make that work is one of the major goals of mpl 2.1.
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments