This section of the tutorial discusses map projections. If you don't know what a projection is, or are looking to learn more about how they work in geoplot
, this page is for you!
I recommend following along with this tutorial interactively using Binder.
In [1]:
import geopandas as gpd
import geoplot as gplt
%matplotlib inline
# load the example data
contiguous_usa = gpd.read_file(gplt.datasets.get_path('contiguous_usa'))
gplt.polyplot(contiguous_usa)
Out[1]:
This map is an example of an unprojected plot: it reproduces our coordinates as if they were on a flat Cartesian plane. But remember, the Earth is not a flat surface; it's a sphere. This isn't a map of the United States that you'd seen in print anywhere because it badly distorts both of the two criteria most projections are evaluated on: shape and area.
For sufficiently small areas, the amount of distortion is very small. This map of New York City, for example, is reasonably accurate:
In [2]:
boroughs = gpd.read_file(gplt.datasets.get_path('nyc_boroughs'))
gplt.polyplot(boroughs)
Out[2]:
But there is a better way: use a projection.
A projection is a way of mapping points on the surface of the Earth into two dimensions (like a piece of paper or a computer screen). Because moving from three dimensions to two is intrinsically lossy, no projection is perfect, but some will definitely work better in certain case than others.
The most common projection used for the contiguous United States is the Albers Equal Area projection. This projection works by wrapping the Earth around a cone, one that's particularly well optimized for locations near the middle of the Northern Hemisphere (and particularly poorly for locations at the poles).
To add a projection to a map in geoplot
, pass a geoplot.crs
object to the projection
parameter on the plot. For instance, here's what we get when we try Albers
out on the contiguous United States:
In [3]:
import geoplot.crs as gcrs
gplt.polyplot(contiguous_usa, projection=gcrs.AlbersEqualArea())
Out[3]:
For a list of projections implemented in geoplot
, refer to the projections reference in the cartopy
documentation (cartopy
is the library geoplot
relies on for its projections).
In [4]:
cities = gpd.read_file(gplt.datasets.get_path('usa_cities'))
ax = gplt.polyplot(
contiguous_usa,
projection=gcrs.AlbersEqualArea()
)
gplt.pointplot(cities, ax=ax)
Out[4]:
By default, geoplot
will set the extent (the area covered by the plot) to the total_bounds of the last plot stacked onto the map.
However, suppose that even though we have data for One entire United States (plus Puerto Rico) we actually want to display just data for the contiguous United States. An easy way to get this is setting the extent
parameter using total_bounds
.
In [5]:
ax = gplt.polyplot(
contiguous_usa,
projection=gcrs.AlbersEqualArea()
)
gplt.pointplot(cities, ax=ax, extent=contiguous_usa.total_bounds)
Out[5]:
The section of the tutorial on Customizing Plots explains the extent
parameter in more detail.
In [6]:
import matplotlib.pyplot as plt
import geoplot as gplt
f, axarr = plt.subplots(1, 2, figsize=(12, 4))
gplt.polyplot(contiguous_usa, ax=axarr[0])
gplt.polyplot(contiguous_usa, ax=axarr[1])
Out[6]:
matplotlib
supports subplotting projected maps using the projection
argument to subplot_kw
.
In [7]:
proj = gcrs.AlbersEqualArea(central_longitude=-98, central_latitude=39.5)
f, axarr = plt.subplots(1, 2, figsize=(12, 4), subplot_kw={
'projection': proj
})
gplt.polyplot(contiguous_usa, projection=proj, ax=axarr[0])
gplt.polyplot(contiguous_usa, projection=proj, ax=axarr[1])
Out[7]:
The Gallery includes several demos, like the Pointplot Scale Functions demo, that use this feature to good effect.
Notice that in this code sample we specified some additional parameters for our projection. The central_longitude=-98
and central_latitude=39.5
parameters set the "center point" around which the points and shapes on the map are reprojected (in this case we use the geographic center of the contiguous United States).
When you pass a projection to a geoplot
function, geoplot
will infer these values for you. But when passing the projection directly to matplotlib
you must set them yourself.