Python library for easily and quickly creating maps from a shapefile and external data.
One common GIS use case is joining tabular data to a shapefile through a spatial key, then visualizing it on a map. Libraries such as Geopandas make this task relatively simple to do, however they do not offer much styling flexibility and can take a long time (several minutes) to plot larger shapefiles. When you are programmatically creating many maps, this latency can add up quickly, and slow down the entire research process. Additionally, when you are creating maps for use in research papers, having finer control over the map's styling is important.
This library aims to fix these problem by 1.) providing methods that transparently cache the results of intermediate mapping steps to dramatically speed up mapping time, and 2.) providing high level methods that make it easy to quickly perform common mapping tasks.
All of the following examples use the US counties shapefile in
examples/cb_2015_us_county_500k_clipped/. This file has been clipped to only include shapes from the continental US. The original data is in
examples/cb_2015_us_county_500k and is from the US Census Bureau's "Cartographic Boundary Shapefiles" and can be downloaded here: http://www2.census.gov/geo/tiger/GENZ2015/shp/cb_2015_us_county_500k.zip
Higher resolution US county shapefiles can be found here: https://www.census.gov/geo/maps-data/data/cbf/cbf_counties.html
BasemapUtils.py file includes
BasemapWrapper() which serves as a drop-in replacement for the
Basemap object constructor (from the Basemap library).
BasemapWrapper caches instantiated
Basemap objects to file based on the parameters passed to the constructor.
If a previously created
Basemap object exists in the cache, then it is loaded from file using
cPickle, instead of re-instantiated, which results in a dramatic speed up in the
This file also includes
PolygonPatchesWrapper() which performs a similar function to
BasemapWrapper for lists of
matplotlib.shape.Polygon objects loaded from a shapefile. The process of loading all the shapes from a large shapefile and converting all of their coordinates to Basemap figure coordinates (i.e. transformed with the
Basemap object) is time consuming. Given a
Basemap object, its parameters, and a shapefile, the
PolygonPatchesWrapper object will transparently cache exactly this result. This method can be used as a second step in generating custom maps.
BasemapUtils.py includes serveral accessory functions that make working with spatial libraries easier:
getBounds- Returns the lat/lon bounding box from a shapefile filename.
getShapefileColumnHeaders- Returns a list of headers from a shapefile filename.
getShapefileColumn- Extracts a column from a shapefile by name. This makes it visualize data in a shapefile.
demoBasemapWrapper.py. This script will take longer to run the first time, as the full resolution
Basemap object is cached to disk. It will run quickly in subsequent executions as reading the cached object from disk is much faster than recalculating it.
(example benchmark times on my machine show an intial runtime of 203 seconds, with subsequent runs taking 8 seconds)
demoPolygonPatchesWrapper.py. This script demonstrates how the
PolygonPatchesWrapper method can be used to map data (random numbers).
Extracting and mapping data from a shapefile example
demoExtractingData.py. This script demonstrates how the
getShapefileColumn methods can be used to create an actual map.
To simplify the above steps, we wrap the BasemapWrapper and PolygonPatchesWrapper functionality, along with custom colobar routines into the
SimpleFigures.simpleMap() method to make it easy to generate maps from spatial data.
demoBasemapWrapper.py. The following maps demonstrate different arguments to
Custom colorbar range
Log colorbar with custom range
demoBinnedFigures.py. The following maps use the
Binned map with Natural Breaks
Binned map with Percentile Breaks
demoDifferenceFigures.py. The following maps use the
This map uses the 2013 and 2014 American Community Survey 5 year population estimates extracted from the TIGER geodatabases: see https://www.census.gov/geo/maps-data/data/tiger-data.html.
We map the log of the 2014 population minus the 2013 population, and start the colorbars at $100$ to filter out smaller changes.