Search code examples
pythonbokeharcgisarcpy

Using Bokeh or ArcPy for labeling maps


I use Bokeh to make choropleth maps and to create other geographical graphics because Python spits it out a million times faster than I could ever create it in another way.

Right now I am doing something like:

from bokeh.io import show, output_file, export_png, output_notebook, output_file, save
from bokeh.models import ColumnDataSource, HoverTool, LabelSet
from bokeh.plotting import figure
from bokeh.sampledata.us_counties import data as counties
import pandas as pd

desired_counties=['Franklin County, Ohio','Fairfield County, Ohio']
counties2 = {code: county for code, county in counties.items() if county["detailed name"] in desired_counties}

unemploymentRate = {'Location': desired_counties, 'rate': [100, 100]} #placeholders
df = pd.DataFrame(data=unemploymentRate)

county_xs = [county["lons"] for county in counties2.values()]
county_ys = [county["lats"] for county in counties2.values()]
county_names = [county['name'] for county in counties2.values()]
unemployment = [df.loc[index,'rate'] for county in counties2.values() for index, row in df.iterrows() if df.loc[index,'Location']==county['detailed name']]

source = ColumnDataSource(data=dict(x=county_xs,y=county_ys,name=county_names,rate=unemployment))

TOOLS="hover,save"
p = figure(x_axis_location=None, y_axis_location=None, plot_width=350,plot_height=250,tools=TOOLS)
p.grid.grid_line_color = None
p.outline_line_color = None
p.patches('x', 'y', source=source,
          fill_color='#007a33',
          fill_alpha=1, line_color="black", line_width=3.5)
hover = p.select_one(HoverTool)
hover.point_policy = "follow_mouse"
hover.tooltips = [
    ("Name", "@name"),
    ("Rate","@rate{0.0}%")
]
labels = LabelSet(x='x', y='y', text='name', level='glyph',
          x_offset=0, y_offset=0, source=source, render_mode='css')
p.add_layout(labels)
p.toolbar.logo = None
p.toolbar_location = None
show(p)

Which gives: Image of Franklin and Fairfield counties in Ohio

When I hover over the image I see the data I want, but what I would rather have is the data annotated on the image instead for a print possibility. Using the LabelSet class that Bokeh has in their documentation seems perfect, except it's geared toward xy plots and so when trying to use it here it just stacks the labels in the corner.

Questions:

  1. Does anyone know how to label on a Bokeh choropleth without using outside graphics software?
  2. I have ArcGIS Pro, which can obviously create this type of map, but I am looking for something that does it using programming. I use Bokeh right now because I can basically tell it a central county I want, and I have code written that makes me a map of the state highlighting the county I want and its surrounding counties, creates an inset map of the county/surrounding counties, and gives hover data on the inset map of the unemployment rate in those counties (the picture/code above is a simplified version of that). Is there a way to go about this using AcrPy/ArcGIS instead?

Solution

  • The reason your labels are misplaced is because you tell them to use fields 'x' and 'y' from the data source, but the data source does not have these columns. You could compute the "center" of each shape, and add those as the x and y columns to source, then things would display as you want.