How to plot a polygon on an interactive map using Bokeh in Python ?


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:

How to plot a polygon on an interactive map using Bokeh in Python ?
How to plot a polygon on an interactive map using Bokeh in Python ?

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)

How to plot a polygon on an interactive map using Bokeh in Python ?
How to plot a polygon on an interactive map using Bokeh in Python ?

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
Image

of