This page was generated from gallery/cartopy_convert.ipynb.
Interactive online version: Binder badge

Plotting with CartoPy and GeoPandas#

Converting between GeoPandas and CartoPy for visualizing data.

CartoPy is a Python library that specializes in creating geospatial visualizations. It has a slightly different way of representing Coordinate Reference Systems (CRS) as well as constructing plots. This example steps through a round-trip transfer of data between GeoPandas and CartoPy.

First we’ll load in the data using GeoPandas.

import matplotlib.pyplot as plt
import geopandas
from cartopy import crs as ccrs
from geodatasets import get_path

path = get_path("")
df = geopandas.read_file(path)
ERROR 1: PROJ: proj_create_from_database: Open of /home/docs/checkouts/ failed

First we’ll visualize the map using GeoPandas

<Axes: >

Plotting with CartoPy#

Cartopy also handles Shapely objects well, but it uses a different system for CRS. To plot this data with CartoPy, we’ll first need to project it into a new CRS. We’ll use a CRS defined within CartoPy and use the GeoPandas to_crs method to make the transformation.

# Define the CartoPy CRS object.
crs = ccrs.AzimuthalEquidistant()

# This can be converted into a `proj4` string/dict compatible with GeoPandas
crs_proj4 = crs.proj4_init
df_ae = df.to_crs(crs_proj4)

# Here's what the plot looks like in GeoPandas
<Axes: >

Now that our data is in a CRS based off of CartoPy, we can easily plot it.

fig, ax = plt.subplots(subplot_kw={"projection": crs})
ax.add_geometries(df_ae["geometry"], crs=crs)
<cartopy.mpl.feature_artist.FeatureArtist at 0x7f19d022c550>

Note that we could have easily done this with an EPSG code like so:

crs_epsg = ccrs.epsg("3857")
df_epsg = df.to_crs(epsg="3857")

# Generate a figure with two axes, one for CartoPy, one for GeoPandas
fig, axs = plt.subplots(1, 2, subplot_kw={"projection": crs_epsg}, figsize=(10, 5))
# Make the CartoPy plot
    df_epsg["geometry"], crs=crs_epsg, facecolor="white", edgecolor="black"
# Make the GeoPandas plot
df_epsg.plot(ax=axs[1], color="white", edgecolor="black")
<GeoAxes: >

CartoPy to GeoPandas#

Next we’ll perform a CRS projection in CartoPy, and then convert it back into a GeoPandas object.

crs_new = ccrs.AlbersEqualArea()
new_geometries = [
    crs_new.project_geometry(ii, src_crs=crs) for ii in df_ae["geometry"].values

fig, ax = plt.subplots(subplot_kw={"projection": crs_new})
ax.add_geometries(new_geometries, crs=crs_new)
<cartopy.mpl.feature_artist.FeatureArtist at 0x7f19d039e2d0>

Now that we’ve created new Shapely objects with the CartoPy CRS, we can use this to create a GeoDataFrame.

df_aea = geopandas.GeoDataFrame(
    df.drop(columns="geometry"), geometry=new_geometries, crs=crs_new.proj4_init
<Axes: >

We can even combine these into the same figure. Here we’ll plot the shapes of the countries with CartoPy. We’ll then calculate the centroid of each with GeoPandas and plot it on top.

# Generate a CartoPy figure and add the countries to it
fig, ax = plt.subplots(subplot_kw={"projection": crs_new})
ax.add_geometries(new_geometries, crs=crs_new)

# Calculate centroids and plot
df_aea_centroids = df_aea.geometry.centroid
# Need to provide "zorder" to ensure the points are plotted above the polygons
df_aea_centroids.plot(ax=ax, markersize=5, color="r", zorder=10)