Introduction
Bokeh provides a powerful framework for creating interactive data visualizations. Through the import of geographical toolkits like GeoPandas, Bokeh enables mapping points on a canvas with a simple and effective interface.
Assuming you have the necessary packages installed (Bokeh, Pandas, and Geopandas), here's a step-by-step guide to plotting a polygon to a map using Bokeh:
In a previous article, we explored the process of adding points to a bokeh map. Now, let's delve into plotting polygons. As an example, we'll take on the challenge of plotting the Bermuda Triangle on a map.
Creating a Bokeh map
To begin, let's create a map using Bokeh. There are multiple approaches and tile options available. For this example, let's use the "OpenStreetMap Mapnik" tile:
from bokeh.plotting import figure, show, output_file
p = figure(x_range=(-10000000, -6000000), y_range=(-1000000, 6000000),
x_axis_type="mercator", y_axis_type="mercator")
p.add_tile("OpenStreetMap Mapnik")
p.grid.visible = False
show(p)
The plot above will generate the following visualization:
To accurately plot a polygon on a map, it is crucial to determine the projection system being used. In this case, our map utilizes the Mercator projection. To properly plot our polygon, we must convert the longitudes and latitudes to the appropriate coordinate system. A highly effective tool for accomplishing this task in Python is a geopandas dataframe. In the following example, we will illustrate how to store your data in a geopandas dataframe and convert the coordinate system to ultimately plot our polygon.
Defining the Bermuda Triangle
The Bermuda Triangle can be roughly defined by three points corresponding to three cities: Miami ([25.7617° N, 80.1918° W]), San Juan, Puerto Rico ([18.4671° N, 66.1185° W]), and Hamilton, Bermuda ([32.2951° N, 64.7842° W]):
data = {'Location':['Miami Florida','San-Juan Puerto-Rico','Hamilton Bermuda'],
'longitude':[-80.1918,-66.118,-64.7842],
'latitude':[25.7617,18.4671,32.2951]}
Creating a GeoPandas DataFrame
To plot a polygon on an interactive map using Bokeh in Python, we must begin by creating a GeoPandas DataFrame.
First, let's store our data in a pandas DataFrame:
import pandas as pd
df = pd.DataFrame(data)
and conver it into a GeoPandas DataFrame
import geopandas
gdf = geopandas.GeoDataFrame(
df,
geometry=geopandas.points_from_xy(df.longitude, df.latitude),
crs="EPSG:4326"
)
To determine the coordinate system CRS associated with our DataFrame, we can execute the following command:
print( gdf.crs )
The code presented here does not correspond to Mercator:
EPSG:4326
In order to convert our GeoPandas into the Mercator-projection we can do:
gdf = gdf.to_crs("epsg:3857") # Mercator-projection
At last, our dataset has transformed into the following format:
Location longitude latitude geometry
0 Miami Florida -80.1918 25.7617 POINT (-8926910.342 2969596.279)
1 San-Juan Puerto-Rico -66.1180 18.4671 POINT (-7360222.092 2092294.925)
2 Hamilton Bermuda -64.7842 32.2951 POINT (-7211744.155 3802109.728)
Extracting the coordinates in the Mercator projection
We will now extract the coordinates in the Mercator projection that correspond to the given longitudes and latitudes
gdf['longitude_x'] = gdf['geometry'].x
gdf['latitude_y'] = gdf['geometry'].y
Now, the GeoPandas DataFrame has two new columns that will be used to plot our polygon:
Location longitude latitude \
0 Miami Florida -80.1918 25.7617
1 San-Juan Puerto-Rico -66.1180 18.4671
2 Hamilton Bermuda -64.7842 32.2951
geometry longitude_x latitude_y
0 POINT (-8926910.342 2969596.279) -8.926910e+06 2.969596e+06
1 POINT (-7360222.092 2092294.925) -7.360222e+06 2.092295e+06
2 POINT (-7211744.155 3802109.728) -7.211744e+06 3.802110e+06
Plotting a polygon on a Bokeh map
To achieve this, we can store the longitudes and latitudes in a list as follows:
gdf['longitude_x'].to_list()
gdf['latitude_y'].to_list()
This will give us the following output:
[-8926910.341796037, -7360222.092269662, -7211744.155449593]
[2969596.2785174837, 2092294.9247172303, 3802109.727954972]
respectively.
We can now visualize our polygon on the map by using the patches() function:
from bokeh.plotting import figure, show, output_file
p = figure(x_range=(-10000000, -6000000), y_range=(-1000000, 6000000),
x_axis_type="mercator", y_axis_type="mercator")
p.add_tile("OpenStreetMap Mapnik")
lons = gdf['longitude_x'].to_list()
lats = gdf['latitude_y'].to_list()
p.patches([lons],
[lats],
color=["firebrick"], alpha=[0.4], line_width=4)
p.grid.visible = False
show(p)
References
Links | Site |
---|---|
tile_demo | docs.bokeh.org |
Mapping geo data | docs.bokeh.org |
MultiPolygons | docs.bokeh.org |
Plotting with basic glyphs | docs.bokeh.org |
patches() | docs.bokeh.org |