首页 > 解决方案 > 如何将 matplotlib 光标 mouse_move 对象与滑块值连接?

问题描述

我有一个图,其中 2 条轴线随着鼠标移动而移动。我想在底部放置一个滑块,它将改变这些轴线覆盖的 y 轴值的范围。

在此处输入图像描述

我尝试了以下代码。问题是滑块的值发生了变化,但鼠标事件对象没有更新。

谢谢

%matplotlib notebook


import pandas as pd
import numpy as np
import scipy.stats as stats

import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
from matplotlib.widgets import Slider



np.random.seed(12345)

df = pd.DataFrame([np.random.normal(32000,200000,3650), 
                   np.random.normal(43000,100000,3650), 
                   np.random.normal(43500,140000,3650), 
                   np.random.normal(48000,70000,3650)], 
                  index=[1992,1993,1994,1995])
df=df.T

data=df.describe().T
data['error']=df.sem()
data['error_range']=df.sem()*1.96

fig, ax = plt.subplots()


def plot_bar(x,y,error,title,alpha_level=0.7):
    ax.bar(x,y, yerr=error,
       align='center', alpha=alpha_level,
       error_kw=dict(ecolor='black', elinewidth=1, capsize=5, capthick=1)) 
    ax.spines['top'].set_visible(False)
    ax.spines['right'].set_visible(False)

    ax.set_title(title)
    ax.xaxis.set_major_locator(ticker.FixedLocator(data.index))
    ax.yaxis.set_major_formatter(ticker.StrMethodFormatter('{x:,.0f}'))
    ax.set_ylim([-5000,55000])
    ax.set_xlim([1990.5,1995.5])
    ax.spines['bottom'].set_position(('data',0))
    ax.spines['left'].set_position(('data',1991.4))
    plt.tight_layout()
    
    return (ax, ax.get_children()[1:5])

ax, barlist=plot_bar(x=data.index,y=data['mean'],error=data['error_range'],title='Even Harder Option', alpha_level=0.6) 

fig.subplots_adjust(bottom=0.1)


axcolor = 'lightgoldenrodyellow'
range_slider = plt.axes([0.2, 0.05, 0.65, 0.03], facecolor=axcolor)


slider = Slider(range_slider, 'Range', 0, 55000, valinit=10000, valstep=100)

def update(val):
    slider.val = slider.val


slider.on_changed(update)


class Cursor(object):
    _df=None
    _bl=None
    def __init__(self, ax,data_F, bars, slider):
        
        #global slider
        self._df=data_F
        self._bl=bars
        self.ax = ax
        self.lx1 = ax.axhline(color='b')
        self.lx2 = ax.axhline(color='b')
        self.text1 = ax.text(1990.55, y, '%d' %45,bbox=dict(fc='white',ec='k'), fontsize='x-small')
        self.text2 = ax.text(1990.55, y, '%d' %45,bbox=dict(fc='white',ec='k'), fontsize='x-small')
        self._sl = slider.val
        

    def mouse_move(self, event):
        if not event.inaxes:
            return
        x, y = event.xdata, event.ydata
        r = self._sl
        
        
        y1 , y2 = y+r/2 , y-r/2
        #self.lx1.set_ydata(y)
        self.lx1.set_ydata(y+r/2)
        self.lx2.set_ydata(y-r/2)
        
        for i in range(4):
            #shade = cmap(norm((data['mean'.values[i]-event.ydata)/df_std.values[i]))
            prob1=stats.norm.cdf(y1,self._df['mean'].values[i],self._df['error'].values[i])
            prob2=stats.norm.cdf(y2,self._df['mean'].values[i],self._df['error'].values[i])
            shade = cmap(prob1-prob2)
            self._bl[i].set_color(shade) 
        self.text1.set_text('%d' %y1)
        self.text1.set_position((1990.55, y1))
        self.text2.set_text('%d' %y2)
        self.text2.set_position((1990.55, y2))
        plt.draw()
     
    
cursor = Cursor(ax, data,barlist, slider)
#plt.connect('range_change', cursor.update)
plt.connect('motion_notify_event', cursor.mouse_move)

标签: python-3.xmatplotlibslidercursormouseevent

解决方案


推荐阅读