Изменить цвет графиков на основе события нажатия мыши - PullRequest
2 голосов
/ 02 апреля 2019

Я пытаюсь создать интерактивную гистограмму, в которой столбцы диаграммы меняют цвет, когда пользователь выбирает значение (на основе щелчка мыши). Выбранное значение отображается в нижней части графика, и столбцы должны менять цвет в зависимости от вероятности того, что выбранное значение будет выше или ниже среднего значения для образца.

Я застрял на раскраске баров. Когда я нажимаю на график, только первая полоса меняет цвет, а затем не обновляется при последующих щелчках.

Общий ожидаемый результат - выбор нескольких значений на основе событий щелчка мыши. Намерение состоит в том, чтобы нарисовать горизонтальную линию при выбранном значении, а затем перекрасить столбцы на основе вероятности того, что выбранное значение находится в диапазоне среднего значения выборки. Это работает в Юпитере.

Я все еще новичок в этом, поэтому, безусловно, ценю любой совет, который вы можете дать.

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 Ответ

1 голос
/ 02 апреля 2019

Ты так близко!Проблема в том, что вы переопределяете 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

...