import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from bokeh.io import output_file, show
from bokeh.plotting import figure
from IPython.display import HTML

plt.rcParams['figure.figsize'] = (10, 5)

Plotting with glyphs

A simple scatter plot

In this example, you're going to make a scatter plot of female literacy vs fertility using data from the European Environmental Agency. This dataset highlights that countries with low female literacy have high birthrates. The x-axis data has been loaded for you as fertility and the y-axis data has been loaded as female_literacy.

Your job is to create a figure, assign x-axis and y-axis labels, and plot female_literacy vs fertility using the circle glyph.

After you have created the figure, in this exercise and the ones to follow, play around with it! Explore the different options available to you on the tab to the right, such as "Pan", "Box Zoom", and "Wheel Zoom". You can click on the question mark sign for more details on any of these tools.

Note: You may have to scroll down to view the lower portion of the figure.

eea = pd.read_csv('./dataset/literacy_birth_rate.csv').dropna()
fertility = eea['fertility'].astype('float').tolist()
female_literacy = eea['female literacy'].astype('float').tolist()
p = figure(x_axis_label='fertility (children per woman)', y_axis_label='female_literacy (% population)')

# Add a circle glyph to the figure p
p.circle(x=fertility, y=female_literacy)

# Call the output_file() function and specify the name of the file
output_file('./html/fert_lit.html')

show(p)
HTML(filename="./html/fert_lit.html")
<!DOCTYPE html> Bokeh Plot

A scatter plot with different shapes

By calling multiple glyph functions on the same figure object, we can overlay multiple data sets in the same figure.

In this exercise, you will plot female literacy vs fertility for two different regions, Africa and Latin America. Each set of x and y data has been loaded separately for you as fertility_africa, female_literacy_africa, fertility_latinamerica, and female_literacy_latinamerica.

Your job is to plot the Latin America data with the circle() glyph, and the Africa data with the x() glyph.

fertility_africa = eea[eea['Continent'] == 'AF']['fertility'].astype(float).tolist()
fertility_latinamerica = eea[eea['Continent'] == 'LAT']['fertility'].astype(float).tolist()

female_literacy_africa = eea[eea['Continent'] == 'AF']['female literacy'].astype(float).tolist()
female_literacy_latinamerica = eea[eea['Continent'] == 'LAT']['female literacy'].astype(float).tolist()
p = figure(x_axis_label='fertility (children per woman)', y_axis_label='female_literacy (% population)')

# Add a circle glyph to the figure p
p.circle(x=fertility_latinamerica, y=female_literacy_latinamerica)

# Add an x glyph to the figure p
p.x(x=fertility_africa, y=female_literacy_africa)

# Specify the name of the file
output_file('./html/fert_lit_separate.html')

show(p);
HTML(filename="./html/fert_lit_separate.html")
<!DOCTYPE html> Bokeh Plot

Customizing your scatter plots

The three most important arguments to customize scatter glyphs are color, size, and alpha. Bokeh accepts colors as hexadecimal strings, tuples of RGB values between 0 and 255, and any of the 147 CSS color names. Size values are supplied in screen space units with 100 meaning the size of the entire figure.

The alpha parameter controls transparency. It takes in floating point numbers between 0.0, meaning completely transparent, and 1.0, meaning completely opaque.

p = figure(x_axis_label='fertility (children per woman)', y_axis_label='female_literacy (% population)')

# Add a blue circle glyph to the figure p
p.circle(fertility_latinamerica, female_literacy_latinamerica, color='blue', alpha=0.8, size=10)

# Add a red circle glyph to the figure p
p.circle(fertility_africa, female_literacy_africa, color='red', alpha=0.8, size=10)

# Specify the name of the file
output_file('./html/fert_lit_separate_colors.html')

# Display the plot
show(p)
HTML(filename='./html/fert_lit_separate_colors.html')
<!DOCTYPE html> Bokeh Plot

Additional glyphs

  • Patches
    • Useful for showing geographic regions
    • Data given as "list of lists"

Lines

We can draw lines on Bokeh plots with the line() glyph function.

In this exercise, you'll plot the daily adjusted closing price of Apple Inc.'s stock (AAPL) from 2000 to 2013.

The data points are provided for you as lists. date is a list of datetime objects to plot on the x-axis and price is a list of prices to plot on the y-axis.

Since we are plotting dates on the x-axis, you must add x_axis_type='datetime' when creating the figure object.

aapl = pd.read_csv('./dataset/aapl.csv', index_col=0)
date = pd.to_datetime(aapl['date']).tolist()
price = aapl['price'].tolist()
p = figure(x_axis_type='datetime', x_axis_label='Date', y_axis_label='US Dollars')

# Plot date along the x axis and price along the y axis
p.line(date, price)

# Specify the name of the output file and show the result
output_file('./html/line.html')
show(p)
HTML(filename='./html/line.html')
<!DOCTYPE html> Bokeh Plot

Lines and markers

Lines and markers can be combined by plotting them separately using the same data points.

In this exercise, you'll plot a line and circle glyph for the AAPL stock prices. Further, you'll adjust the fill_color keyword argument of the circle() glyph function while leaving the line_color at the default value.

p = figure(x_axis_type='datetime', x_axis_label='Date', y_axis_label='US Dollars')

# Plot date along the x-axis and price along the y-axis
p.line(date, price)

# With date on the x-axis and price on the y-axis, add a white circle glyph of size 4
p.circle(date, price, fill_color='white', size=4)

# Specify the name of the output file and show the result
output_file('./html/line2.html')
show(p)
HTML(filename='./html/line2.html')
<!DOCTYPE html> Bokeh Plot

Patches

n Bokeh, extended geometrical shapes can be plotted by using the patches() glyph function. The patches glyph takes as input a list-of-lists collection of numeric values specifying the vertices in x and y directions of each distinct patch to plot.

In this exercise, you will plot the state borders of Arizona, Colorado, New Mexico and Utah. The latitude and longitude vertices for each state have been prepared as lists.

az = pd.read_csv('./dataset/az.csv')
co = pd.read_csv('./dataset/co.csv')
nm = pd.read_csv('./dataset/nm.csv')
ut = pd.read_csv('./dataset/ut.csv')
az_lats, az_lons = az['lats'].tolist(), az['lons'].tolist()
co_lats, co_lons = co['lats'].tolist(), co['lons'].tolist()
nm_lats, nm_lons = nm['lats'].tolist(), nm['lons'].tolist()
ut_lats, ut_lons = ut['lats'].tolist(), ut['lons'].tolist()
p = figure()
# Create a list of az_lons, co_lons, nm_lons and ut_lons: x
x = [az_lons, co_lons, nm_lons, ut_lons]

# Create a list of az_lats, co_lats, nm_lats, ut_lats: y
y = [az_lats, co_lats, nm_lats, ut_lats]

# Add patches to figure p with line_color=white for x and y
p.patches(x, y, line_color='white')

# Specify the number of the output and show the result
output_file('./html/four_corners.html')
show(p)
HTML(filename='./html/four_corners.html')
<!DOCTYPE html> Bokeh Plot

Data formats

  • Column Data Source
    • Common fundamental data structure for Bokeh
    • Maps string column names to sequences of data
    • Often created automatically for you
    • Can be shared between glyphs to link selections
    • Extra columns can be used with hover tooltips

Plotting data from NumPy arrays

In the previous exercises, you made plots using data stored in lists. You learned that Bokeh can plot both numbers and datetime objects.

In this exercise, you'll generate NumPy arrays using np.linspace() and np.cos() and plot them using the circle glyph.

np.linspace() is a function that returns an array of evenly spaced numbers over a specified interval. For example, np.linspace(0, 10, 5) returns an array of 5 evenly spaced samples calculated over the interval [0, 10]. np.cos(x)calculates the element-wise cosine of some array x.

For more information on NumPy functions, you can refer to the NumPy User Guide and NumPy Reference.

x = np.linspace(0, 5, 100)

# Create array using np.cos: y
y = np.cos(x)

# Add circles at x and y
p = figure()
p.circle(x, y)

# Specify the name of the output file and show the result
output_file('./html/numpy.html')
show(p)
HTML(filename='./html/numpy.html')
<!DOCTYPE html> Bokeh Plot

Plotting data from Pandas DataFrames

You can create Bokeh plots from Pandas DataFrames by passing column selections to the glyph functions.

Bokeh can plot floating point numbers, integers, and datetime data types. In this example, you will read a CSV file containing information on 392 automobiles manufactured in the US, Europe and Asia from 1970 to 1982.

Your job is to plot miles-per-gallon (mpg) vs horsepower (hp) by passing Pandas column selections into the p.circle() function. Additionally, each glyph will be colored according to values in the color column.

df = pd.read_csv('./dataset/auto-mpg.csv')
p = figure(x_axis_label='HP', y_axis_label='MPG')

# Plot mpg vs hp by color
p.circle(x=df['hp'], y=df['mpg'], color=df['color'], size=10)

# Specify the name of the output file and show the result
output_file('./html/auto_df.html')
show(p)
HTML(filename='./html/auto_df.html')
<!DOCTYPE html> Bokeh Plot

The Bokeh ColumnDataSource (continued)

You can create a ColumnDataSource object directly from a Pandas DataFrame by passing the DataFrame to the class initializer.

In this exercise, we have imported pandas as pd and read in a data set containing all Olympic medals awarded in the 100 meter sprint from 1896 to 2012. A color column has been added indicating the CSS colorname we wish to use in the plot for every data point.

Your job is to import the ColumnDataSource class, create a new ColumnDataSource object from the DataFrame df, and plot circle glyphs with 'Year' on the x-axis and 'Time' on the y-axis. Color each glyph by the color column.

df = pd.read_csv('./dataset/sprint.csv')
from bokeh.plotting import ColumnDataSource

# Createthe figure: p
p = figure(x_axis_label='Year', y_axis_label='Time')

# Create a ColumnDataSource from df: source
source = ColumnDataSource(df)

# Add circle glyphs to the figure p
p.circle(x='Year', y='Time', source=source, color='color', size=8)

# Specify the name of the output file and show the result
output_file('./html/sprint.html')
show(p)
HTML('./html/sprint.html')
<!DOCTYPE html> Bokeh Plot

Customizing glyphs

Selection and non-selection glyphs

In this exercise, you're going to add the box_select tool to a figure and change the selected and non-selected circle glyph properties so that selected glyphs are red and non-selected glyphs are transparent blue.

You'll use the ColumnDataSource object of the Olympic Sprint dataset you made in the last exercise. It is provided to you with the name source.

After you have created the figure, be sure to experiment with the Box Select tool you added! As in previous exercises, you may have to scroll down to view the lower portion of the figure.

Note: ColumnDataSource can handle only one dataframe in current doc. So it needs to re-assign it every time.
source = ColumnDataSource(df)

# Create a figure with the "box_select" tool: p
p = figure(x_axis_label='Year', y_axis_label='Time', tools='box_select')

# Add circle glyphs to the figure p with the selected and non-selected properties
p.circle(x='Year', y='Time', source=source, selection_color='red', nonselection_alpha=0.1)

# Specify the name of the output file and show the result
output_file('./html/selection_glyph.html')
show(p)
HTML('./html/selection_glyph.html')
<!DOCTYPE html> Bokeh Plot

Hover glyphs

Now let's practice using and customizing the hover tool.

In this exercise, you're going to plot the blood glucose levels for an unknown patient. The blood glucose levels were recorded every 5 minutes on October 7th starting at 3 minutes past midnight.

The date and time of each measurement are provided to you as x and the blood glucose levels in mg/dL are provided as y.

Your job is to add a circle glyph that will appear red when the mouse is hovered near the data points. You will also add a customized hover tool object to the plot.

When you're done, play around with the hover tool you just created! Notice how the points where your mouse hovers over turn red.

df = pd.read_csv('./dataset/glucose.csv')
x = pd.to_datetime(df['datetime'])
y = df['glucose']
from bokeh.models import HoverTool

# Create figure
p = figure(x_axis_type='datetime', x_axis_label='date', y_axis_label='glucose levels (mg/dL)')

# Add circle glyphs to figure p
p.circle(x, y, size=10,
        fill_color='grey', alpha=0.1, line_color=None,
        hover_fill_color='firebrick', hover_alpha=0.5,
        hover_line_color='white')

# Create a HoverTool: hover
hover = HoverTool(tooltips=None, mode='vline')

# Add the hover tool to the figure p
p.add_tools(hover)

# Specify the name of the output file and show the result
output_file('./html/hover_glyph.html')
show(p)
HTML('./html/hover_glyph.html')
<!DOCTYPE html> Bokeh Plot

Colormapping

The final glyph customization we'll practice is using the CategoricalColorMapper to color each glyph by a categorical property.

Here, you're going to use the automobile dataset to plot miles-per-gallon vs weight and color each circle glyph by the region where the automobile was manufactured.

The origin column will be used in the ColorMapper to color automobiles manufactured in the US as blue, Europe as red and Asia as green.

df = pd.read_csv('./dataset/auto-mpg.csv')
from bokeh.models import CategoricalColorMapper

# Create a figure: p
p = figure(x_axis_label='Weight', y_axis_label='MPG')

# Convert df to a ColumnDataSource: source
source = ColumnDataSource(df)

# Make a CategoricalColorMapper object: color_mapper
color_mapper = CategoricalColorMapper(factors=['Europe', 'Asia', 'US'],
                                     palette=['red', 'green', 'blue'])

# Add a circlr glyph to the figure p
p.circle('weight', 'mpg', source=source, color=dict(field='origin', transform=color_mapper),
        legend_field='origin')

# Specify the name of the output file and show the result
output_file('./html/colormap.html')
show(p)
HTML('./html/colormap.html')
<!DOCTYPE html> Bokeh Plot