import matplotlib as mpl
import matplotlib.pyplot as plt
import geopandas as gpd
import rasterio
import rasterio.plot
= gpd.read_file("data/nz.gpkg") nz
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.
8.2 Static maps
- Focus on matlibplot
- First example: NZ with fill and borders
- Scary matplotlib code here…
="grey");
nz.plot(color="none", edgecolor="blue");
nz.plot(color="grey", edgecolor="blue"); nz.plot(color
As covered in Chapter 2, you can plot raster datasets as follows:
= rasterio.open('data/nz_elev.tif')
nz_elev ; rasterio.plot.show(nz_elev)
You can combine the raster and vector plotting methods shown above into a single visualisation with multiple layers as follows:
= plt.subplots(figsize=(5, 5))
fig, ax =ax)
rasterio.plot.show(nz_elev, ax=ax, facecolor='none', edgecolor='r'); nz.to_crs(nz_elev.crs).plot(ax
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"""
= requests.get(uri, timeout=10)
r return io.StringIO(str(r.content, encoding))
# NaPTAN data service
='https://multiple-la-generator-dot-dft-add-naptan-prod.ew.r.appspot.com/v1/access-nodes?dataFormat=csv'
URI= get_databuffer(URI) BUFFER
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
= pd.read_csv(BUFFER, low_memory=False)
DF1 = DF1[['Longitude', 'Latitude']].values DATA
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
= gpd.points_from_xy(*DATA.T, crs='WGS84')
POINTS = gpd.GeoDataFrame(data=DF1, geometry=POINTS)
NaPTAN
= NaPTAN.dropna(how='all', axis=1) NaPTAN
The next step is to create the timing-point TIPLOC
data based on the StopType
and a subset of the ATCOCode
columns.
'TIPLOC'] = ''
NaPTAN[# Heavy railway stations
= NaPTAN['StopType'] == 'RLY'
IDX1 'TIPLOC'] = NaPTAN['ATCOCode'].str[4:]
NaPTAN.loc[IDX1,
# Ferrys
= NaPTAN['StopType'] == 'FER'
IDX1 'TIPLOC'] = NaPTAN['ATCOCode'].str[4:]
NaPTAN.loc[IDX1,
# Metro and trams
= NaPTAN['StopType'] == 'MET'
IDX1 'TIPLOC'] = NaPTAN['ATCOCode'].str[6:] NaPTAN.loc[IDX1,
We extract the heavy and light rail, or ferry locationsFrom the 435,298 rows in the NaPTAN data-frame.
= NaPTAN['StopType'].isin(['RLY', 'FER', 'MET'])
IDX1 = NaPTAN[IDX1] STATIONS
Filter columns and drop points within Yorkshire.
= ['ATCOCode', 'CommonName', 'ShortCommonName', 'LocalityName',
FIELDS 'StopType', 'Status', 'TIPLOC', 'geometry']
# Clean up data-frame columns
= STATIONS[FIELDS]
STATIONS
= gpd.read_file('data/yorkshire.json').iloc[0, 0]
YORKSHIRE = STATIONS.within(YORKSHIRE)
IDX
= STATIONS[IDX]
STATIONS
# Write to GeoJSON
'stations.geojson', driver='GeoJSON')
STATIONS.to_file(# Write file to GeoPackage
= STATIONS.copy()
OUTPUT = 'EPSG:32630'
CRS 'geometry'] = OUTPUT['geometry'].to_crs(CRS)
OUTPUT['stations.gpkg', driver='GPKG', layer='stations') OUTPUT.to_file(
- Holoviews: facetted plotting
- Panel: allows you to create applications/dashboards