为什么Bokeh的地块不会随着地块选择而改变? [英] Why is Bokeh's plot not changing with plot selection?

查看:40
本文介绍了为什么Bokeh的地块不会随着地块选择而改变?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

努力理解为什么这个散景效果视图不允许我更改图并查看预测数据.出现图和选择(下拉菜单)菜单,但我无法更改菜单中项目的图.

Struggling to understand why this bokeh visual will not allow me to change plots and see the predicted data. The plot and select (dropdown-looking) menu appears, but I'm not able to change the plot for items in the menu.

通过Anaconda运行Bokeh 1.2.0.该代码已在内部&在Jupyter之外.运行代码时没有错误显示.我已经浏览了与同一问题相关的少数SO帖子,但未能成功应用相同的解决方案.

Running Bokeh 1.2.0 via Anaconda. The code has been run both inside & outside of Jupyter. No errors display when the code is run. I've looked through the handful of SO posts relating to this same issue, but I've not been able to apply the same solutions successfully.

我不确定如何由此产生玩具问题,因此,除了下面的代码示例外,完整的代码(包括回归代码和相应的数据)都可以在我的github

I wasn't sure how to create a toy problem out of this, so in addition to the code sample below, the full code (including the regression code and corresponding data) can be found at my github here (code: Regression&Plotting.ipynb, data: pred_data.csv, historical_data.csv, features_created.pkd.)

import pandas as pd
import datetime
from bokeh.io import curdoc, output_notebook, output_file
from bokeh.layouts import row, column
from bokeh.models import Select, DataRange1d, ColumnDataSource
from bokeh.plotting import figure

#Must be run from the command line
def get_historical_data(src_hist, drug_id):
    historical_data = src_hist.loc[src_hist['ndc'] == drug_id]
    historical_data.drop(['Unnamed: 0', 'date'], inplace = True, axis = 1)#.dropna()
    historical_data['date'] = pd.to_datetime(historical_data[['year', 'month', 'day']], infer_datetime_format=True)
    historical_data = historical_data.set_index(['date'])
    historical_data.sort_index(inplace = True)
    # csd_historical = ColumnDataSource(historical_data)
    return historical_data

def get_prediction_data(src_test, drug_id):
    #Assign the new date
    #Write a new dataframe with values for the new dates
    df_pred = src_test.loc[src_test['ndc'] == drug_id].copy()
    df_pred.loc[:, 'year'] = input_date.year
    df_pred.loc[:, 'month'] = input_date.month
    df_pred.loc[:, 'day'] = input_date.day
    df_pred.drop(['Unnamed: 0', 'date'], inplace = True, axis = 1)
    prediction = lin_model.predict(df_pred)
    prediction_data = pd.DataFrame({'drug_id': prediction[0][0], 'predictions': prediction[0][1], 'date': pd.to_datetime(df_pred[['year', 'month', 'day']], infer_datetime_format=True, errors = 'coerce')})
    prediction_data = prediction_data.set_index(['date'])
    prediction_data.sort_index(inplace = True)
    # csd_prediction = ColumnDataSource(prediction_data)
    return prediction_data

def make_plot(historical_data, prediction_data, title):
    #Historical Data
    plot = figure(plot_width=800, plot_height = 800, x_axis_type = 'datetime',
                  toolbar_location = 'below')
    plot.xaxis.axis_label = 'Time'
    plot.yaxis.axis_label = 'Price ($)'
    plot.axis.axis_label_text_font_style = 'bold'
    plot.x_range = DataRange1d(range_padding = 0.0)
    plot.grid.grid_line_alpha = 0.3
    plot.title.text = title
    plot.line(x = 'date', y='nadac_per_unit', source = historical_data, line_color = 'blue', ) #plot historical data
    plot.line(x = 'date', y='predictions', source = prediction_data, line_color = 'red') #plot prediction data (line from last date/price point to date, price point for input_date above)
    return plot

def update_plot(attrname, old, new):
    ver = vselect.value
    new_hist_source = get_historical_data(src_hist, ver) #calls the function above to get the data instead of handling it here on its own
    historical_data.data = ColumnDataSource.from_df(new_hist_source)
    # new_pred_source = get_prediction_data(src_pred, ver)
    # prediction_data.data = new_pred_source.data

#Import data source
src_hist = pd.read_csv('data/historical_data.csv')
src_pred = pd.read_csv('data/pred_data.csv')

#Prep for default view
#Initialize plot with ID number
ver = 781593600
#Set the prediction date
input_date = datetime.datetime(2020, 3, 31) #Make this selectable in future
#Select-menu options
menu_options = src_pred['ndc'].astype(str) #already contains unique values
#Create select (dropdown) menu
vselect = Select(value=str(ver), title='Drug ID', options=sorted((menu_options)))

#Prep datasets for plotting
historical_data = get_historical_data(src_hist, ver)
prediction_data = get_prediction_data(src_pred, ver)

#Create a new plot with the source data
plot = make_plot(historical_data, prediction_data, "Drug Prices")

#Update the plot every time 'vselect' is changed'
vselect.on_change('value', update_plot)
controls = row(vselect)

curdoc().add_root(row(plot, controls))

已更新:错误:

1)Jupyter Notebook中没有错误显示.

1) No errors show up in Jupyter Notebook.

2)CLI显示了一个 UserWarning:Pandas不允许通过新的属性名称来复制列,引用的是"historical_data.data = ColumnDatasource.from_df(new_hist_source)".

2) CLI shows a UserWarning: Pandas doesn't allow columns to be careated via a new attribute name, referencing `historical_data.data = ColumnDatasource.from_df(new_hist_source).

最终,该图应该具有一条历史数据线,以及一条来自sklearn的预测数据线或点.它还具有一个下拉菜单,用于选择要绘制的每个项目(一次选择一个).

Ultimately, the plot should have a line for historical data, and another line or dot for predicted data derived from sklearn. It also has a dropdown menu to select each item to plot (one at a time).

推荐答案

您的 update_plot 是空操作,实际上不会对Bokeh模型状态进行任何更改,这是更改的必要条件散景图.更改散景模型状态意味着为散景对象上的属性分配新值.通常,要更新图,您将计算一个新的数据字典,然后从中设置一个现有的CDS:

Your update_plot is a no-op that does not actually make any changes to Bokeh model state, which is what is necessary to change a Bokeh plot. Changing Bokeh model state means assigning a new value to a property on a Bokeh object. Typically, to update a plot, you would compute a new data dict and then set an existing CDS from it:

source.data = new_data  # plain python dict

或者,如果您想从DataFame更新:

Or, if you want to update from a DataFame:

source.data = ColumnDataSource.from_df(new_df)

顺便说一句,请勿将 .data 从一个CDS分配给另一CDS:

As an aside, don't assign the .data from one CDS to another:

source.data = other_source.data  # BAD

通过对比,您的 update_plot 计算一些新数据,然后将其丢弃.请注意,从任何Bokeh回调中返回任何内容都没有任何目的.回调由Bokeh库代码调用,该代码不期望或不使用任何返回值.

By contrast, your update_plot computes some new data and then throws it away. Note there is never any purpose to returning anything at all from any Bokeh callback. The callbacks are called by Bokeh library code, which does not expect or use any return values.

最后,我认为最后的JS控制台错误都不是BokehJS产生的.

Lastly, I don't think any of those last JS console errors were generated by BokehJS.

这篇关于为什么Bokeh的地块不会随着地块选择而改变?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆