Introduction to Bokeh Server

Tavish Aggarwal

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!

Author Info

Tavish Aggarwal

Website: http://tavishaggarwal.com

Living in Hyderabad and working as a research-based Data Scientist with a specialization to improve the major key performance business indicators in the area of sales, marketing, logistics, and plant productions. He is an innovative team leader with data wrangling out-of-the-box capabilities such as outlier treatment, data discovery, data transformation with a focus on yielding high-quality results.