Let's try to build a chloropleth map using Bokeh, inspired by this example. Let's get our imports going:
from bokeh.sampledata import us_states, us_counties, unemployment
from bokeh.plotting import figure, show, output_file, output_notebook
It should be noted we're only importing three things from bokeh.plotting: figure, show and output_file.
help(figure)
Help on function figure in module bokeh.plotting: figure(**kwargs) Create a new :class:`~bokeh.plotting.Figure` for plotting, and add it to the current document. Returns: Figure
help(show)
Help on function show in module bokeh.io: show(obj, browser=None, new='tab') Immediately display a plot object. In an IPython/Jupyter notebook, the output is displayed in an output cell. Otherwise, a browser window or tab is autoraised to display the plot object. If both a server session and notebook output have been configured on the default output state then the notebook output will be generated to load the plot from that server session. Args: obj (Widget/Plot object) : a plot object to display browser (str, optional) : browser to show with (default: None) For systems that support it, the **browser** argument allows specifying which browser to display in, e.g. "safari", "firefox", "opera", "windows-default" (see the ``webbrowser`` module documentation in the standard lib for more details). new (str, optional) : new file output mode (default: "tab") For file-based output, opens or raises the browser window showing the current output file. If **new** is 'tab', then opens a new tab. If **new** is 'window', then opens a new window. Returns: None .. note:: The ``browser`` and ``new`` parameters are ignored when showing in an IPython/Jupyter notebook.
help(output_file)
Help on function output_file in module bokeh.io: output_file(filename, title='Bokeh Plot', autosave=False, mode='inline', root_dir=None) Configure the default output state to generate output saved to a file when :func:`show` is called. Args: filename (str) : a filename for saving the HTML document title (str, optional) : a title for the HTML document (default: "Bokeh Plot") autosave (bool, optional) : whether to automatically save (default: False) If True, then Bokeh plotting APIs may opt to automatically save the file more frequently (e.g., after any plotting command). If False, then the file is only saved upon calling :func:`show` or :func:`save`. mode (str, optional) : how to include BokehJS (default: ``'inline'``) One of: ``'inline'``, ``'cdn'``, ``'relative(-dev)'`` or ``'absolute(-dev)'``. See :class:`bokeh.resources.Resources` for more details. root_dir (str, optional) : root directory to use for 'absolute' resources. (default: None) This value is ignored for other resource types, e.g. ``INLINE`` or ``CDN``. Returns: None .. note:: Generally, this should be called at the beginning of an interactive session or the top of a script. .. warning:: This output file will be overwritten on every save, e.g., each time show() or save() is invoked, or any time a Bokeh plotting API causes a save, if ``autosave`` is True.
We can now go through the example steps: first, let's load the data.
us_states = us_states.data.copy()
us_counties = us_counties.data.copy()
unemployment = unemployment.data
type(us_states)
dict
type(us_counties)
dict
type(unemployment)
dict
We now delete Alaska and Hawai from the data and load the coordinates for each state in separate variables.
del us_states["HI"]
del us_states["AK"]
state_xs = [us_states[code]["lons"] for code in us_states]
state_ys = [us_states[code]["lats"] for code in us_states]
county_xs=[us_counties[code]["lons"] for code in us_counties if us_counties[code]["state"] not in ["ak", "hi", "pr", "gu", "vi", "mp", "as"]]
county_ys=[us_counties[code]["lats"] for code in us_counties if us_counties[code]["state"] not in ["ak", "hi", "pr", "gu", "vi", "mp", "as"]]
To have a better look at what we're manipulating, we can just plot the coordinates using matplotlib.
import matplotlib.pyplot as plt
%matplotlib inline
plt.plot(county_xs[0], county_ys[0])
[<matplotlib.lines.Line2D at 0xc086b38>]
We now go over the data for each county and assign it a color, depending on the numerical value of the unemployment.
colors = ["#F1EEF6", "#D4B9DA", "#C994C7", "#DF65B0", "#DD1C77", "#980043"]
county_colors = []
for county_id in us_counties:
if us_counties[county_id]["state"] in ["ak", "hi", "pr", "gu", "vi", "mp", "as"]:
continue
try:
rate = unemployment[county_id]
idx = min(int(rate/2), 5)
county_colors.append(colors[idx])
except KeyError:
county_colors.append("black")
Finally, a figure is created and patches are added to the map. Filled patches are used, as well as simpler patches that only map the contour of the states.
p = figure(title="US Unemployment 2009", toolbar_location="left",
plot_width=1100, plot_height=700)
p.patches(county_xs, county_ys, fill_color=county_colors, fill_alpha=0.7,
line_color="white", line_width=0.5)
p.patches(state_xs, state_ys, fill_alpha=0.0,
line_color="#884444", line_width=2)
show(p)