On this tutorial, we create a totally interactive, visually compelling knowledge visualization dashboard utilizing Bokeh. We begin by turning uncooked knowledge into insightful plots, then improve them with options reminiscent of linked brushing, colour gradients, and real-time filters powered by dropdowns and sliders. As we progress, we deliver our dashboard to life with Customized JavaScript (CustomJS) interactivity, enabling immediate browser-side responses and not using a single Python callback. By mixing the perfect of Python’s analytical power with JavaScript’s responsiveness, we construct a seamless, dynamic dashboard expertise that redefines how we visualize and work together with knowledge. Take a look at the FULL CODES right here.
!pip set up bokeh pandas numpy scipy -q
import numpy as np
import pandas as pd
from bokeh.io import output_notebook, present, export_png, output_file
from bokeh.plotting import determine
from bokeh.layouts import row, column, gridplot
from bokeh.fashions import (
ColumnDataSource, HoverTool, LassoSelectTool, BoxSelectTool, TapTool,
ColorBar, LinearColorMapper, BasicTicker, PrintfTickFormatter, Slider,
Choose, CheckboxGroup, CustomJS, CDSView, BooleanFilter, Div, Button
)
from bokeh.palettes import Viridis256
from bokeh.fashions.widgets import DataTable, TableColumn
output_notebook()
np.random.seed(42)
N = 300
knowledge = pd.DataFrame({
"temp_c": 20 + 5 * np.random.randn(N),
"pressure_kpa": 101 + 3 * np.random.randn(N),
"humidity_pct": 40 + 15 * np.random.randn(N),
"sensor_id": np.random.selection(["A1","A2","B7","C3"], dimension=N),
"timestep": np.arange(N)
})
source_main = ColumnDataSource(knowledge)
p_scatter = determine(title="Temperature vs Stress", width=400, top=300,
x_axis_label="Temperature (°C)", y_axis_label="Stress (kPa)",
instruments="pan,wheel_zoom,reset")
scat = p_scatter.circle(x="temp_c", y="pressure_kpa", dimension=8, fill_alpha=0.6,
fill_color="orange", line_color="black", supply=source_main,
legend_label="Sensor Readings")
hover = HoverTool(tooltips=[
("Temp (°C)", "@temp_c{0.0}"), ("Pressure", "@pressure_kpa{0.0} kPa"),
("Humidity", "@humidity_pct{0.0}%"), ("Sensor", "@sensor_id"),
("Timestep", "@timestep")], renderers=[scat])
p_scatter.add_tools(hover)
p_scatter.legend.location = "top_left"
present(p_scatter)
We start by organising our surroundings and importing all the mandatory libraries. We then create an artificial dataset and visualize temperature towards strain utilizing a easy scatter plot with hover performance. This helps us set up a basis for our interactive dashboard. Take a look at the FULL CODES right here.
p_humidity = determine(title="Humidity vs Temperature (Linked Choice)", width=400, top=300,
x_axis_label="Temperature (°C)", y_axis_label="Humidity (%)",
instruments="pan,wheel_zoom,reset,box_select,lasso_select,faucet")
r2 = p_humidity.sq.(x="temp_c", y="humidity_pct", dimension=8, fill_alpha=0.6,
fill_color="navy", line_color="white", supply=source_main)
p_humidity.add_tools(HoverTool(tooltips=[
("Temp (°C)", "@temp_c{0.0}"), ("Humidity", "@humidity_pct{0.0}%"),
("Sensor", "@sensor_id")], renderers=[r2]))
layout_linked = row(p_scatter, p_humidity)
present(layout_linked)
We lengthen our visualization by including one other plot that hyperlinks humidity and temperature by shared knowledge. We use linked brushing in order that picks in a single plot mechanically replicate within the different, serving to us analyze relationships throughout a number of variables concurrently. Take a look at the FULL CODES right here.
color_mapper = LinearColorMapper(palette=Viridis256, low=knowledge["humidity_pct"].min(),
excessive=knowledge["humidity_pct"].max())
p_color = determine(title="Stress vs Humidity (Coloured by Humidity)", width=500, top=350,
x_axis_label="Stress (kPa)", y_axis_label="Humidity (%)",
instruments="pan,wheel_zoom,reset,box_select,lasso_select")
r3 = p_color.circle(x="pressure_kpa", y="humidity_pct", dimension=8, fill_alpha=0.8,
line_color=None, colour={"area": "humidity_pct", "rework": color_mapper},
supply=source_main)
color_bar = ColorBar(color_mapper=color_mapper, ticker=BasicTicker(desired_num_ticks=5),
formatter=PrintfTickFormatter(format="%4.1f%%"), label_standoff=8,
border_line_color=None, location=(0,0), title="Humidity %")
p_color.add_layout(color_bar, "proper")
present(p_color)
We improve our visualization by introducing a steady colour mapping function to symbolize humidity ranges. By including a colour bar and gradient, we make our chart extra informative and intuitive, permitting us to interpret variations visually. Take a look at the FULL CODES right here.
sensor_options = sorted(knowledge["sensor_id"].distinctive().tolist())
sensor_select = Choose(title="Sensor ID Filter", worth=sensor_options[0], choices=sensor_options)
temp_slider = Slider(title="Max Temperature (°C)",
begin=float(knowledge["temp_c"].min()),
finish=float(knowledge["temp_c"].max()), step=0.5,
worth=float(knowledge["temp_c"].max()))
columns_available = ["temp_c", "pressure_kpa", "humidity_pct", "sensor_id", "timestep"]
checkbox_group = CheckboxGroup(labels=columns_available,
lively=checklist(vary(len(columns_available))))
def filter_mask(sensor_val, max_temp):
return [(s == sensor_val) and (t <= max_temp)
for s, t in zip(data["sensor_id"], knowledge["temp_c"])]
bool_filter = BooleanFilter(filter_mask(sensor_select.worth, temp_slider.worth))
view = CDSView(filter=bool_filter)
p_filtered = determine(title="Filtered: Temp vs Stress", width=400, top=300,
x_axis_label="Temp (°C)", y_axis_label="Stress (kPa)",
instruments="pan,wheel_zoom,reset,box_select,lasso_select")
r_filtered = p_filtered.circle(x="temp_c", y="pressure_kpa", dimension=8, fill_alpha=0.7,
fill_color="firebrick", line_color="white",
supply=source_main, view=view)
p_filtered.add_tools(HoverTool(tooltips=[
("Temp", "@temp_c{0.0}"), ("Pressure", "@pressure_kpa{0.0}"),
("Humidity", "@humidity_pct{0.0}%"), ("Sensor", "@sensor_id")],
renderers=[r_filtered]))
def make_table_src(cols):
return ColumnDataSource(knowledge[cols])
table_src = make_table_src(columns_available)
table_columns = [TableColumn(field=c, title=c) for c in columns_available]
table_widget = DataTable(supply=table_src, columns=table_columns, width=500, top=200)
def update_filters(attr, previous, new):
bool_filter.booleans = filter_mask(sensor_select.worth, temp_slider.worth)
def update_table(attr, previous, new):
active_cols = [columns_available[i] for i in checkbox_group.lively]
new_src = make_table_src(active_cols)
table_widget.supply.knowledge = new_src.knowledge
table_widget.columns = [TableColumn(field=c, title=c) for c in active_cols]
sensor_select.on_change("worth", update_filters)
temp_slider.on_change("worth", update_filters)
checkbox_group.on_change("lively", update_table)
dashboard_controls = column(Div(textual content="Interactive Filters"), sensor_select,
temp_slider, Div(textual content="Columns in Desk"), checkbox_group)
dashboard_layout = row(column(p_filtered, table_widget), dashboard_controls)
present(dashboard_layout)
We introduce interactivity by widgets reminiscent of dropdowns, sliders, and checkboxes. We dynamically filter knowledge and replace tables in actual time, enabling us to simply discover completely different subsets and attributes of the dataset. Take a look at the FULL CODES right here.
mini_source = ColumnDataSource({
"x": np.linspace(0, 2*np.pi, 80),
"y": np.sin(np.linspace(0, 2*np.pi, 80))
})
p_wave = determine(title="Sine Wave (CustomJS: Enlarge factors)", width=400, top=250,
instruments="pan,wheel_zoom,reset")
wave_render = p_wave.circle(x="x", y="y", dimension=6, fill_alpha=0.8,
fill_color="inexperienced", line_color="black", supply=mini_source)
js_callback = CustomJS(args=dict(r=wave_render),
code="const new_size = r.glyph.dimension.worth + 2; r.glyph.dimension = new_size;")
grow_button = Button(label="Enlarge factors (CustomJS)", button_type="success")
grow_button.js_on_click(js_callback)
present(column(p_wave, grow_button))
We implement a JavaScript-based interplay utilizing Bokeh’s CustomJS. We create a sine wave visualization and permit customers to enlarge the plot markers with a button click on, demonstrating client-side management with none Python callbacks. Take a look at the FULL CODES right here.
stream_source = ColumnDataSource({"t": [], "val": []})
p_stream = determine(title="Streaming Sensor Worth", width=500, top=250,
x_axis_label="timestep", y_axis_label="worth",
instruments="pan,wheel_zoom,reset")
p_stream.line(x="t", y="val", supply=stream_source, line_width=3, line_alpha=0.8)
p_stream.circle(x="t", y="val", supply=stream_source, dimension=6, fill_color="crimson")
present(p_stream)
for t in vary(10):
new_point = {"t": [t], "val": [np.sin(t/2) + 0.2*np.random.randn()]}
stream_source.stream(new_point, rollover=200)
present(p_stream)
We simulate a stay knowledge stream by constantly including new knowledge factors to our plot. We watch the visualization replace dynamically, showcasing how Bokeh can deal with real-time knowledge and supply immediate visible suggestions.
In conclusion, we create a totally purposeful, real-time, and browser-interactive dashboard that showcases the total potential of Bokeh. We learn to visualize a number of dimensions of information, dynamically filter and replace visuals, and even harness JavaScript integration to make immediate, client-side updates instantly inside the browser. This hands-on expertise reveals us how Bokeh effortlessly merges Python and JavaScript, empowering us to design dashboards that aren’t simply interactive however clever, responsive, and production-ready.
Take a look at the FULL CODES right here. Be at liberty to take a look at our GitHub Web page for Tutorials, Codes and Notebooks. Additionally, be at liberty to observe us on Twitter and don’t neglect to affix our 100k+ ML SubReddit and Subscribe to our E-newsletter. Wait! are you on telegram? now you possibly can be part of us on telegram as properly.
Asif Razzaq is the CEO of Marktechpost Media Inc.. As a visionary entrepreneur and engineer, Asif is dedicated to harnessing the potential of Synthetic Intelligence for social good. His most up-to-date endeavor is the launch of an Synthetic Intelligence Media Platform, Marktechpost, which stands out for its in-depth protection of machine studying and deep studying information that’s each technically sound and simply comprehensible by a large viewers. The platform boasts of over 2 million month-to-month views, illustrating its recognition amongst audiences.
Elevate your perspective with NextTech Information, the place innovation meets perception.
Uncover the most recent breakthroughs, get unique updates, and join with a world community of future-focused thinkers.
Unlock tomorrow’s developments at this time: learn extra, subscribe to our publication, and develop into a part of the NextTech group at NextTech-news.com

