Skip to content

Matplotlib Geospatial Intelligence: Create Interactive Maps, Heatmaps & Spatial Analytics

Updated: at 01:32 AM

Geospatial intelligence (GEOINT) relies on analyzing and visualizing location-based data to gain insights and support decision making. As a popular Python visualization library, Matplotlib is a powerful tool for creating informative maps and geo-visualizations for GEOINT applications. This guide will demonstrate key Matplotlib capabilities for working with geospatial data, including creating choropleth maps, overlaying vector layers, generating heatmaps, and enabling interactive visual analytics.

Overview of Matplotlib for Geospatial Data Visualization

Matplotlib’s Pyplot interface provides a MATLAB-style API for building visualizations in Python. For working with geospatial data, Matplotlib integrates well with packages like Geopandas, Descartes, and Cartopy to create both static and interactive map visualizations.

Some key features of Matplotlib for geospatial intelligence include:

When paired with NumPy, SciPy, and other Python scientific computing stacks, Matplotlib enables automated generation of production-ready maps and charts for geospatial applications.

Setting Up Matplotlib for Mapping

To start using Matplotlib for mapping, install Matplotlib along with Cartopy, Geopandas, Descarte, and other geospatial packages:

import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy.feature as cfeature
import geopandas as gpd
from descartes import PolygonPatch

Now we can import shapefiles and begin visualizing geospatial vector data:

world = gpd.read_file(gpd.datasets.get_path('naturalearth_lowres'))

By default, Matplotlib will plot geometries in a simplePlateCarree projection. We can define projections centered on specific regions using Cartopy:

projection = ccrs.PlateCarree()
ax = plt.axes(projection=projection)
ax.set_extent([140, 150, -10, -50], crs=ccrs.Geodetic())

Adding coastlines, borders, and other map elements is done via Cartopy features:

ax.add_feature(cfeature.LAND)
ax.add_feature(cfeature.OCEAN)
ax.add_feature(cfeature.COASTLINE)
ax.add_feature(cfeature.BORDERS, edgecolor='black')

Now we can visualize vector geometries from Geopandas:

world.plot(ax=ax, color='white', edgecolor='black')

This provides a basic configurable map projection to plot points, lines, and polygons with Matplotlib!

Creating Choropleth Maps

A common mapping technique is a choropleth map, which shades regions based on data variable values. This provides a visualization of patterns across locations.

First, we need geospatial region shapes and associated dataset. Geopandas provides USA state shapefiles:

states = gpd.read_file(gpd.datasets.get_path('usa_states'))

We will join state population data (saved as CSV called ‘population.csv’):

pop = pd.read_csv("population.csv")
merged = states.merge(pop, on='state')

Now we can create a choropleth map, with states shaded based on population:

vmin, vmax = 0, merged['population'].max()
fig, ax = plt.subplots(1, figsize=(10, 5))

merged.plot(column='population', cmap='Reds', linewidth=0.8, ax=ax, edgecolor='0.8', vmin=vmin, vmax=vmax)

ax.set_title("US State Population")
fig.colorbar(ax.get_children()[0], shrink=0.7)

This shades states with higher populations in darker red. We can customize the color palette, legend, and styles as needed. Choropleth maps are an effective way to visualize geo-patterns in data.

Plotting Points, Lines, and Polygons

Matplotlib can overlay various geometries, including points, lines, and polygons:

fig, ax = plt.subplots(figsize=(8, 8))

# Points
df = pd.DataFrame(np.random.randn(1000, 2), columns=['x', 'y'])
ax.scatter(df['x'], df['y'], c='red', alpha=0.3)

# Lines
from matplotlib.lines import Line2D
line = Line2D([0, 1], [0, 1], transform=ax.transAxes, color='green')
ax.add_line(line)

# Polygon
poly = PolygonPatch([[-1,-1], [1,-1], [1,1], [-1,1]], closed=True,
                    alpha=0.5, facecolor='blue')
ax.add_patch(poly)

ax.set(xlim=(-2, 2), ylim=(-2, 2))

This provides an overlay of all three geometry types on a single map. We can configure colors, transparency, sizes, and other stylistic properties as needed.

Plotting Spatial Dataframes

Geopandas extends Matplotlib for mapping geospatial data. Given a GeoDataFrame called gdf:

gdf.plot(column='pop_density', cmap='OrRd', figsize=(10, 6),
        edgecolor='grey', legend=True)

This plots the GeoDataFrame, shading regions by the ‘pop_density’ attribute. GeoPandas handles the geographic projection, coordinate system transforms, geometry patching, attribute joins, and choropleth legend generation automatically.

Annotating Maps

We can label geometries and add custom text annotations:

gdf.plot(color='white', edgecolor='black')

for idx, row in gdf.iterrows():
    plt.annotate(s=row['City'], xy=row['Coordinates'],
                horizontalalignment='center')

plt.scatter(x, y, s=200, marker='v', color='red')
plt.text(x, y, 'Capital City')

This plots city labels based on a GeoDataFrame attribute, and adds a custom annotation for the capital. Annotations help provide context and highlights for map readers.

Creating Heatmaps

Heatmaps visualize the density or magnitude of events, helping identify “hot spots” and clusters. This is useful for crime maps, disease outbreaks, earthquake epicenters, and more.

We’ll demonstrate a heatmap of earthquake occurrences in the Pacific Northwest:

data = pd.read_csv('earthquakes.csv')

fig, ax = plt.subplots(figsize=(8,6))
ax.set_extent([-125, -114, 24, 49], crs=ccrs.PlateCarree())

ax.scatter(data['longitude'], data['latitude'],
           c=data['magnitude'], s=data['magnitude']*3,
           cmap='plasma', transform=ccrs.PlateCarree())

The color and size of points indicates the earthquake magnitude. This reveals clustering patterns and “hot spots” for seismic activity.

We can also generate raster heatmaps using Kernel Density Estimation (KDE) from Scikit-Learn:

from sklearn.neighbors import KernelDensity

kde = KernelDensity(bandwidth=0.1, kernel='gaussian')
kde.fit(data[['longitude', 'latitude']])

xgrid = np.arange(data.longitude.min(), data.longitude.max(), 0.1)
ygrid = np.arange(data.latitude.min(), data.latitude.max(), 0.1)
grid = np.meshgrid(xgrid, ygrid)

density = np.reshape(kde.score_samples(np.c_[grid[0].ravel(), grid[1].ravel()]), grid[0].shape)

fig, ax = plt.subplots(figsize=(8, 6))
ax.imshow(density.T, origin='lower', extent=[xgrid.min(), xgrid.max(), ygrid.min(), ygrid.max()])

This uses KDE to estimate the density across the region, then plots it as a pixel heatmap. This is an effective way to visualize hotspots and clusters.

Building Interactive Maps

Matplotlib powers several Python interactive visualization libraries like Plotly Express, Bokeh, Datashader, and HoloViews. These let us pan, zoom, hover, and apply other dynamic functionality to maps.

As an example, we can make an interactive heatmap using Plotly Express:

import plotly.express as px

fig = px.density_heatmap(data, x='longitude', y='latitude')
fig.update_layout(margin=dict(t=0, b=0, l=0, r=0))
fig.show()

This generates a web-based zoomable heatmap. Hovering shows the density values, and toolbar buttons enable panning and zooming.

Other common interactive features include:

This interactivity makes it easy to explore data and derive insights from geospatial visualizations.

Exporting Maps and Visualizations

For reports, dashboards, and publications, we often need to export static map images and animations.

Matplotlib can generate high-resolution PNGs, SVGs, PDFs, and other image formats:

plt.savefig('map.png', dpi=300)

Adjusting the DPI and figure size controls the output resolution.

For animations, Matplotib supports converting a sequence of plot images into animated GIFs:

from matplotlib.animation import FuncAnimation

fig, ax = plt.subplots()
def update(frame):
   ax.cla()
   # Draw frame
   ...

ani = FuncAnimation(fig, update, frames=len(time_steps), interval=200)

ani.save('animation.gif', dpi=80, writer='pillow')

This saves an animated map as a shareable GIF!

Advanced Spatial Analysis and Visualization

Matplotlib connects to larger Python geospatial ecosystems like GeoPandas, Pandas, Shapely, Fiona, PyProj, and Rasterio.

These additional packages enable more advanced spatial analysis and visualization capabilities:

By leveraging these additional tools, Matplotlib can power more sophisticated geospatial intelligence use cases like tracking assets, optimizing logistics, responding to emergencies, and analyzing demographic patterns.

Here are the three additional sections incorporated into the previous guide:

Real-World Case Study: Visualizing Urban Growth Patterns

To demonstrate a real-world application of these techniques, let’s examine a case study visualizing urban growth over time. Historical urban area boundary data can reveal geospatial patterns in how cities expand.

Using urban growth rasters from the European Environment Agency, we can animate expansion in Southern England between 1960 to 2010:

raster_paths = ['urban_1960.tif', 'urban_1970.tif', ..., 'urban_2010.tif']

fig, ax = plt.subplots()
def update(i):
   ax.cla()
   raster = rasterio.open(raster_paths[i])
   show(raster, ax=ax)
   ax.set_title(f"Year {1960 + i*10}")

ani = animation.FuncAnimation(fig, update, frames=len(raster_paths))
ani.save('urban_growth.gif')

This animated map clearly highlights the spread of urban areas over time near London. Geospatial analysis of urban growth helps planners model future expansion patterns and demands.

Comparison to Other Python Geospatial Libraries

Matplotlib provides a full-featured mapping solution, but alternatives like Bokeh, HoloViews, and PyPlot offer different capabilities:

In benchmark tests, Matplotlib generates basic static maps faster than Bokeh and HoloViews, but falls behind on large/streaming data volumes. PyPlot outperforms Matplotlib for 3D visualizations.

For maximum flexibility, using Matplotlib alongside libraries like GeoPandas and Plotly Express combines strengths in geospatial data wrangling and interactivity.

Best Practices for Geospatial Project Structure

For consistent and maintainable geospatial code, some best practices include:

Following geospatial-specific project guidelines helps produce clear, robust code as an analysis scales up.

Conclusion

This guide demonstrated how Matplotlib enables flexible and intuitive generation of maps, heatmaps, and interactive geo-visualizations in Python. Using vector layers, choropleths, annotations, and other mapping components, Matplotlib facilitates exploration and presentation of geospatial data for business intelligence and research applications.

By building on Matplotlib’s foundations with packages like Geopandas and Cartopy, Python provides a scalable platform for geospatial analytics and visualization. The Python data science ecosystem continues to evolve powerful tools for working with location-based data. Leveraging languages like Python for mapping helps unlock the full potential of geospatial intelligence to create actionable insights.