Mapping geo data¶
Bokeh supports creating map-based visualizations and working with geographical data.
Tile provider maps¶
Bokeh is compatible with several XYZ tile services that use the Web Mercator projection.
The module bokeh.tile_providers contains several pre-configured tile sources with appropriate attribution.
To add these to a plot, use the 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 that passing x_axis_type="mercator"
and y_axis_type="mercator"
to figure
generates axes with latitude and longitude labels, instead of raw Web
Mercator coordinates.
Alternatively, you can use any xyzservices.TileProvider
, either pre-defined in
xyzservices
or a custom one.
import xyzservices.providers as xyz
from bokeh.plotting import figure, show
from bokeh.tile_providers import get_provider
tile_provider = get_provider(xyz.OpenStreetMap.Mapnik)
# 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)
Google Maps¶
To plot glyphs over a Google Map, use the function gmap()
.
For the function to work, you must pass it a Google API Key and configure the Google Map underlay GMapOptions
.
The Google API Key will be stored in the Bokeh Document JSON.
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
Any use of Bokeh with Google Maps must be within Google’s Terms of Service.
Google Maps exerts 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
and adding one 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:
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
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.