Introduction to Bokeh Server
August 9, 2021
In the previous post, Data Visualization using the Bokeh package in Python, we learned about generating powerful visualizations using the Bokeh package in Python. If you have not gone through this post or don't know about Bokeh, I highly recommend you go through the post before proceeding further.
We will continue our discussion on Bokeh, and we will see how to build powerful applications using the Bokeh package.
Advantages of Bokeh Server
- Visualization/reports can be viewed by a large audience, as output is in the form of HTML pages. Therefore, it can be deployed as a web application.
- We can generate real-time interactive visualizations.
- We can build apps and dashboards
Running Bokeh Server
To run the bokeh server, we need to run the below command:
bokeh serve --show <file.py>
I would recommend creating python files only(.py) instead of creating a Jupyter notebook. I feel it's much easy in this way.
We can also run an app in the directory style approach to create more sophisticated bokeh app:
bokeh serve --show /directory
Getting Started
In all the examples shown below, we will be using house property sales dataset from the kaggle. The data has been loaded in housePropertyDataset
variable.
import pandas as pd
housePropertyDataset = pd.read_csv('house_property_sales.csv')
Let's get started and build our first bokeh application using bokeh server. In this example, we will be plotting TotalBsmtSF
and SalePrice
column of housePropertyDataset
.
Refer to the code shown below:
# Perform necessary imports
from bokeh.io import curdoc
from bokeh.plotting import figure, ColumnDataSource
from bokeh.layouts import widgetbox
import pandas as pd
housePropertyDataset = pd.read_csv('../house_property_sales.csv')
x = housePropertyDataset['TotalBsmtSF']
y = housePropertyDataset['SalePrice']
plot = figure(x_axis_label='Total Basement Area (In sqft)', y_axis_label='Sales Price')
source = ColumnDataSource(data={'total_bsmt_SF': x, 'sale_price': y})
# Add a line to the plot
plot.circle('total_bsmt_SF', 'sale_price', source=source)
layout = column(plot)
# Add the plot to the current document
curdoc().add_root(layout)
Note that we have used curdoc
function to add a layout to the current document which will be rendered on the page.
We have just created a basic visualization and serve it on bokeh server. Few of us might be wondering what is the advantage I am getting over here, as the same output can be generated using bokeh as well.
Which is TRUE, as of now we have just started and have not experienced the real power of Bokeh Server. Follow along the post to know the real power of bokeh server.
Sliders
It's time to add sliders to our visualization which is one of the advantages of using bokeh server instead of bokeh. Let's see an example shown below:
# Perform necessary imports
from bokeh.io import curdoc
from bokeh.plotting import figure, show, ColumnDataSource
from bokeh.models import Slider
from bokeh.layouts import widgetbox, column, row
import pandas as pd
housePropertyDataset = pd.read_csv('../house_property_sales.csv')
x = housePropertyDataset['TotalBsmtSF']
y = housePropertyDataset['SalePrice']
def changeArea(attr, old, new):
scale = slider.value
new_data = {
'total_bsmt_SF' : housePropertyDataset.loc[housePropertyDataset['YrSold'] == scale, 'TotalBsmtSF'],
'sale_price' : housePropertyDataset.loc[housePropertyDataset['YrSold'] == scale, 'SalePrice']
}
source.data = new_data
plot.title.text = 'Total Basement Area VS Sales Price for the Year Sold %d' % scale
plot = figure(x_axis_label='Total Basement Area (In sqft)', y_axis_label='Sales Price')
source = ColumnDataSource(data={'total_bsmt_SF': x, 'sale_price': y})
# Creating Slider
slider = Slider(title='Sales Year', start=2006, end=2010, step=1, value=2006)
slider.on_change('value', changeArea)
plot.circle('total_bsmt_SF', 'sale_price', source=source)
# Generating Layout
layout = column(widgetbox(slider), plot)
curdoc().add_root(layout)
We are using the callback function in the example shown above. Callbacks are functions that a user can define, like def callback(attr, old, new)
, that can be called automatically when some property of a Bokeh object (e.g., the value of a Slider) changes.
You might have noticed that we are slicing the data based on the year sold, and rendering new data. We are also updating the title of the plot based on the slider.
In this way, the slider can help us to achieve interactive visualizations where we can view plots based on the slider applied.
Dropdown Menu
We can add dropdowns to our visualization to make it interactive. Consider an example shown below:
# Perform necessary imports
from bokeh.io import curdoc
from bokeh.plotting import figure, show, ColumnDataSource
from bokeh.models import Slider, Select
from bokeh.layouts import widgetbox, column, row
import pandas as pd
housePropertyDataset = pd.read_csv('../house_property_sales.csv')
x = housePropertyDataset['TotalBsmtSF']
y = housePropertyDataset['SalePrice']
def salesCondition(attr, old, new):
source.data = {
'total_bsmt_SF' : housePropertyDataset.loc[housePropertyDataset['SaleCondition'] == new, 'TotalBsmtSF'],
'sale_price' : housePropertyDataset.loc[housePropertyDataset['SaleCondition'] == new, 'SalePrice']
}
plot = figure(x_axis_label='Total Basement Area (In sqft)', y_axis_label='Sales Price')
source = ColumnDataSource(data={'total_bsmt_SF': x, 'sale_price': y})
select = Select(title="Sales Condition", options=['Normal', 'Abnorml', 'Partial', 'AdjLand', 'Alloca', 'Family'], value='Normal')
select.on_change('value', salesCondition)
# Add a line to the plot
plot.circle('total_bsmt_SF', 'sale_price', source=source)
# Add slider1 and slider2 to a widgetbox
layout = column(widgetbox(select), plot)
# Add the plot to the current document
curdoc().add_root(layout)
Adding a dropdown menu is almost similar to adding a slider to the plot. We declare a function and define it to the on_change function of the Select option.
Every time we select the option from the menu, the plot is re-rendered.
Buttons
We can define toggle, radio, checkboxes, buttons, etc in our bokeh server visualization. Consider the code shown below displaying the button:
# Perform necessary imports
from bokeh.io import curdoc
from bokeh.plotting import figure, show, ColumnDataSource
from bokeh.models import Slider, Select, Button
from bokeh.layouts import widgetbox, column, row
import pandas as pd
housePropertyDataset = pd.read_csv('../house_property_sales.csv')
x = housePropertyDataset['TotalBsmtSF']
y = housePropertyDataset['SalePrice']
def reset():
source.data ={'total_bsmt_SF': x, 'sale_price': y}
plot = figure(x_axis_label='Total Basement Area (In sqft)', y_axis_label='Sales Price')
source = ColumnDataSource(data={'total_bsmt_SF': x, 'sale_price': y})
button = Button(label='Reset Filters')
button.on_click(reset)
# Add a line to the plot
plot.circle('total_bsmt_SF', 'sale_price', source=source)
# Add slider1 and slider2 to a widgetbox
layout = column(widgetbox(button), plot)
# Add the plot to the current document
curdoc().add_root(layout)
In the code shown above, we have declared a button to reset the plot.
In a similar way we can define any of button:
from bokeh.models import CheckboxGroup, RadioGroup, Toggle
toggle = Toggle(button_type='success', label='Toggle button')
checkbox = CheckboxGroup(labels=['Old', 'New', 'Unsold'])
radio = RadioGroup(labels=['Old', 'New', 'Unsold'])
curdoc().add_root(widgetbox(toggle, checkbox, radio))
Summary
In this post, we have seen:
- The basic to generate a bokeh Server application.
- We added sliders and dropdown menus to the visualization and make it interactive.
- We also saw how to add Toggle, radio button, checkbox to the visualizations.
You can find the final output of the bokeh application generated here.
We have seen the basics of Bokeh Server and created amazing interactive visualizations. Why don't you give it a try and make it much more interactive?
Let me know your views in the comment section below. Happy Learning!