Jupyter:如何使用widgets.SelectMultiple()交互式选择要绘制的系列?

时间:2019-02-11 11:00:33

标签: python jupyter-notebook

背景

有人问过类似的问题here,但问题并不十分明确,通常只能参考其他来源来回答。我的案子听起来很基础,而令我感到惊讶的是,很难找到可行的例子。

目标:

我希望能够通过使用这样的小部件从熊猫数据框中选择任何子集来绘制如下图:

enter image description here

我的尝试

docs中简要描述了widgets.SelectMultiple()小部件,this section描述了如何交互地更改图中序列的值。我试图用widgets.SelectMultiple()的功能替换后面的演示的中心部分,但是收效甚微。

思考我真的很想让这个工作正常,我希望我要做的就是找出标记为的部分下的内容。在下面的代码段中>“#该怎么做!?” 。就像现在的片段一样,将生成一个小部件和图表,但是它们之间没有有效的链接。

我知道的问题:

我对链接中提供的示例的复制存在一些缺陷。我认为dfwidg应该包含在multiplot函数中。 interactive plot函数可能也是如此。我也尝试过其他方法,但是没有成功。

代码段(在Jupyter Notebook中使用):

# imports
%matplotlib inline

from ipywidgets import interactive
import pandas as pd
import numpy as np
from jupyterthemes import jtplot

# Sample data
np.random.seed(123)
rows = 50
dfx = pd.DataFrame(np.random.randint(90,110,size=(rows, 1)), columns=['Variable X'])
dfy = pd.DataFrame(np.random.randint(25,68,size=(rows, 1)), columns=['Variable Y'])
dfz = pd.DataFrame(np.random.randint(60,70,size=(rows, 1)), columns=['Variable Z'])

df = pd.concat([dfx,dfy,dfz], axis = 1)
#jtplot.style()

import ipywidgets as widgets
from IPython.display import display

def multiplot():
    opts = df.columns.values

    widg = widgets.SelectMultiple(
           options=opts,
           value=[opts[1]],
           rows=len(opts),
           description='Variables',
           disabled=False)

    display(widg)

    # what to do!? 
    df.plot()

    #attempts:
    #df[widg].plot()
    #df[widg.value[0]].plot()

interactive_plot = interactive(multiplot)
output = interactive_plot.children[-1]
output.layout.height = '350px'
interactive_plot

输出(有缺陷):

enter image description here

2 个答案:

答案 0 :(得分:4)

我发现使用multipleSelect小部件的最简单方法是使用装饰器interact

%matplotlib inline
import numpy as np
import pandas as pd
from ipywidgets.widgets import interact, SelectMultiple

np.random.seed(123)
rows = 50
dfx = pd.DataFrame(np.random.randint(90,110,size=(rows, 1)), columns=['Variable X'])
dfy = pd.DataFrame(np.random.randint(25,68,size=(rows, 1)), columns=['Variable Y'])
dfz = pd.DataFrame(np.random.randint(60,70,size=(rows, 1)), columns=['Variable Z'])

df = pd.concat([dfx,dfy,dfz], axis = 1)

sel_mul = SelectMultiple(description="Variables",options=df.columns,value=['Variable X','Variable Z'],disabled=False)
@interact(variables=sel_mul)
def plot_multiple(variables):
    df[list(variables)].plot()

这是result

答案 1 :(得分:3)

感谢明确的示例。不幸的是,我不确定SelectMultiple是否可以按您期望的方式使用。

通常,对于交互调用,您需要一个将参数传递给的函数。您无需在函数体内创建小部件,interact调用应从传递的参数中了解需要哪种类型的输入小部件。

请参见此处的一些示例,其中指定了字符串选项(https://ipywidgets.readthedocs.io/en/stable/examples/Using%20Interact.html#Widget-abbreviations

我对您的代码做了一些小改动,以实现与Dropdown选择器的交互。我怀疑您是否要使用SelectMultiple而不是Dropdown,这超出了interact的功能。您可能需要分别创建小部件,然后使用observe

# imports
%matplotlib inline

from ipywidgets import interactive
import pandas as pd
import numpy as np
# from jupyterthemes import jtplot

# Sample data
np.random.seed(123)
rows = 50
dfx = pd.DataFrame(np.random.randint(90,110,size=(rows, 1)), columns=['Variable X'])
dfy = pd.DataFrame(np.random.randint(25,68,size=(rows, 1)), columns=['Variable Y'])
dfz = pd.DataFrame(np.random.randint(60,70,size=(rows, 1)), columns=['Variable Z'])

df = pd.concat([dfx,dfy,dfz], axis = 1)
#jtplot.style()

import ipywidgets as widgets
from IPython.display import display

def multiplot(a):
    opts = df.columns.values
    df.loc[:, a].plot()

interactive_plot = interactive(multiplot, a=['Variable X', 'Variable Y', 'Variable Z'])
output = interactive_plot.children[-1]
output.layout.height = '350px'
interactive_plot

enter image description here

这是使用observe,一个SelectMultiple小部件和一个Output小部件的版本:

# imports
%matplotlib inline

from ipywidgets import interactive
import pandas as pd
import numpy as np
from IPython.display import clear_output
import matplotlib.pyplot as plt

# Sample data
np.random.seed(123)
rows = 50
dfx = pd.DataFrame(np.random.randint(90,110,size=(rows, 1)), columns=['Variable X'])
dfy = pd.DataFrame(np.random.randint(25,68,size=(rows, 1)), columns=['Variable Y'])
dfz = pd.DataFrame(np.random.randint(60,70,size=(rows, 1)), columns=['Variable Z'])

df = pd.concat([dfx,dfy,dfz], axis = 1)
#jtplot.style()

import ipywidgets as widgets
from IPython.display import display

opts = df.columns.values

selector = widgets.SelectMultiple(
options=opts,
value=[opts[1]],
rows=len(opts),
description='Variables',
disabled=False)

output = widgets.Output()

display(selector)
display(output)

def multiplot(widg):
    choices = widg['new']
    data = df.loc[:, choices] if choices else df
    output.clear_output(wait=True)
    with output:
        ax = data.plot()
        plt.show()

selector.observe(multiplot, names='value')

enter image description here