Hello,
I created a figure with vbar and line glyphs. I applied custom JS callbacks through the select widget, this widget allows the user to choose their preferred data view: monthly or daily. The default data value that support the glyph are monthly. When selecting the daily value on the widget, the figure’s axes and the glyphs adjust appropriately. When I use the widget to select the month value, then the axes range values and glyphs disappear. Can anyone help me find out why?
Notes:
- I have noticed that the callbacks work as intended if i comment out the vbar glyph code.
- I also receive this error on the browser console: “TypeError: t is undefined”
Versions:
Python: 3.7.1
Bokeh: 1.0.4
Firefox Browser: 65.0.1
Code:
import pandas as pd
from bokeh.plotting import figure, show
from bokeh.models.sources import ColumnDataSource
from bokeh.models import Range1d, FactorRange, CustomJS
from bokeh.models.widgets import Select
from bokeh.models.glyphs import VBar, Line
from bokeh.layouts import column
import math
#data gen
monthly_data = {‘widgets_made’ : [34.0, 30.0, 40.0, 53.0, 49.0, 62.0],
‘defects’ : [2.0,1.0,3.0,3.0,2.0,4.0]}
daily_data = {‘widgets_made’ : [3.0, 6.0, 5.0, 3.0, 7.0, 10.0,3.0, 6.0, 5.0, 3.0, 7.0, 10.0],
‘defects’ : [1.0,1.0,3.0,3.0,2.0,4.0,1.0,1.0,3.0,3.0,2.0,4.0]}
df_monthly =pd.DataFrame(monthly_data, index=[‘2018-01’, ‘2018-02’,‘2018-03’,‘2018-04’,‘2018-05’,‘2018-06’])
df_daily =pd.DataFrame(daily_data, index=[‘2018-01-01’, ‘2018-01-02’,‘2018-01-03’,‘2018-01-04’,‘2018-01-05’,‘2018-01-06’,
‘2018-01-07’,‘2018-01-08’,‘2018-01-09’,‘2018-01-10’,‘2018-01-11’,‘2018-01-12’])
fill_source = ColumnDataSource(df_monthly)
source_monthly = ColumnDataSource(df_monthly)
source_daily = ColumnDataSource(df_daily)
#VISUALIZATION: code to build chart
xdr = FactorRange(factors=fill_source.data[‘index’])
ydr = Range1d(start = 0, end = int(max(fill_source.data[‘widgets_made’] + 1.05)))
acv = figure(plot_width=1310, plot_height=400, x_range=xdr, y_range=ydr,x_axis_label=‘Date Range’, y_axis_label=‘Count’)
acv_bar = acv.vbar(x=‘index’, top=‘widgets_made’, width=.5, legend=‘Completed Tests’,source=fill_source)
acv_line = acv.line(‘index’, ‘defects’, line_width=2, color=‘red’, source=fill_source)
acv.xaxis.major_label_orientation = math.pi / 2
#Custom JS code for callback
codes = “”"
var f = cb_obj.value;
var sdata = source.data;
var data1 = monthly.data;
var data2 = daily.data;
if (f == "monthly") {
for (key in data1) {
sdata[key] = [];
for (i=0;i<data1[key].length;i++){
sdata[key].push(data1[key][i]);
}
}
//updating axes
var y_range_arr=sdata['widgets_made'];
var yrange_max = Math.max(...y_range_arr) * 1.05;
yrange.end = yrange_max;
xrange.factors = sdata['index'];
console.log(sdata);
} else if (f == "daily") {
for (key in data2) {
sdata[key] = [];
for (k=0;k<data2[key].length;k++){
sdata[key].push(data2[key][k]);
}
}
//updating axes
var y_range_arr=sdata['widgets_made'];
var yrange_max = Math.max(...y_range_arr) * 1.05;
yrange.end = yrange_max;
xrange.factors = sdata['index'];
console.log(sdata)
};
yrange.change.emit();
xrange.change.emit();
source.change.emit();
“”"
callback = CustomJS(args=dict(source=fill_source, monthly=source_monthly, daily=source_daily,
yrange=acv.y_range, xrange=acv.x_range),code=codes)
#WIDGET: Building drop-down to choose different levels of aggregation
select = Select(title = ‘Data Aggregation Levels:’, value=‘monthly’,
options=[‘monthly’,‘daily’],callback=callback)
show(column(select,acv))
``