努力理解为什么这个散景图不允许我更改绘图并查看预测的数据。出现绘图和选择(下拉菜单)菜单,但我无法更改项目的绘图在菜单中。
通过Anaconda运行Bokeh 1.2.0。该代码已在Jupyter内部和外部运行。运行代码时无错误显示。我浏览了与该问题相关的少数SO帖子,但我无法成功应用相同的解决方案。
我不确定如何由此产生玩具问题,因此,除了下面的代码示例外,完整的代码(包括回归代码和相应的数据)可以在我的github here中找到(代码: Regression&Plotting.ipynb
,数据: 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中没有错误显示。更新:错误
2)CLI显示UserWarning: Pandas doesn't allow columns to be careated via a new attribute name
,引用`historical_data.data = ColumnDatasource.from_df(new_hist_source)。
最终,该图应该具有一条历史数据线,以及一条来自sklearn的预测数据线或点。它还具有一个下拉菜单,用于选择要绘制的每个项目(一次选择一个)。
update_plot
是空操作,实际上不对Bokeh模型状态进行任何更改,这是更改Bokeh图的必要条件。更改散景模型状态意味着为散景对象的属性分配新值。通常,要更新图,您将计算一个新的数据字典,然后从中设置一个现有的CDS:
source.data = new_data # plain python dict
或者,如果要从DataFame更新:
source.data = ColumnDataSource.from_df(new_df)
此外,请勿将.data
从一个CDS分配给另一个:
source.data = other_source.data # BAD
相反,您的update_plot
计算一些新数据,然后将其丢弃。请注意,从任何Bokeh回调中返回任何内容都没有任何目的。回调由Bokeh库代码调用,该代码不期望或不使用任何返回值。最后,我认为最后的JS控制台错误都不是BokehJS产生的。