我正在尝试创建一个交互式条形图,当用户选择一个值(基于鼠标单击)时,该条形图的条形会更改颜色。所选值显示在图表的底部,并且条形图会根据所选值高于或低于样本平均值的概率而改变颜色。
我被卡在酒吧的颜色上。当我单击图表时,只有第一个柱会更改颜色,然后在以后的单击中不会更新。
总体预期结果是允许根据鼠标单击事件选择多个值。然后打算在所选值处绘制水平线,然后根据所选值在样本平均值范围内的概率对条进行重新着色。这是在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)```