8  Making maps with Python

8.1 Introduction

  • Geopandas explore has been used in previous chapters.
  • When to focus on visualisation? At the end of geographic data processing workflows.
import matplotlib as mpl
import matplotlib.pyplot as plt
import geopandas as gpd
import rasterio
import rasterio.plot
nz = gpd.read_file("data/nz.gpkg")

8.2 Static maps

  • Focus on matlibplot
  • First example: NZ with fill and borders
  • Scary matplotlib code here…
nz.plot(color="none", edgecolor="blue");
nz.plot(color="grey", edgecolor="blue");

As covered in Chapter 2, you can plot raster datasets as follows:

nz_elev = rasterio.open('data/nz_elev.tif')

You can combine the raster and vector plotting methods shown above into a single visualisation with multiple layers as follows:

fig, ax = plt.subplots(figsize=(5, 5))
rasterio.plot.show(nz_elev, ax=ax)
nz.to_crs(nz_elev.crs).plot(ax=ax, facecolor='none', edgecolor='r');

8.2.1 Palettes

8.2.2 Layers

8.2.3 Faceted maps

8.2.4 Exporting maps as images

8.3 Interactive maps

  • When are interactive maps useful

An interactive map is an important way to understand and interpret complex geographical information. A good interactive map enables movement across the map area, change the area of interest and provide additional context or text information. In this section we will look an interactive map based of national public transport access nodes (NaPTAN), the UK Department for Transport repository of public transport point-of-interest in England, Scotland and Wales consisting of: - bus stops and railway stations - tram, metro and underground stops - airports and ferry terminals

We will show how to create this may restricted to railway stations, tram stops and ferry terminals in Yorkshire. This will also match data to the National Rail customer reservation code (CRS) and timing point location (TIPLOC) attributes used in the the national rail timetable.

In the first code block we define a function get_databuffer that uses the requests library to download the NaPTAN data-set in CSV format to a StringIO buffer.

import io
import requests

def get_databuffer(uri, encoding='UTF-8'):
    """Download data from URI and returns as an StringIO buffer"""
    r = requests.get(uri, timeout=10)
    return io.StringIO(str(r.content, encoding))

# NaPTAN data service
BUFFER = get_databuffer(URI)

We then read the in-memory string-buffer into a Panda data-frame, treating the buffer as if it were a CSV file. We then extract the location data into a numpy two-dimensional array.

import pandas as pd

DF1 = pd.read_csv(BUFFER, low_memory=False)
DATA = DF1[['Longitude', 'Latitude']].values

We then convert the \(transposed data-array\) into a GeoSeries and use this to create a GeoDataFrame. Which we then tidy by dropping any columns that only contain invalid (pd.NA) values.

import geopandas as gpd

POINTS = gpd.points_from_xy(*DATA.T, crs='WGS84')
NaPTAN = gpd.GeoDataFrame(data=DF1, geometry=POINTS)

NaPTAN = NaPTAN.dropna(how='all', axis=1)

The next step is to create the timing-point TIPLOC data based on the StopType and a subset of the ATCOCode columns.

# Heavy railway stations
IDX1 = NaPTAN['StopType'] == 'RLY'
NaPTAN.loc[IDX1, 'TIPLOC'] = NaPTAN['ATCOCode'].str[4:]

# Ferrys
IDX1 = NaPTAN['StopType'] == 'FER'
NaPTAN.loc[IDX1, 'TIPLOC'] = NaPTAN['ATCOCode'].str[4:]

# Metro and trams
IDX1 = NaPTAN['StopType'] == 'MET'
NaPTAN.loc[IDX1, 'TIPLOC'] = NaPTAN['ATCOCode'].str[6:]

We extract the heavy and light rail, or ferry locationsFrom the 435,298 rows in the NaPTAN data-frame.

IDX1 = NaPTAN['StopType'].isin(['RLY', 'FER', 'MET'])

Filter columns and drop points within Yorkshire.

FIELDS = ['ATCOCode', 'CommonName', 'ShortCommonName', 'LocalityName',
          'StopType', 'Status', 'TIPLOC', 'geometry']

# Clean up data-frame columns

YORKSHIRE = gpd.read_file('data/yorkshire.json').iloc[0, 0]


# Write to GeoJSON
STATIONS.to_file('stations.geojson', driver='GeoJSON')
# Write file to GeoPackage

CRS = 'EPSG:32630'
OUTPUT['geometry'] = OUTPUT['geometry'].to_crs(CRS)
OUTPUT.to_file('stations.gpkg', driver='GPKG', layer='stations')
  • Holoviews: facetted plotting
  • Panel: allows you to create applications/dashboards

8.3.1 GeoPandas explore

8.3.2 Layers

8.3.3 Publishing interactive maps

8.3.4 Linking geographic and non-geographic visualisations

8.4 Exercises