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)
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:
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.