Источник Bokeh-Source не обновляется для всех линий на графике правильно при изменении с помощью пользовательского обратного вызова js - PullRequest
0 голосов
/ 17 июня 2020

У меня есть фрейм данных, который концентрируется на прогонах для 22 элементов. Он структурирован так:

      run           9Be       45Sc    .....
3/24/16 Run A      0.9280     nan
3/24/16 Run B      1.1052     0.4904
4/6/16 Run A       0.490      0.3374

Для каждого элемента мне нужно построить график концентрации по прогонам, а также средние и стандартные отклонения (в виде solid линий) для этого элемента. Я хочу создать график боке, где я могу выбрать элемент в таблице, и график будет обновляться с данными этого элемента. Код ниже

os.chdir(r'')


low=pd.read_excel(r"", sheet_name="QC LOW", skiprows=5, usecols=range(0,34))
low["run"]=low["run"].astype(str)
low.loc[~(low["run"].str.contains("A")) & ~(low["run"].str.contains("B")),"run"]=pd.to_datetime(low.loc[(~low["run"].str.contains("A")) & (~low["run"].str.contains("B")),"run"]).dt.strftime('%m/%d/%y')
cols=low.columns.tolist()
cols=cols[2:]

select = Select(title="Option:", value="9Be", options=cols)

source=ColumnDataSource(data=low)

#Using 9Be as default. Will be changed when updated
mean=source.data['9Be'].mean()
plus_three_sigma=mean+(source.data['9Be'].std()*3)
minus_three_sigma=mean-(source.data['9Be'].std()*3)
plus_two_sigma=mean+(source.data['9Be'].std()*2)
minus_two_sigma=mean-(source.data['9Be'].std()*2)

tips=[("Run", "@Run"),("Concentration", "$y")]
p = figure(plot_width=1300, plot_height=800, x_range=source.data["run"], tooltips=tips, title="QC Low", x_axis_label="Run ID",y_axis_label="Concentration ng/mL")
p.line(x=source.data["run"], y=mean, line_width=1, color="black")
p.line(x=source.data["run"], y=plus_three_sigma, line_width=1, color="red")
p.line(x=source.data["run"], y=minus_three_sigma, line_width=1, color="red")
p.line(x=source.data["run"], y=minus_two_sigma, line_width=1, color="green",line_dash="dashed")
p.line(x=source.data["run"], y=plus_two_sigma, line_width=1, color="green",line_dash="dashed")
pc=p.circle(x='run', y="9Be",source=source)
p.xaxis.major_label_orientation = 1.2

callback = CustomJS(args=dict(source=source), code="""
    var data=source.data;
    data['9Be'] = data[cb_obj.value];
    source.change.emit();
""")

output_file("output.html")


select.js_on_change('value', callback)

show(row(select,p))

В настоящее время диаграмма рассеяния обновляется правильно при выборе элементов ... большую часть времени (она не всегда обновляется. Например, если я выбираю элемент, а затем снова пытаюсь выбрать 9Be). Но моя главная проблема в том, что средние значения и стандартные отклонения не обновляются, хотя источник должен быть изменен?

1 Ответ

1 голос
/ 18 июня 2020

Вы используете файл stati c HTML, созданный с помощью show, но вам нужно запустить код Python при изменении текущего элемента. Либо вам нужно запустить код Python, который вычисляет среднее значение и другие параметры для всех столбцов заранее и сохранять их для использования позже в CustomJS.code, либо вы должны использовать bokeh serve для иметь возможность запускать Python обратные вызовы в ответ на некоторые действия пользователя.

Другая проблема с вашим кодом заключается в том, что вы изменяете данные в CustomJS.code. Не делайте этого - вы просто перезаписываете значения 9Be, полностью теряя их. Вместо этого сохраните каждое средство визуализации (значение, возвращаемое из p.line, p.circle, et c.), Передайте средства визуализации в CustomJS.args (так же, как с source, вам придется дать им несколько имен), и обновите соответствующее поле вместо обновления данных. Он должен выглядеть примерно так в CustomJS.code:

pc.glyph.y = {field: cb_obj.value};

Часть {field: ...} необходима для боке JS - она ​​создается Бокеном на стороне Python автоматически для вас, но у вас есть применить его вручную в CustomJS.code. Для значений stati c, таких как предварительно вычисленное среднее значение, это будет примерно так:

mean_renderer.glyph.y = {value: current_mean};

Как хранить current_mean зависит от вас. Вы можете сохранить все предварительно вычисленные значения, например, в другом источнике данных и просто изменить имя столбца на {field: ...} вместо изменения значения на {value: ...}.

...