The Ultimate Guide to Data Visualization with Bokeh in Python
Data visualization is a crucial skill for data scientists and analysts in 2024. The ability to create clear, compelling charts and graphics makes data and insights more accessible and actionable for stakeholders. While many plotting libraries are available in Python, Bokeh stands out for its flexibility and interactivity.
In this in-depth guide, we‘ll dive into using Bokeh for data visualization in Python. Whether you‘re a beginner or looking to level up your plotting skills, you‘ll learn how to create an array of polished, interactive charts to bring your data to life. We‘ll cover installation, key features, styling, arranging multiple plots, and best practices. An example use case will reinforce the concepts. Let‘s get started!
What is Bokeh?
Bokeh is a powerful Python library for creating interactive visualizations in modern web browsers. It allows you to construct elegant graphics with minimal code and offers tools for building complex dashboards and data applications.
Some standout features of Bokeh are:
- Flexible and customizable: Modify every aspect of your charts
- Interactive: Pan, zoom, hover, select, and more
- High-performance: Can handle large, dynamic datasets
- Publication-ready: Outputs attractive, polished graphics
- Extensible: Plays well with other libraries and tools
While Matplotlib is the go-to general plotting library, Bokeh shines for interactive visualizations, especially in data applications and dashboards. It utilizes JavaScript but can be used entirely in Python thanks to bindings with JS libraries.
Getting Started with Bokeh
Installation
Install Bokeh with pip:
pip install bokeh
Or using conda:
conda install bokeh
Imports
You‘ll typically need these imports:
from bokeh.plotting import figure, show
from bokeh.io import output_notebook, output_file
from bokeh.models import ColumnDataSource, HoverTool
figure creates the plot, show displays it. output_notebook outputs inline in Jupyter notebooks, output_file saves to an HTML file. ColumnDataSource lets you pass in data, while HoverTool powers interactive tooltips.
Basic Syntax
Here‘s the typical workflow:
1. Prepare the data
2. Create a figure and customize
3. Add renderers for the data
4. Display the plot
For example:
# Prepare data
x = [1, 2, 3, 4, 5]
y = [6, 7, 2, 4, 5]
# Create figure
p = figure(title="Example Plot", x_axis_label=‘x‘, y_axis_label=‘y‘)
# Add circle renderer
p.circle(x, y, legend_label="Data", line_color="blue", size=8)
# Display plot
show(p)
This produces a basic circle scatter plot. The figure function creates the plot object, then we call the circle method to add the points. Finally show displays the plot.
Styling and Customizing Bokeh Charts
One of Bokeh‘s strengths is the level of customization it offers. Nearly every property of a chart can be modified to your liking. Here are some common style attributes:
plot_width,plot_height: figure dimensionstitle: the plot titlex_axis_label,y_axis_label: axis labelsx_range,y_range: axis rangesbackground_fill_color: chart background colorborder_fill_color: chart border colortoolbar_location: location of toolbar
You can also style individual renderers when adding them, for instance:
p.circle(x, y, legend_label="Data", line_color="blue", fill_color="white", size=8, alpha=0.5)
This sets the edge color, fill color, size, and opacity of the circles. Each renderer has relevant properties you can tweak.
To customize further, you can modify the attributes of the axis objects:
p.xaxis.axis_label_text_font_size = "16pt"
p.yaxis.major_label_orientation = "vertical"
This changes the x-axis label size and rotates the y-axis labels. Bokeh also has a theming system to style related groups of properties.
Example Use Case: Analyzing Flight Delays
To demonstrate using Bokeh, let‘s walk through visualizing a real-world dataset. We‘ll use flight delay data from the U.S. Department of Transportation to examine airline performance.
First, load the data into a Pandas DataFrame:
import pandas as pd
flights = pd.read_csv(‘flights.csv‘)
flights.head()
The DataFrame contains fields like date, airline, origin airport, destination, departure delay in minutes, and more.
Let‘s start by comparing the average delay by airline with a bar chart:
from bokeh.models import FactorRange
# Compute average delay per airline
avg_delay_by_airline = flights.groupby(‘AIRLINE‘)[‘DEPARTURE_DELAY‘].mean()
airlines = list(avg_delay_by_airline.index)
delays = list(avg_delay_by_airline.values)
# Create figure
p = figure(x_range=airlines, plot_height=250, title="Average Departure Delay by Airline",
toolbar_location=None, tools="")
# Add renderers
p.vbar(x=airlines, top=delays, width=0.9)
p.y_range.start = 0
p.xgrid.grid_line_color = None
# Display plot
show(p)
This computes the mean delay grouped by airline, then creates a vertical bar chart comparing the values. We customize the height, title, and toolbar. The categorical airline names are supplied to x_range, while delay values are passed to the top parameter of vbar.
Next, let‘s examine how delays vary by origin airport using a box plot:
from bokeh.models import ColumnDataSource
# Filter for top 10 airports by number of flights
top10_airports = flights.groupby(‘ORIGIN‘).size().nlargest(10).index
# Compute stats for boxplot
stats = flights[flights.ORIGIN.isin(top10_airports)].groupby(‘ORIGIN‘)[‘DEPARTURE_DELAY‘].describe()
# Convert to ColumnDataSource
source = ColumnDataSource(stats)
# Create figure
p = figure(x_range=top10_airports, plot_height=300, title="Departure Delay Distribution by Airport",
toolbar_location=None, tools="")
# Add box plot renderer
p.hbar(y=top10_airports, height=0.5, left=‘25%‘, right=‘75%‘, source=source,
line_color="black")
p.hbar(y=top10_airports, height=0.2, left=‘min‘, right=‘max‘, source=source,
fill_color=None, line_color="black")
# Display plot
show(p)
We filter for the 10 busiest airports, compute quartile stats on the delays, convert to a ColumnDataSource, then add box plot renderers. The thick bar spans from the 25th to 75th percentile, while the thin line goes from the minimum to maximum value.
Finally, let‘s plot the trend in delays over time with an interactive time series:
from bokeh.models import HoverTool
# Group by month and compute average delay
flights[‘DATE‘] = pd.to_datetime(flights[‘DATE‘])
monthly_avg_delay = flights.set_index(‘DATE‘).groupby(pd.Grouper(freq=‘M‘))[‘DEPARTURE_DELAY‘].mean()
dates = list(monthly_avg_delay.index)
delays = list(monthly_avg_delay.values)
# Create figure
p = figure(plot_width=800, title="Average Departure Delay by Month",
x_axis_type=‘datetime‘, y_axis_label=‘Delay (minutes)‘)
# Add line renderer with hover tool
p.line(dates, delays, line_width=2, legend_label="Trend")
p.add_tools(HoverTool(
tooltips=[
( ‘date‘, ‘@x{%F}‘ ),
( ‘delay‘, ‘$@y{%0.2f} minutes‘ ),
],
formatters={
‘@x‘ : ‘datetime‘, # use ‘datetime‘ formatter for ‘@date‘ field
‘@y‘ : ‘printf‘, # use ‘printf‘ formatter for ‘@{adj close}‘ field
# use default ‘numeral‘ formatter for other fields
},
# display a tooltip whenever the cursor is vertically in line with a glyph
mode=‘vline‘
))
show(p)
We group the flight records by month, aggregate the mean delay, then plot as a line chart. The x_axis_type is set to ‘datetime‘. A HoverTool is added to show the date and delay value when hovering over the line.
These examples demonstrate the flexibility of Bokeh for creating informative, interactive visualizations. With a bit of data manipulation and a few lines of code, you can build professional-quality charts to explore your data.
Bokeh Chart Types and Samples
Bokeh supports a variety of chart types for different use cases. Here‘s a quick reference of key types and code samples:
Scatter Plot
“`python
p = figure(title="Scatter Plot")
p.scatter(x, y, marker="circle", size=8, fill_color="blue")
“`
Line Chart
“`python
p = figure(title="Line Chart")
p.line(x, y, line_color="red", line_width=2)
“`
Bar Chart
“`python
p = figure(x_range=categories, title="Bar Chart")
p.vbar(x=categories, top=values, width=0.8)
“`
Histogram
“`python
hist, edges = np.histogram(data, bins=50)
p = figure(title="Histogram")
p.quad(top=hist, bottom=0, left=edges[:-1], right=edges[1:])
<h3>Box Plot</h3>
```python
p = figure(x_range=factors, title="Box Plot")
# Box
p.hbar(y=factors, height=0.5, left=q1, right=q3, line_color="black")
# Whiskers
p.hbar(y=factors, height=0.2, left=lower, right=upper, fill_color=None, line_color="black")
# Outliers
p.circle(x=outliers, y=outlier_factors, size=6, color="red")
Area Chart
“`python
p = figure(title="Area Chart")
p.varea(x=x, y1=y1, y2=y2, fill_color="blue", fill_alpha=0.5)
“`
Donut Chart
“`python
p = figure(title="Donut Chart", toolbar_location=None, tools="hover", tooltips="@countries: @values")
p.annular_wedge(x=0, y=0, inner_radius=0.2, outer_radius=0.4,
start_angle=cumsum(‘angle‘, include_zero=True), end_angle=cumsum(‘angle‘),
fill_color=‘color‘, legend_field=‘countries‘, source=data)
<h3>Heatmap</h3>
```python
p = figure(title="Heatmap", x_range=list(x), y_range=list(y))
p.rect(x="x", y="y", width=1, height=1, source=data,
fill_color={‘field‘: ‘value‘, ‘transform‘: color_mapper})
These samples provide templates you can adapt to your own data. See the Bokeh docs for the full set of supported chart types and options.
Arranging Multiple Plots with Layouts
Bokeh provides several layout options for arranging multiple plots together:
column: displays plots in a vertical columnrow: arranges plots horizontally in a rowgridplot: places plots in a gridlayout: Bokeh‘s general grid layout
For instance, here‘s how to display three plots stacked vertically:
from bokeh.layouts import column
plot1 = figure()
plot1.circle(x, y)
plot2 = figure()
plot2.line(x, y)
plot3 = figure()
plot3.vbar(x=categories, top=values)
layout = column(plot1, plot2, plot3)
show(layout)
Layouts let you group related plots to tell a story and build dashboards.
Bokeh Best Practices and Tips
Here are some tips for getting the most out of Bokeh:
- Tidy your data first with Pandas, especially for aggregation and reshaping
- Stick to default styles until you need to customize
- Adapt examples from the Bokeh gallery and docs
- Utilize
ColumnDataSourcefor easy data updates and optimal performance - Add interactivity with tools like
HoverToolandTapTool - Format tooltips for both legibility and precision
- Avoid overloading charts with too many elements
- Pick palette colors for readability and to convey information
- Collect styling options in dicts for reuse
- Lay out dashboards with a grid structure
- Test charts on realistic and edge case data
- Enable Bokeh‘s optimizations for large datasets
Conclusion
We‘ve taken a comprehensive tour of interactive data visualization in Python with Bokeh. You should now feel comfortable customizing plots, building dashboards, and using Bokeh to explore real-world data.
Bokeh is a powerful tool to have in your data science toolkit. Its flexibility and controls let you craft compelling graphics for data applications, dashboards, and notebooks. Leveraging interactivity draws your audience into the data. And the ability to glue everything together in pure Python keeps your workflow streamlined.
The best way to grow your Bokeh skills is diving into your own datasets. Start with basic chart types, layer in interactivity, and compose more complex dashboards. In no time you‘ll be creating professional data visualizations ready for sharing insights with the world.