简体   繁体   English

IPython Notebook / Matplotlib:可以在绘图上交互式显示/隐藏图形吗?

[英]IPython Notebook/Matplotlib: Interactive show/hide graphs on a plot, is it possible?

I am using IPython Notebook and Matplotlib to visualise some data, with inline display mode (ie I want to display and interact with my plots on the web interface of IPython Notebook). 我正在使用IPython Notebook和Matplotlib以内联显示模式来可视化一些数据(即,我想在IPython Notebook的Web界面上显示并与我的绘图进行交互)。

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: 我的情节看起来像这样:

难以一起浏览这9个图,最好隐藏其中一些并显示其他

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: 附加到DataFrame对象的绘图方法返回它们绘制到的Axes对象(这对于简单的事情很有用,但使复杂的事情变得不可能),因此,一些绘图代码:

%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). cycler是从mpl分离出来的一个辅助项目(对于1.5来说是必需的dep)。 It is currently pip installable. 目前可以点子安装。

See https://gist.github.com/tacaswell/7a0e5e76fb3cafa3b7cd#file-so_interactive_demo-ipynb for a demo notebook. 有关演示笔记本,请参见https://gist.github.com/tacaswell/7a0e5e76fb3cafa3b7cd#file-so_interactive_demo-ipynb

There is on-going work to make this easier (so that mpl Artists can auto-construct their UI elements). 正在进行的工作使此操作更容易(以便mpl Artists可以自动构造其UI元素)。 The infrastructure that will make that work is one of the major goals of mpl 2.1. 使该工作正常进行的基础结构是mpl 2.1的主要目标之一。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM