小部件中的 Ipython 交互式图例在更新时没有响应

问题描述

我正在尝试在 jupyter 笔记本中为传感器 (B) 的时间线实现一个小部件,用户应该能够在其中选择他想要看到的水果 (A)。他还应该能够选择他想要检查的时间段。根据我发现的以下代码,我尝试合并一个小部件。

  • [https://stackoverflow.com/questions/31410043/hiding-lines-after-showing-a-pyplot-figure][1]

第一次绘制整个数据周期时,交互式绘图与附加代码一起使用。但是每次我更新情节时,交互式图例不再响应。当我点击图例时,什么也没发生。

我找不到正确的方法,我尝试了各种更新情节或清除情节的方法,但总是出现同样的问题。

Joe Kingston 的互动情节部分

import pandas as pd
import seaborn as sns

import ipywidgets as widgets
from ipywidgets import AppLayout,Button,Layout
%matplotlib widget
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
from matplotlib.dates import DateFormatter

# generate dummy data
dti = pd.date_range("2018-01-01",periods=10,freq="H")
d = {"A":["Apple","Banana"] * 5,"B":np.random.randint(0,10,size=(10))}
df = pd.DataFrame(d,index = dti)
df_pump = df

# from Joe Kington,Stackoverflow
def main():
    #prepare labels for plotting
    labels = df_pump["A"].unique()

    # if one of the time pickers is empty,use the whole dataset
    if start_date_picker.value or end_date_picker.value == None:
        df_plot = df_pump
    # else use user entered dates
    else:
        df_plot = df_pump.loc[start_date_picker.value:end_date_picker.value]

    # make a new line for each container of the plant,e.g. HYD1,HYD2 etc.
    fig,ax = plt.subplots(figsize=(9,6))
    for i in range(0,len(labels)):
        sns.scatterplot(x = df_plot.loc[df_plot["A"] == labels[i],"B"].index,y = df_plot.loc[df_plot["A"] == labels[i],"B"],label=labels[i],)

    ax.legend(loc='upper left',bBox_to_anchor=(1.05,1),ncol=2,borderaxespad=0)
    fig.subplots_adjust(right=0.55)
    fig.suptitle('pH Verlauf pro Behälter \n' +
                '\n Right-click to hide all\nMiddle-click to show all',va='top',size='large')
    plt.ylabel("pH")
    plt.xlabel("")
    ax.xaxis.set_major_formatter(DateFormatter('%d %b %y'),) # maybee use dateformatter

    plt.tight_layout()

    leg = interactive_legend()
    return fig,ax,leg

def interactive_legend(ax=None):
    if ax is None:
        ax = plt.gca()
    if ax.legend_ is None:
        ax.legend()

    return InteractiveLegend(ax.get_legend())

class InteractiveLegend(object):
    def __init__(self,legend):
        self.legend = legend
        self.fig = legend.axes.figure

        self.lookup_artist,self.lookup_handle = self._build_lookups(legend)
        self._setup_connections()

        self.update()

    def _setup_connections(self):
        for artist in self.legend.texts + self.legend.legendHandles:
            artist.set_picker(10) # 10 points tolerance

        self.fig.canvas.mpl_connect('pick_event',self.on_pick)
        self.fig.canvas.mpl_connect('button_press_event',self.on_click)

    def _build_lookups(self,legend):
        labels = [t.get_text() for t in legend.texts]
        handles = legend.legendHandles
        label2handle = dict(zip(labels,handles))
        handle2text = dict(zip(handles,legend.texts))

        lookup_artist = {}
        lookup_handle = {}
        for artist in legend.axes.get_children():
            if artist.get_label() in labels:
                handle = label2handle[artist.get_label()]
                lookup_handle[artist] = handle
                lookup_artist[handle] = artist
                lookup_artist[handle2text[handle]] = artist

        lookup_handle.update(zip(handles,handles))
        lookup_handle.update(zip(legend.texts,handles))

        return lookup_artist,lookup_handle

    def on_pick(self,event):
        handle = event.artist
        if handle in self.lookup_artist:

            artist = self.lookup_artist[handle]
            artist.set_visible(not artist.get_visible())
            self.update()

    def on_click(self,event):
        if event.button == 3:
            visible = False
        elif event.button == 2:
            visible = True
        else:
            return

        for artist in self.lookup_artist.values():
            artist.set_visible(visible)
        self.update()

    def update(self):
        for artist in self.lookup_artist.values():
            handle = self.lookup_handle[artist]
            if artist.get_visible():
                handle.set_visible(True)
            else:
                handle.set_visible(False)
        self.fig.canvas.draw()

    def show(self):
        plt.show()

小部件部分:

def update_plot(change):
    #clear_output() tried with clearing,no success

    fig,leg = main()
    plt.show()
    
    
### open widget
output = widgets.Output()

with output:
    fig,leg = main()
    

# date pickers
start_date_picker = widgets.DatePicker(
    description='Starting date',disabled=False
)
end_date_picker = widgets.DatePicker(
    description='End date',disabled=False
)

# plot update and displays
b = widgets.Button(
    value=False,description='Time active',button_style='',# 'success','info','warning','danger' or ''
    tooltip='Click this button after choosing the desired time period',icon='chevron-circle-right' # (FontAwesome names without the `fa-` prefix)
)

# control links
b.on_click(update_plot)

# app layout
controls = widgets.HBox([start_date_picker,end_date_picker,b])

AppLayout(header=None,left_sidebar=None,center=output,right_sidebar=None,footer=controls)

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)