Static maps

Download datasets

Before we start you need to download (and then extract) the dataset zip-package used during this lesson from this link.

You should have following Shapefiles in the Data folder:

  • population_square_km.shp

  • schools_tartu.shp

  • roads.shp

population_square_km.shp.xml  schools_tartu.cpg
population_square_km.shx      schools_tartu.csv
roads.cpg                     schools_tartu.dbf
roads.dbf                     schools_tartu.prj
L6.zip                        roads.prj                     schools_tartu.sbn
roads.sbn                     schools_tartu.sbx
roads.sbx                     schools_tartu.shp             schools5.csv
population_square_km.cpg      roads.shp                     schools_tartu.shp.xml
population_square_km.dbf      roads.shp.xml                 schools_tartu.shx
population_square_km.prj      roads.shx                     schools_tartu.txt.xml
population_square_km.sbn
population_square_km.sbx
population_square_km.shp

Static maps in Geopandas

We have already seen during the previous lessons quite many examples how to create static maps using Geopandas.

Thus, we won’t spend too much time repeating making such maps but let’s create a one with more layers on it than just one which kind we have mostly done this far.

Let’s create a static accessibility map with roads and schools line on it.

First, we need to read the data.

In [1]: import geopandas as gpd

In [2]: import matplotlib.pyplot as plt

# Filepaths
In [3]: grid_fp = "source/_static/data/L6/population_square_km.shp"

In [4]: roads_fp = "source/_static/data/L6/roads.shp"

In [5]: schools_fp = "source/_static/data/L6/schools_tartu.shp"

# Read files
In [6]: grid = gpd.read_file(grid_fp)

In [7]: roads = gpd.read_file(roads_fp)

In [8]: schools = gpd.read_file(schools_fp)

Then, we need to be sure that the files are in the same coordinate system. Let’s use the crs of our travel time grid.

In [9]: gridCRS = grid.crs

In [10]: roads['geometry'] = roads['geometry'].to_crs(crs=gridCRS)

In [11]: schools['geometry'] = schools['geometry'].to_crs(crs=gridCRS)

Finally we can make a visualization using the .plot() -function in Geopandas. The .plot() function takes all the matplotlib parameters where appropriate. For example we can adjust various parameters

  • ax if used, then can indicate a joint plot axes onto which to plot, used to plot several times (several layers etc) into the same plot (using the same axes, i.e. x and y coords)

  • column which dataframe column to plot

  • linewidth if feature with an outline, or being a line feature then line width

  • markersize size of point/marker element to plot

  • color colour for the layers/feature to plot

  • cmap colormaps (*cmap* - parameter)

  • alpha transparency 0-1

  • legend True/False show the legend

  • scheme one of 3 basic classification schemes (“quantiles”, “equal_interval”, “fisher_jenks”), beyond that use PySAL explicitly

  • k number of classes for above scheme if used.

  • `` vmin`` indicate a minimal value from the data column to be considered when plotting (also affects the classification scheme), can be used to “normalise” several plots where the data values don’t aligh exactly

  • `` vmax`` indicate a maximal value from the data column to be considered when plotting (also affects the classification scheme), can be used to “normalise” several plots where the data values don’t aligh exactly

# in Jupyter Notebook don't forget to enable the inline plotting magic
import matplotlib.pyplot as plt
%matplotlib inline

Let’s check the histgram first:

# Plot
In [12]: grid.hist(column="Population", bins=100)
Out[12]: 
array([[<matplotlib.axes._subplots.AxesSubplot object at 0x00000215F13F25C0>]],
      dtype=object)

# Add title
In [13]: plt.title("Amount of population km2 Tartumaa histogram")
Out[13]: Text(0.5, 1.0, 'Amount of population km2 Tartumaa histogram')

In [14]: plt.tight_layout()
_staticimgpopulation_histogram2.png ../_images/population_histogram2.png
In [15]: fig, ax = plt.subplots(figsize=(15, 13))

# Visualize the population density into 5 classes using "Quantiles" classification scheme
# Add also a little bit of transparency with `alpha` parameter
# (ranges from 0 to 1 where 0 is fully transparent and 1 has no transparency)
In [16]: grid.plot(column="Population", ax=ax, linewidth=0.03, cmap="Reds", scheme="quantiles", k=5, alpha=0.8, legend=True)
Out[16]: <matplotlib.axes._subplots.AxesSubplot at 0x215f13eada0>

# Add roads on top of the grid
# (use ax parameter to define the map on top of which the second items are plotted)
In [17]: roads.plot(ax=ax, color="grey", linewidth=1.5)
Out[17]: <matplotlib.axes._subplots.AxesSubplot at 0x215f13eada0>

# Add schools on top of the previous map
In [18]: schools.plot(ax=ax, color="cyan", markersize=9.0)
Out[18]: <matplotlib.axes._subplots.AxesSubplot at 0x215f13eada0>

# Remove the empty white-space around the axes
In [19]: plt.title("population km2 Tartumaa in relation to schools and major roads")
Out[19]: Text(0.5, 1, 'population km2 Tartumaa in relation to schools and major roads')

In [20]: ax.set_ylabel('Northing in EPSG:3301 Estonian grid (metres)')
Out[20]: Text(190.84722222221734, 0.5, 'Northing in EPSG:3301 Estonian grid (metres)')

In [21]: ax.set_xlabel('Easting in EPSG:3301 Estonian grid (metres)')
Out[21]: Text(0.5, 113.72222222222219, 'Easting in EPSG:3301 Estonian grid (metres)')

In [22]: plt.tight_layout()
_staticimgstatic_map.png ../_images/static_map.png
outfp = "static_map.png"
plt.savefig(outfp, dpi=300)

This kind of approach can be used really effectively to produce large quantities of nice looking maps (though this example of ours isn’t that pretty yet, but it could be) which is one of the most useful aspects of coding and what makes it so important to learn how to code.

Launch in the web/MyBinder:

https://mybinder.org/badge_logo.svg