Bokeh has started adding support for working with Geographical data. There are a number of powerful features already available, but we still have more to add. Please tell us your use cases through Discourse or on GitHub so that we can continue to extend these features to meet your needs.
Bokeh plots can also consume XYZ tile services which use the Web Mercator projection. The module bokeh.tile_providers contains several pre-configured tile sources with appropriate attribution which can be added to a plot using the add_tile() method.
add_tile()
from bokeh.plotting import figure, output_file, show from bokeh.tile_providers import CARTODBPOSITRON, get_provider output_file("tile.html") tile_provider = get_provider(CARTODBPOSITRON) # range bounds supplied in web mercator coordinates p = figure(x_range=(-2000000, 6000000), y_range=(-1000000, 7000000), x_axis_type="mercator", y_axis_type="mercator") p.add_tile(tile_provider) show(p)
Notice also that passing x_axis_type="mercator" and y_axis_type="mercator" to figure generate axes with latitude and longitude labels, instead of raw Web Mercator coordinates.
x_axis_type="mercator"
y_axis_type="mercator"
figure
Bokeh can also plot glyphs over a Google Map using the gmap() function. You must pass a Google API Key to this function in order for it to work, as well as any GMapOptions to configure the Google Map underlay. The Google API Key will be stored in the Bokeh Document JSON.
gmap()
GMapOptions
from bokeh.io import output_file, show from bokeh.models import ColumnDataSource, GMapOptions from bokeh.plotting import gmap output_file("gmap.html") map_options = GMapOptions(lat=30.2861, lng=-97.7394, map_type="roadmap", zoom=11) # For GMaps to function, Google requires you obtain and enable an API key: # # https://developers.google.com/maps/documentation/javascript/get-api-key # # Replace the value below with your personal API key: p = gmap("GOOGLE_API_KEY", map_options, title="Austin") source = ColumnDataSource( data=dict(lat=[ 30.29, 30.20, 30.29], lon=[-97.70, -97.74, -97.78]) ) p.circle(x="lon", y="lat", size=15, fill_color="blue", fill_alpha=0.8, source=source) show(p)
Note
Google has its own Terms of Service for using the Google Maps API, and any use of Bokeh with Google Maps must be within Google’s Terms of Service
Also note that Google Maps exerts explicit control over aspect ratios at all times, which imposes some limitations on GMapPlot:
GMapPlot
Only Range1d ranges are supported. Attempting to use other range types will result in an error.
Range1d
Usage of BoxZoomTool is incompatible with GMapPlot. Adding a BoxZoomTool will have no effect.
BoxZoomTool
GeoJSON is a popular open standard for representing geographical features with JSON. It describes points, lines, and polygons (called Patches in Bokeh) as a collection of features. Each feature can also have a set of properties.
Bokeh’s GeoJSONDataSource can be used almost seamlessly in place of Bokeh’s ColumnDataSource. For example:
GeoJSONDataSource
ColumnDataSource
import json from bokeh.io import output_file, show from bokeh.models import GeoJSONDataSource from bokeh.plotting import figure from bokeh.sampledata.sample_geojson import geojson output_file("geojson.html") data = json.loads(geojson) for i in range(len(data['features'])): data['features'][i]['properties']['Color'] = ['blue', 'red'][i%2] geo_source = GeoJSONDataSource(geojson=json.dumps(data)) TOOLTIPS = [ ('Organisation', '@OrganisationName') ] p = figure(background_fill_color="lightgrey", tooltips=TOOLTIPS) p.circle(x='x', y='y', size=15, color='Color', alpha=0.7, source=geo_source) show(p)
Warning
Behind the scenes, Bokeh converts the GeoJSON coordinates into columns called x and y or xs and ys (depending on whether the features are Points, Lines, MultiLines, Polygons, or MultiPolygons). Properties with clashing names will be overridden when the GeoJSON is converted and should be avoided.