I gave your code a slight touch up, I believe it’s doing what you wanted now. There is most probably a better way of implementing what you want, but at least it kind of works. You would need to run your model with bokeh server for it to work.
import pandas as pd
import numpy as np
from bokeh.models import HoverTool
from bokeh.io import curdoc
from bokeh.plotting import figure, ColumnDataSource
from bokeh.layouts import row, column, gridplot
from bokeh.models.widgets import RangeSlider
class hist_data:
def __init__(self, df, col, n_bins, bin_range):
self.A_lwr = min(df['A'])
self.A_upr = max(df['A'])
self.B_lwr = min(df['B'])
self.B_upr = max(df['B'])
self.col = col
self.n_bins = n_bins
self.bin_range = bin_range
self.original_df = df
self.source = ColumnDataSource(self.create_hist_data(df))
def filt_df(self):
filt = (pd.DataFrame(self.original_df[(self.original_df.A >=self.A_lwr) & (self.original_df.A <= self.A_upr) & (self.original_df.B >= self.B_lwr) & (self.original_df.B <= self.B_upr)]))
print(f'{self.A_lwr} {self.A_upr} {self.B_lwr} {self.B_upr}')
filt.shape
return ColumnDataSource(self.create_hist_data(filt))
def create_hist_data(self,df):
arr_hist, edges = np.histogram(df[self.col],bins=self.n_bins, range=self.bin_range)
arr_df = pd.DataFrame({'count': arr_hist, 'left': edges[:-1], 'right': edges[1:]})
arr_df['f_count'] = ['%d' % count for count in arr_df['count']]
arr_df['f_interval'] = ['%d to %d ' % (left, right) for left, right in zip(arr_df['left'], arr_df['right'])]
return (arr_df)
df = pd.DataFrame(np.random.randint(0,100,size=(100, 4)), columns=list('ABCD'))
hist_data_A = hist_data(df,'A',df['A'].nunique(),[min(df['A']),max(df['A'])])
hist_data_B = hist_data(df,'B',df['B'].nunique(),[min(df['B']),max(df['B'])])
A_Slider= RangeSlider(start=min(df['A']), end=max(df['A']), value=(min(df['A']),max(df['A'])), step=1, title='YY in mm')
B_Slider = RangeSlider(start=min(df['B']), end=max(df['B']), value=(min(df['B']),max(df['B'])), step=1, title='ZZ')
def callback_A(attr,new,old):
hist_data_A.A_lwr = new[0]
hist_data_A.A_upr = new[1]
hist_data_A.source = hist_data_A.filt_df()
Graphs1.children[0] = plot_data_A()
def callback_B(attr,new,old):
hist_data_B.B_lwr = new[0]
hist_data_B.B_upr = new[1]
hist_data_B.source = hist_data_B.filt_df()
Graphs1.children[1] = plot_data_B()
A_Slider.on_change("value",callback_A)
B_Slider.on_change("value",callback_B)
(df,'A',df['A'].nunique(),[min(df['A']),max(df['A'])])
(df,'B',df['B'].nunique(),[min(df['B']),max(df['B'])])
# Histogram
def interactive_histogram( hist_data, title,x_axis_label,x_tooltip):
source = hist_data
# Set up the figure same as before
toollist = ['lasso_select', 'tap', 'reset', 'save','crosshair','wheel_zoom','pan','hover','box_select']
p = figure(plot_width = 500,
plot_height = 500,
title = title,
x_axis_label = x_axis_label,
y_axis_label = 'Count',tools=toollist)
# Add a quad glyph with source this time
p.quad(bottom=0,
top='count',
left='left',
right='right',
source=source,
fill_color='red',
hover_fill_alpha=0.7,
hover_fill_color='blue',
line_color='black')
# Add style to the plot
p.title.align = 'center'
p.title.text_font_size = '18pt'
p.xaxis.axis_label_text_font_size = '12pt'
p.xaxis.major_label_text_font_size = '12pt'
p.yaxis.axis_label_text_font_size = '12pt'
p.yaxis.major_label_text_font_size = '12pt'
# Add a hover tool referring to the formatted columns
hover = HoverTool(tooltips = [(x_tooltip, '@f_interval'),
('Count', '@f_count')])
# Add the hover tool to the graph
p.add_tools(hover)
return p
binsize = 10
def plot_data_A():
A_hist = interactive_histogram(hist_data_A.source, 'A Histogram','A','A')
return A_hist
def plot_data_B():
B_hist = interactive_histogram(hist_data_B.source, 'B Histogram','B ','B')
return B_hist
#
Graphs1 = row([plot_data_A(), plot_data_B()])
Controls1= column([A_Slider,B_Slider])
grid = gridplot([[Graphs1],
[Controls1]])
curdoc().add_root(grid)
curdoc().title = "questiontrialsample"