This example demonstrates how to plot polygons on a Folium map.
import geopandas as gpd
import geodatasets
import folium
import matplotlib.pyplot as plt
This example uses the nybb dataset, which contains polygons of New York boroughs.
path = geodatasets.get_path("nybb")
df = gpd.read_file(path)
df.head()
Plot from the original dataset
df.plot(figsize=(6, 6))
plt.show()
Notice that the values of the polygon geometries do not directly represent the values of latitude of longitude in a geographic coordinate system.
To view the coordinate reference system of the geometry column, access the crs
attribute:
df.crs
The epsg:2263 crs is a projected coordinate reference system with linear units (ft in this case). As folium (i.e. leaflet.js) by default accepts values of latitude and longitude (angular units) as input, we need to project the geometry to a geographic coordinate system first.
# Use WGS 84 (epsg:4326) as the geographic coordinate system
df = df.to_crs(epsg=4326)
print(df.crs)
df.head()
df.plot(figsize=(6, 6))
plt.show()
m = folium.Map(location=[40.70, -73.94], zoom_start=10, tiles="CartoDB positron")
m
Overlay the boundaries of boroughs on map with borough name as popup:
for _, r in df.iterrows():
# Without simplifying the representation of each borough,
# the map might not be displayed
sim_geo = gpd.GeoSeries(r["geometry"]).simplify(tolerance=0.001)
geo_j = sim_geo.to_json()
geo_j = folium.GeoJson(data=geo_j, style_function=lambda x: {"fillColor": "orange"})
folium.Popup(r["BoroName"]).add_to(geo_j)
geo_j.add_to(m)
m
In order to properly compute geometric properties, in this case centroids, of the geometries, we need to project the data to a projected coordinate system.
# Project to NAD83 projected crs
df = df.to_crs(epsg=2263)
# Access the centroid attribute of each polygon
df["centroid"] = df.centroid
Since we're again adding a new geometry to the Folium map, we need to project the geometry back to a geographic coordinate system with latitude and longitude values.
# Project to WGS84 geographic crs
# geometry (active) column
df = df.to_crs(epsg=4326)
# Centroid column
df["centroid"] = df["centroid"].to_crs(epsg=4326)
df.head()
for _, r in df.iterrows():
lat = r["centroid"].y
lon = r["centroid"].x
folium.Marker(
location=[lat, lon],
popup="length: {} <br> area: {}".format(r["Shape_Leng"], r["Shape_Area"]),
).add_to(m)
m