根据鼠标按下事件更改图表条的颜色

时间:2019-04-02 05:39:57

标签: python matplotlib event-handling bar-chart colorbar

我正在尝试创建一个交互式条形图,当用户选择一个值(基于鼠标单击)时,该条形图的条形会更改颜色。所选值显示在图表的底部,并且条形图会根据所选值高于或低于样本平均值的概率而改变颜色。

我被卡在酒吧的颜色上。当我单击图表时,只有第一个柱会更改颜色,然后在以后的单击中不会更新。

总体预期结果是允许根据鼠标单击事件选择多个值。然后打算在所选值处绘制水平线,然后根据所选值在样本平均值范围内的概率对条进行重新着色。这是在jupyter中运行。

对此我还是很陌生,所以请务必感谢您的任何建议。

import numpy as np
from scipy import stats
from scipy.stats import norm
import math
import matplotlib.gridspec as gridspec
import matplotlib.pyplot as plt
import ipywidgets as wdg
from matplotlib.cm import ScalarMappable

%matplotlib notebook

###Set up dummy data
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])

###Calculate statistics incl confidence interval for the mean.  Calculate 97.5% interquantile range of the normal distribution (being 1.96 x standard error)
df =  df.T
stats = df.describe(percentiles = [0.025, 0.25, 0.5, 0.75, 0.975])
mean = stats.loc['mean']
onesd_meanerror = df.sem(axis = 0)
error_low = onesd_meanerror*1.96
error_high = onesd_meanerror*1.96

###Setup initial chart and plot bar chart
fig = plt.figure()
ax = fig.add_subplot(111)
x_axis_label = df.columns.values
plt.xticks(x_axis_label)

bars = (ax.bar(x_axis_label, mean, width=0.85, alpha=0.9, align='center',
                yerr = (error_low, error_high), error_kw={'capsize': 10, 'elinewidth': 2, 'alpha':1}))

###Create and display textarea widget
txt = wdg.Textarea(
    value='',
    placeholder='',
    description='Y Value:',
    disabled=False)
display(txt)

### Formats color bar.  Need the scalar mapable to enable use of the color bar.
my_cmap = plt.cm.get_cmap('coolwarm')
sm = ScalarMappable(cmap=my_cmap, norm=plt.Normalize(0,1))
sm.set_array([])
cbar = plt.colorbar(sm)
cbar.set_label('Probability', rotation=270,labelpad=25)

ydataselect = 40000

class ClickChart(object):

    def __init__(self, ax):
        self.fig=ax.figure
        self.ax = ax
        self.horiz_line = ax.axhline(y=ydataselect, color='black', linewidth=2)
        self.fig.canvas.mpl_connect('button_press_event', self.onclick)

### Event handlers
    def onclick(self, event):
        self.horiz_line.remove()
        self.ypress = event.ydata
        self.horiz_line = ax.axhline(y=self.ypress, color='red', linewidth=2)
        txt.value = str(event.ydata)
        self.color_bar(event)

    def color_bar(self, event):

        for index, bar in enumerate(bars):
            bar.set_color(c=my_cmap(self.calc_prob(index)))
            print(index)

    def calc_prob(self, index):
        global mean, onesd_meanerror
        mean = mean.iloc[index]
        err = onesd_meanerror.iloc[index]
        result = norm.cdf(self.ypress, loc=mean, scale=err)
        return result

click = ClickChart(ax)```

1 个答案:

答案 0 :(得分:1)

您是如此亲密!问题是您正在mean内重新定义calc_prob()。进行更改以避免这种情况将修复代码并给出您想要的行为:

def calc_prob(self, index):
    global mean, onesd_meanerror
    mean2 = mean.iloc[index] # Changed
    err = onesd_meanerror.iloc[index]
    result = norm.cdf(self.ypress, loc=mean2, scale=err) # Changed
    return result

Dynamic figure