Skip to content

Commit

Permalink
starts rev ch8 jn
Browse files Browse the repository at this point in the history
  • Loading branch information
Nowosad committed Oct 19, 2023
1 parent 4c4264a commit f3a57c9
Showing 1 changed file with 37 additions and 41 deletions.
78 changes: 37 additions & 41 deletions 08-mapping.qmd
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ else:
z.extractall(".")
```

Let's import the required packages:
This chapter requires importing the following packages:

```{python}
import matplotlib.pyplot as plt
Expand All @@ -39,7 +39,7 @@ pd.options.display.max_colwidth = 35
plt.rcParams['figure.figsize'] = (5, 5)
```

and load the sample data for this chapter:
It also relies on the following data files:

```{python}
nz = gpd.read_file('data/nz.gpkg')
Expand Down Expand Up @@ -76,70 +76,69 @@ Maps are also often the best way to present the findings of geocomputational res
Map making is therefore a critical part of geocomputation and its emphasis not only on describing, but also changing the world.

Basic static display of vector layers in Python is done with the `.plot` method or the `rasterio.plot.show` function, for vector layers and rasters, as we saw in Sections @sec-vector-layers and @sec-using-rasterio, respectively.
Other, more advaned uses of these methods, were also encountered in subsequent chapters, when demonstrating the various outputs we got.
Other, more advanced uses of these methods, were also encountered in subsequent chapters, when demonstrating the various outputs we got.
In this chapter, we provide a comprehensive summary of the most useful workflows of these two methods for creating static maps (@sec-static-maps).
Then, we move on to elaborate on the `.explore` method for creating interactive maps, which was also briefly introduced earlier (@sec-vector-layers).
Static maps can be easily shared and viewed (whether digitally or in print), however they can only convey as much information as a static image can.
Interactive maps provide much more flexibilty in terms of user experience and amount of information, however they often require more work to design and effectively share.
Thus, in @sec-interactive-maps, we move on to elaborate on the `.explore` method for creating interactive maps, which was also briefly introduced earlier in @sec-vector-layers.

## Static maps {#sec-static-maps}
<!-- jn: this intro can be improved/expanded -->

Static maps are the most common type of visual output from geocomputation.
When stored in a file, standard formats include `.png` and `.pdf` for raster and vector outputs, respectively.
Static maps can be easily shared and viewed (whether digitally or in print), however they can only convey as much information as a static image can.
Interactive maps (@sec-interactive-maps) provide much more flexibilty in terms of user experience and amount of information, however they often require more work to design and effectively share.
When stored in a file, standard formats include `.png` and `.pdf` for graphical raster and vector outputs, respectively.
<!-- jn: maybe it would be good to add a block here about the similarities and differences between spatial raster/vectors and graphical raster/vectors? -->

<!-- Decision of whether to use static or interactive. -->

<!-- Flow diagram? -->

Let's move on to the basics of static mapping with Python.

### Minimal example
### Minimal examples of static maps

A vector layer (`GeoDataFrame`) or a geometry column (`GeoSeries`) can be displayed using their `.plot` method (@sec-vector-layers).
A minimal example of a vector layer map is obtained using `.plot` with nothing but the defaults (@fig-vector-minimal):
A minimal example of a vector layer map is obtained using `.plot` with nothing but the defaults (@fig-vector-minimal).

```{python}
#| label: fig-vector-minimal
#| fig-cap: Minimal example of a static vector layer plot with `.plot`
nz.plot();
```

A `rasterio` raster file connection, or a numpy `ndarray`, can be displayed using `rasterio.plot.show` (@sec-using-rasterio).
Here is a minimal example of a static raster map (@fig-raster-minimal):
@fig-raster-minimal shows a minimal example of a static raster map.

```{python}
#| label: fig-raster-minimal
#| fig-cap: Minimal example of a static raster plot with `rasterio.plot.show`
rasterio.plot.show(nz_elev);
```

### Styling {#sec-static-styling}

The most useful visual properties of the geometries, that can be specified in `.plot`, include `color`, `edgecolor`, and `markersize` (for points) (@fig-basic-plot):
The most useful visual properties of the geometries, that can be specified in `.plot`, include `color`, `edgecolor`, and `markersize` (for points) (@fig-basic-plot).

```{python}
#| label: fig-basic-plot
#| fig-cap: Setting `color` and `edgecolor` in static maps of a vector layer
#| fig-subcap:
#| - Grey fill
#| - Light grey fill
#| - No fill, blue edge
#| - Grey fill, blue edge
#| - Light grey fill, blue edge
#| layout-ncol: 3
nz.plot(color='grey');
nz.plot(color='lightgrey');
nz.plot(color='none', edgecolor='blue');
nz.plot(color='grey', edgecolor='blue');
nz.plot(color='lightgrey', edgecolor='blue');
```

And here is an example of using `markersize` to get larger points (@fig-basic-plot-markersize).
This example also demonstrates how to control the overall [figure size](https://matplotlib.org/stable/gallery/subplots_axes_and_figures/figure_size_units.html), such as $4 \times 4$ $in$ in this case, using [`plt.subplots`](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.subplots.html) to initialize the plot and its `figsize` parameter to specify dimensions:
The next example uses `markersize` to get larger points (@fig-basic-plot-markersize).
It also demonstrates how to control the overall [figure size](https://matplotlib.org/stable/gallery/subplots_axes_and_figures/figure_size_units.html), such as $4 \times 4$ $in$ in this case, using [`plt.subplots`](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.subplots.html) to initialize the plot and its `figsize` parameter to specify dimensions.
<!-- jn: I think that a longer explanation is needed... What's fig? What else can be achieved with plt.subplots? What's the unit of 4x4? Etc... -->

```{python}
#| label: fig-basic-plot-markersize
#| fig-cap: Setting `markersize` in a static map of a vector layer
fig, ax = plt.subplots(figsize=(4,4))
nz_height.plot(markersize=100, ax=ax);
```
Expand All @@ -148,25 +147,25 @@ nz_height.plot(markersize=100, ax=ax);

We can set symbology in a `.plot` using the following parameters:

- `column`---A column name
- `legend`---Whether to show a legend
- `cmap`---Color map
- `column`---a column name
- `legend`---whether to show a legend
- `cmap`---color map
<!-- jn: what's color map? what does it mean? You use term color scale later... -->

For example, here we plot the `nz` polygons colored according to the `'Median_income'` attribute (@fig-plot-symbology):
For example, @fig-plot-symbology shows the `nz` polygons colored according to the `'Median_income'` attribute (column), with a legend.

```{python}
#| label: fig-plot-symbology
#| fig-cap: Symbology in a static map created with `.plot`
nz.plot(column='Median_income', legend=True);
```

The default color scale which you see in @fig-plot-symbology is `cmap='viridis'`.
The `cmap` ("color map") argument can be used to specify any of countless other color scales.
The `cmap` ("color map") argument can be used to specify one of countless color scales.
A first safe choice is often the [ColorBrewer](https://colorbrewer2.org/#type=sequential&scheme=BuGn&n=3) collection of color scales, specifically designed for mapping.
Any color scale can be reversed, using the `_r` suffic.
Finally, other color scales are available, see the **matplotlib** [colormaps article](https://matplotlib.org/stable/tutorials/colors/colormaps.html) for details.
The following code sections demonstrates three color scale specifications other than the default (@fig-plot-symbology-colors):
Any color scale can be reversed, using the `_r` suffix.
Finally, other color scales are available: see the **matplotlib** [colormaps article](https://matplotlib.org/stable/tutorials/colors/colormaps.html) for details.
The following code sections demonstrates three color scale specifications other than the default (@fig-plot-symbology-colors).

```{python}
#| label: fig-plot-symbology-colors
Expand All @@ -176,34 +175,32 @@ The following code sections demonstrates three color scale specifications other
#| - Reversed `'Reds'` color scale
#| - The `'spring'` color scale from **matplotlib**
#| layout-ncol: 3
nz.plot(column='Median_income', legend=True, cmap='Reds');
nz.plot(column='Median_income', legend=True, cmap='Reds_r');
nz.plot(column='Median_income', legend=True, cmap='spring');
```

<!-- jn: spring does not look like a color blind friendly color scale... I would suggest to use a different one. (I would suggest avoiding giving bad examples, even if they are just examples...) -->

Categorical symbology is also supported, such as when `column` points to an `str` attribute.
For example, the following expression sets symbology according to the `'Island'` column.
For categorical variables, it makes sense to use a qualitative color scale, such as `'Set1'` from ColorBrewer (@fig-plot-symbology-categorical):
For categorical variables, it makes sense to use a qualitative color scale, such as `'Set1'` from ColorBrewer.
For example, the following expression sets symbology according to the `'Island'` column (@fig-plot-symbology-categorical).

```{python}
#| label: fig-plot-symbology-categorical
#| fig-cap: Symbology for a categorical variable
nz.plot(column='Island', legend=True, cmap='Set1');
```

In case the legend interferes with the contents (such as in @fig-plot-symbology-categorical), we can modify the legend position, as follows (@fig-plot-legend-pos):
In case the legend interferes with the contents (such as in @fig-plot-symbology-categorical), we can modify the legend position using the `legend_kwds` argument (@fig-plot-legend-pos).

```{python}
#| label: fig-plot-legend-pos
#| fig-cap: Setting legend position in `.plot`
nz.plot(column='Island', legend=True, cmap='Set1', legend_kwds={'loc': 4});
```

The `rasterio.plot.show` function, based on **matplotlib** as well, supports the same kinds of `cmap` arguments.
For example (@fig-plot-symbology-colors-r):
The `rasterio.plot.show` function is also based on **matplotlib**, and thus supports the same kinds of `cmap` arguments (@fig-plot-symbology-colors-r).

```{python}
#| label: fig-plot-symbology-colors-r
Expand All @@ -213,19 +210,18 @@ For example (@fig-plot-symbology-colors-r):
#| - The `'BrBG'` color scale from ColorBrewer
#| - Reversed `'BrBG_r'` color scale
#| - The `'nipy_spectral'` color scale from **matplotlib**
rasterio.plot.show(nz_elev, cmap='BrBG');
rasterio.plot.show(nz_elev, cmap='BrBG_r');
rasterio.plot.show(nz_elev, cmap='nipy_spectral');
```

Unfortunately, there is no built-in option to display a legend in `rasterio.plot.show`.
The following [workaround](https://stackoverflow.com/questions/61327088/rio-plot-show-with-colorbar), reverting to **matplotlib** methods, can be used to acheive it instead (@fig-plot-symbology-colors-r-scale):
The following [workaround](https://stackoverflow.com/questions/61327088/rio-plot-show-with-colorbar), reverting to **matplotlib** methods, can be used to acheive it instead (@fig-plot-symbology-colors-r-scale).
<!-- jn: a few sentence explanation of the code below is needed... -->

```{python}
#| label: fig-plot-symbology-colors-r-scale
#| fig-cap: Adding a legend in `rasterio.plot.show`
fig, ax = plt.subplots()
i = ax.imshow(nz_elev.read(1), cmap='BrBG')
rasterio.plot.show(nz_elev, cmap='BrBG', ax=ax);
Expand Down

0 comments on commit f3a57c9

Please sign in to comment.