[英]How to change bin widths using JavaScript callback and Bokeh slider
任何人都可以提供有关如何使用 Bokeh 滑块对象更改 Bokeh 直方图的 bin 宽度的帮助。 我知道如何使用 Python 回调来做到这一点,但想知道如何使用 JavaScript 回调——使用CustomJS
函数来做到这一点。
import pandas as pd
import numpy as np
from bokeh.plotting import figure
from bokeh.models.widgets import Slider
from bokeh.models import ColumnDataSource, CustomJS
# generate random data
x = np.random.choice(a = 20, size = 100, replace = True)
# generate histogram
hist, edges = np.histogram(x, bins = 10)
# create dataframe of histogram
hist_df = pd.DataFrame({'count': hist, 'left':edges[:-1], 'right':edges[1:]})
# generate bokeh data source
bokeh_data = ColumnDataSource(hist_df)
# generate bokeh plot
plot = figure()
plot.quad(source = bokeh_data, bottom = 0, top = 'counts', left = 'left', right = 'right')
# generate slider object to change bin widths interactively
bin_slider = Slider(start = 10, end = 100, step = 5, value = 10)
bin_slider.js_on_change('value', callback)
# javascript callback function to change bin widths goes here...
callback = CustomJS ....
任何帮助是极大的赞赏。
谢谢
我对此的解决方案是使用原始数据(在您的情况下为 x)来重新计算 customjs 中的直方图。 我对 javascript 真的很陌生,所以可能有更优雅的方式来实现这一点。 但无论如何,代码对我有用,所以你可以试一试。
import pandas as pd
import numpy as np
from bokeh.plotting import figure
from bokeh.models.widgets import Slider, RangeSlider
from bokeh.models import ColumnDataSource, CustomJS
# generate random data
x = np.random.normal(10, 1, 1000)
# generate histogram
hist, edges = np.histogram(x, bins = 10)
# create dataframe of histogram
hist_df = pd.DataFrame({'count': hist, 'left':edges[:-1], 'right':edges[1:]})
# generate bokeh data source for initial histogram
bokeh_data = ColumnDataSource(hist_df)
# generate bokeh data source for new histogram calculation
x_df=pd.DataFrame(x,columns={'value'})
x_src=ColumnDataSource(x_df)
# generate bokeh plot
plot = figure()
plot.quad(source = bokeh_data, bottom = 0, top = 'count', left = 'left', right = 'right')
callback = CustomJS(args=dict(source1=x_src,source2=bokeh_data), code="""
var data = source1.data;
var val = data['value'];
var length = val.length;
var size = bin_size.value;
var min = data_range.value[0];
var max = data_range.value[1];
// Decide number of bins needed
var bins = Math.floor((max - min) / size);
// Put left edge point in an array
var left_edge = new Array(bins);
for (var i = 0; i < bins; i++){
left_edge[i] = min+i*size;
}
// Put right edge point in an array
var right_edge = new Array(bins);
for (var i = 0; i < bins; i++){
right_edge[i] = min+(i+1)*size;
}
// Initialize frequency
var frequency = new Array(bins);
for (var i = 0; i < bins; i++) frequency[i] = 0;
// Calculate frequency for each bin
for (var i = 0; i < length; i++) {
if (val[i]==min) frequency[0]++;
else if (val[i]==max) frequency[bins-1]++;
else frequency[Math.floor((val[i] - min) / size)]++;
}
// Oupdate data source with new bins and frequency
var bokeh_data_new={};
bokeh_data_new.count=frequency;
bokeh_data_new.left=left_edge;
bokeh_data_new.right=right_edge;
source2.data=bokeh_data_new;
""")
# generate slider object to change bin widths interactively
binwidth_slider = Slider(start = 0, end = 1, step = 0.02, value = 0.5 , callback=callback)
callback.args["bin_size"] = binwidth_slider
# generate range slider object to change min and max of the data points to be shown interactively
range_slider = RangeSlider(start = 0, end = 20, step = 1, value = (0, 20), callback=callback)
callback.args["data_range"] = range_slider
widgets = WidgetBox(binwidth_slider, range_slider)
output_notebook()
show(row(plot, widgets))
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.