Mapping Geo Data¶
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 the Discourse or on github so that we can continue to build out these features to meet your needs.
Tile Provider Maps¶
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.
from bokeh.plotting import figure, show, output_file
from bokeh.tile_providers import get_provider, Vendors
output_file("tile.html")
tile_provider = get_provider(Vendors.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 longitute labels, instead of raw Web
Mercator coordinates.
Google Maps¶
Bokeh can also plot glyphs over a Google Map using the gmap()
function. You must pass this function Google API Key in order for it to work, as
well as any GMapOptions
to configure the Google Map
underlay.
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 Google Maps API and any use of Bokeh with Google Maps must be within Google’s Terms of Service
Also note that Google Maps exert explicit control over aspect ratios at all
times, which imposes some limitations on GMapPlot
:
Only
Range1d
ranges are supported. Attempting to use other range types will result in an error.Usage of
BoxZoomTool
is incompatible withGMapPlot
. Adding aBoxZoomTool
will have no effect.
GeoJSON Data¶
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:
from bokeh.io import output_file, show
from bokeh.models import GeoJSONDataSource
from bokeh.plotting import figure
from bokeh.sampledata.sample_geojson import geojson
import json
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
It is important to note that 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.