mirror of
https://github.com/wassname/geopandas.git
synced 2026-09-20 12:50:47 +08:00
107 lines
3.9 KiB
Python
107 lines
3.9 KiB
Python
"""
|
|
Plotting with CartoPy and GeoPandas
|
|
-----------------------------------
|
|
|
|
Converting between GeoPandas and CartoPy for visualizing data.
|
|
|
|
`CartoPy <http://scitools.org.uk/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.
|
|
"""
|
|
# sphinx_gallery_thumbnail_number = 7
|
|
import matplotlib.pyplot as plt
|
|
import geopandas
|
|
from cartopy import crs as ccrs
|
|
|
|
path = geopandas.datasets.get_path('naturalearth_lowres')
|
|
df = geopandas.read_file(path)
|
|
# Add a column we'll use later
|
|
df['gdp_pp'] = df['gdp_md_est'] / df['pop_est']
|
|
|
|
####################################################################
|
|
# First we'll visualize the map using GeoPandas
|
|
df.plot()
|
|
|
|
###############################################################################
|
|
# 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
|
|
df_ae.plot()
|
|
|
|
###############################################################################
|
|
# 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)
|
|
|
|
###############################################################################
|
|
# 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
|
|
axs[0].add_geometries(df_epsg['geometry'], crs=crs_epsg,
|
|
facecolor='white', edgecolor='black')
|
|
# Make the GeoPandas plot
|
|
df_epsg.plot(ax=axs[1], color='white', edgecolor='black')
|
|
|
|
###############################################################################
|
|
# 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)
|
|
|
|
###############################################################################
|
|
# 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['gdp_pp'], geometry=new_geometries,
|
|
crs=crs_new.proj4_init)
|
|
df_aea.plot()
|
|
|
|
###############################################################################
|
|
# 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)
|
|
|
|
plt.show()
|