diff --git a/08-mapping.ipynb b/08-mapping.ipynb index d5d3f35b..6c66bdcf 100644 --- a/08-mapping.ipynb +++ b/08-mapping.ipynb @@ -6,9 +6,9 @@ "source": [ "# Making maps with Python {#sec-map-making}\n", "\n", - "## Prerequisites {.unnumbered}" + "## Prerequisites {.unnumbered}\n" ], - "id": "65f0b74f" + "id": "b06a04d0" }, { "cell_type": "code", @@ -36,9 +36,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Let's import the required packages:" + "Let's import the required packages:\n" ], - "id": "a819ef48" + "id": "6d660dcb" }, { "cell_type": "code", @@ -51,7 +51,7 @@ "import contextily as cx\n", "import folium" ], - "id": "50d83c23", + "id": "ef9fdd3c", "execution_count": null, "outputs": [] }, @@ -67,7 +67,7 @@ "pd.options.display.max_colwidth = 35\n", "plt.rcParams['figure.figsize'] = (5, 5)" ], - "id": "4cc72590", + "id": "4a0adf8b", "execution_count": null, "outputs": [] }, @@ -75,9 +75,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "and load the sample data for this chapter:" + "and load the sample data for this chapter:\n" ], - "id": "8935f8c5" + "id": "8f5ce72e" }, { "cell_type": "code", @@ -90,7 +90,7 @@ "tanzania_buf = tanzania.to_crs(32736).buffer(50000).to_crs(4326)\n", "tanzania_neigh = gpd.read_file('data/world.gpkg', mask=tanzania_buf)" ], - "id": "a658a269", + "id": "26d2d326", "execution_count": null, "outputs": [] }, @@ -144,9 +144,9 @@ "### Minimal example\n", "\n", "A vector layer (`GeoDataFrame`) or a geometry column (`GeoSeries`) can be displayed using their `.plot` method (@sec-vector-layers).\n", - "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):\n" ], - "id": "39cc5bc6" + "id": "1d180b71" }, { "cell_type": "code", @@ -166,9 +166,9 @@ "metadata": {}, "source": [ "A `rasterio` raster file connection, or a numpy `ndarray`, can be displayed using `rasterio.plot.show` (@sec-using-rasterio).\n", - "Here is a minimal example of a static raster map (@fig-raster-minimal):" + "Here is a minimal example of a static raster map (@fig-raster-minimal):\n" ], - "id": "7d057122" + "id": "5c8a51fa" }, { "cell_type": "code", @@ -189,9 +189,9 @@ "source": [ "### Styling {#sec-static-styling}\n", "\n", - "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):\n" ], - "id": "c6b20d14" + "id": "3b4814e2" }, { "cell_type": "code", @@ -218,9 +218,9 @@ "metadata": {}, "source": [ "And here is an example of using `markersize` to get larger points (@fig-basic-plot-markersize).\n", - "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:" + "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:\n" ], - "id": "ce62e849" + "id": "79206a9f" }, { "cell_type": "code", @@ -248,9 +248,9 @@ "- `legend`---Whether to show a legend\n", "- `cmap`---Color map\n", "\n", - "For example, here we plot the `nz` polygons colored according to the `'Median_income'` attribute (@fig-plot-symbology):" + "For example, here we plot the `nz` polygons colored according to the `'Median_income'` attribute (@fig-plot-symbology):\n" ], - "id": "bb3e9d45" + "id": "f7ede20c" }, { "cell_type": "code", @@ -274,9 +274,9 @@ "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.\n", "Any color scale can be reversed, using the `_r` suffic.\n", "Finally, other color scales are available, see the **matplotlib** [colormaps article](https://matplotlib.org/stable/tutorials/colors/colormaps.html) for details.\n", - "The following code sections demonstrates three color scale specifications other than the default (@fig-plot-symbology-colors):" + "The following code sections demonstrates three color scale specifications other than the default (@fig-plot-symbology-colors):\n" ], - "id": "c0c63fe6" + "id": "74a67b61" }, { "cell_type": "code", @@ -304,9 +304,9 @@ "source": [ "Categorical symbology is also supported, such as when `column` points to an `str` attribute.\n", "For example, the following expression sets symbology according to the `'Island'` column.\n", - "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 (@fig-plot-symbology-categorical):\n" ], - "id": "86fb3ead" + "id": "9916ff1f" }, { "cell_type": "code", @@ -325,9 +325,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "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, as follows (@fig-plot-legend-pos):\n" ], - "id": "e3153b0f" + "id": "578f0ce9" }, { "cell_type": "code", @@ -347,9 +347,9 @@ "metadata": {}, "source": [ "The `rasterio.plot.show` function, based on **matplotlib** as well, supports the same kinds of `cmap` arguments.\n", - "For example (@fig-plot-symbology-colors-r):" + "For example (@fig-plot-symbology-colors-r):\n" ], - "id": "21f53d8e" + "id": "bc69f414" }, { "cell_type": "code", @@ -376,9 +376,9 @@ "metadata": {}, "source": [ "Unfortunately, there is no built-in option to display a legend in `rasterio.plot.show`.\n", - "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):\n" ], - "id": "dce55770" + "id": "d1ca2e68" }, { "cell_type": "code", @@ -403,13 +403,13 @@ "### Labels {#sec-plot-static-labels}\n", "\n", "Labels are often useful to annotate maps, to identify the location of specific features. \n", - "GIS software has specialized algorithms for label placement, e.g., to avoid overlaps. \n", + "GIS software has specialized algorithms for label placement, e.g., to avoid overlaps between adjacent labels. \n", "Furthermore, editing in graphical editing software is sometimes used for fine tuning of label placement.\n", - "Nevertheless, simple labels addend within the Python environment can be a good starting point.\n", + "Nevertheless, simple labels added within the Python environment can be a good starting point, both for interactive exploration and sharing analysis results.\n", "\n", - "To demonstrate, suppose that we have a layer of polygons comprising the New Zealand southern Island:" + "To demonstrate, suppose that we have a layer `nz1` of regions comprising the New Zealand southern Island:\n" ], - "id": "f3b87572" + "id": "29227e2a" }, { "cell_type": "code", @@ -417,7 +417,7 @@ "source": [ "nz1 = nz[nz['Island'] == 'South']" ], - "id": "ff35e1d5", + "id": "e3f1ef86", "execution_count": null, "outputs": [] }, @@ -425,9 +425,15 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "... @fig-labels-polygon." + "To add a label in **matplotlib**, we use the [`.annotate`](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.annotate.html) method where the important arguments are the label string and the placement (a `tuple` of the form `(x,y)`). \n", + "When labeling vector layers, we typically want to add numerous labels, based on (one or more) attribute of each feature. \n", + "To do that, we can run a `for` loop or the `.apply` method, passing the label text and the coordinates of each feature.\n", + "For example, in the following example we use the `.apply` method the pass the region name (`'Name'` attribute) and the geometry centroid coordinates, for each region, to `.annotate`.\n", + "We are also using `ha='center'` (short for `horizontalalignment`).\n", + "\n", + "The result is shown in @fig-labels-polygon.\n" ], - "id": "8b336671" + "id": "283ef485" }, { "cell_type": "code", @@ -455,9 +461,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "..." + "...\n" ], - "id": "2e56cc89" + "id": "6f0afa78" }, { "cell_type": "code", @@ -467,7 +473,7 @@ "ctr['geometry'] = ctr.centroid\n", "ctr" ], - "id": "9342120e", + "id": "39bc5dda", "execution_count": null, "outputs": [] }, @@ -475,9 +481,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "... @fig-labels-points1." + "... @fig-labels-points1.\n" ], - "id": "18fd7b12" + "id": "6bce3c15" }, { "cell_type": "code", @@ -506,9 +512,9 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "... @fig-labels-points2." + "... @fig-labels-points2.\n" ], - "id": "f2685b0c" + "id": "68c72c74" }, { "cell_type": "code", @@ -545,9 +551,9 @@ "- store the first plot in a variable (e.g., `base`), and\n", "- pass it as the `ax` argument of any subsequent plot(s) (e.g., `ax=base`).\n", "\n", - "For example, here is how we can plot `nz` and `nz_height` together (@fig-two-layers):" + "For example, here is how we can plot `nz` and `nz_height` together (@fig-two-layers):\n" ], - "id": "28dafaeb" + "id": "1d9f63f2" }, { "cell_type": "code", @@ -574,9 +580,9 @@ "\n", "- Panel (a) shows a raster (New Zealand elevation) and a vector layer (New Zealand administrative division)\n", "- Panel (b) shows the raster with a buffer of 22.2 $km$ around the dissolved administrative borders, representing New Zealand's [territorial waters](https://en.wikipedia.org/wiki/Territorial_waters) (see @sec-global-operations-and-distances)\n", - "- Panel (c) shows the raster with two vector layers: the territorial waters (in red) and elevation measurement points (in yellow)" + "- Panel (c) shows the raster with two vector layers: the territorial waters (in red) and elevation measurement points (in yellow)\n" ], - "id": "3eb405d1" + "id": "70c88710" }, { "cell_type": "code", @@ -630,9 +636,9 @@ "\n", "Basemaps can be added to **geopandas** static plots using the [**contextily**](https://contextily.readthedocs.io/en/latest/index.html) package.\n", "A preliminary step is to convert our layers to `EPSG:3857` ([\"Web Mercator\"](https://en.wikipedia.org/wiki/Web_Mercator_projection)), to be in agreement with the basemaps, which are typically provided in this CRS.\n", - "For example, let's take the small `\"Nelson\"` polygon from `nz`, and reproject it to `3857`:" + "For example, let's take the small `\"Nelson\"` polygon from `nz`, and reproject it to `3857`:\n" ], - "id": "8928c691" + "id": "3071d481" }, { "cell_type": "code", @@ -640,7 +646,7 @@ "source": [ "nzw = nz[nz['Name'] == 'Nelson'].to_crs(epsg=3857)" ], - "id": "3817c9c2", + "id": "5c7ac58c", "execution_count": null, "outputs": [] }, @@ -654,9 +660,9 @@ "The possible values are given in the `cx.providers`.\n", "Also check out the [gallery](https://xyzservices.readthedocs.io/en/stable/gallery.html).\n", "Finally, custom basemaps (such as from your own raster tile server) can be specified using a [URL](https://contextily.readthedocs.io/en/latest/providers_deepdive.html#Manually-specifying-a-provider).\n", - "For example (@fig-basemap):" + "For example (@fig-basemap):\n" ], - "id": "4949f901" + "id": "76689753" }, { "cell_type": "code", @@ -699,9 +705,9 @@ "\n", "Faceted maps are multiple maps displaying the same symbology for the same spatial layers, but with different data in each panel.\n", "The data displayed in the different panels typically refer to different properties, or time steps.\n", - "For example, the `nz` layer has several different properties for each polygon, stored as separate attributes:" + "For example, the `nz` layer has several different properties for each polygon, stored as separate attributes:\n" ], - "id": "b69ca33e" + "id": "f879acc6" }, { "cell_type": "code", @@ -710,7 +716,7 @@ "vars = ['Land_area', 'Population', 'Median_income', 'Sex_ratio']\n", "nz[vars]" ], - "id": "675f94c4", + "id": "b90fe48b", "execution_count": null, "outputs": [] }, @@ -719,9 +725,9 @@ "metadata": {}, "source": [ "We may want to plot them all in a faceted map, that is, four small maps of `nz` with the different variables.\n", - "To do that, we initialize the plot with the right number of panels, such as `ncols=len(vars)` if we wish to have one row and four columns, and then go over the variables in a `for` loop, each time plotting `vars[i]` into the `ax[i]` panel (@fig-faceted-map):" + "To do that, we initialize the plot with the right number of panels, such as `ncols=len(vars)` if we wish to have one row and four columns, and then go over the variables in a `for` loop, each time plotting `vars[i]` into the `ax[i]` panel (@fig-faceted-map):\n" ], - "id": "7af60a41" + "id": "6a091fdd" }, { "cell_type": "code", @@ -750,9 +756,9 @@ "- plot into `ax[i]`\n", "\n", "For example, here is how we can reproduce the last plot, this time in a $2 \\times 2$ layout, instead of a $1 \\times 4$ layout (@fig-faceted-map2).\n", - "One more modification we are doing here is hiding the axis ticks and labels, to make the map less \"crowded\", using `ax[i].xaxis.set_visible(False)` (and same for `.yaxis`):" + "One more modification we are doing here is hiding the axis ticks and labels, to make the map less \"crowded\", using `ax[i].xaxis.set_visible(False)` (and same for `.yaxis`):\n" ], - "id": "7619048e" + "id": "e1e44ad2" }, { "cell_type": "code", @@ -779,9 +785,9 @@ "source": [ "It is also possible to \"manually\" specify the properties of each panel, and which row/column it goes in (e.g., @fig-spatial-aggregation-different-functions).\n", "This can be useful when the various panels have different components, or even completely different types of plots (e.g., @fig-zion-transect), making automation with a `for` loop less applicable.\n", - "For example, here is a plot similar to @fig-faceted-map2, but specifying each panel using a separate expression instead of using a `for` loop (@fig-faceted-map3):" + "For example, here is a plot similar to @fig-faceted-map2, but specifying each panel using a separate expression instead of using a `for` loop (@fig-faceted-map3):\n" ], - "id": "4f1108e6" + "id": "ab4ad75a" }, { "cell_type": "code", @@ -813,9 +819,9 @@ "### Exporting static maps {#sec-exporting-static-maps}\n", "\n", "Static maps can be exported to a file using the [`matplotlib.pyplot.savefig`](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.savefig.html) function.\n", - "For example, the following code section recreates @fig-read-shp-query (see previous Chapter), but this time the last expression saves the image to a JPG image named `plot_geopandas.jpg`:" + "For example, the following code section recreates @fig-read-shp-query (see previous Chapter), but this time the last expression saves the image to a JPG image named `plot_geopandas.jpg`:\n" ], - "id": "84b9fdab" + "id": "ee35f2ab" }, { "cell_type": "code", @@ -833,7 +839,7 @@ "tanzania_neigh.apply(lambda x: axes[1].annotate(text=x['name_long'], xy=x.geometry.centroid.coords[0], ha='center'), axis=1);\n", "plt.savefig('output/plot_geopandas.jpg')" ], - "id": "d0a37fa8", + "id": "ca5167d6", "execution_count": null, "outputs": [] }, @@ -842,9 +848,9 @@ "metadata": {}, "source": [ "Figures with rasters can be exported exactly the same way.\n", - "For example, the following code section (@sec-plot-static-layers) creates an image of a raster and a vector layer, which is then exported to a file named `plot_rasterio.jpg`:" + "For example, the following code section (@sec-plot-static-layers) creates an image of a raster and a vector layer, which is then exported to a file named `plot_rasterio.jpg`:\n" ], - "id": "498c55e8" + "id": "793035b8" }, { "cell_type": "code", @@ -857,7 +863,7 @@ "nz.to_crs(nz_elev.crs).plot(ax=ax, facecolor='none', edgecolor='r');\n", "plt.savefig('output/plot_rasterio.jpg')" ], - "id": "080b5a4b", + "id": "4147c422", "execution_count": null, "outputs": [] }, @@ -866,9 +872,9 @@ "metadata": {}, "source": [ "Image file properties can be controlled through the `plt.subplots` and `plt.savefig` parameters.\n", - "For example, the following code section exports the same raster plot to a file named `plot_rasterio2.svg`, which has different dimensions (width = 5 $in$, height = 7 $in$), a different format (SVG), and different resolution (300 $DPI$:)" + "For example, the following code section exports the same raster plot to a file named `plot_rasterio2.svg`, which has different dimensions (width = 5 $in$, height = 7 $in$), a different format (SVG), and different resolution (300 $DPI$:)\n" ], - "id": "364d27c4" + "id": "471f65a2" }, { "cell_type": "code", @@ -881,7 +887,7 @@ "nz.to_crs(nz_elev.crs).plot(ax=ax, facecolor='none', edgecolor='r');\n", "plt.savefig('output/plot_rasterio2.svg', dpi=300)" ], - "id": "85a5ff74", + "id": "e4e504d8", "execution_count": null, "outputs": [] }, @@ -896,9 +902,9 @@ "### Minimal example\n", "\n", "An interactive map of a `GeoSeries` or `GeoDataFrame` can be created with `.explore` (@sec-vector-layers).\n", - "Here is a minimal example:" + "Here is a minimal example:\n" ], - "id": "52d055d1" + "id": "05f76ee5" }, { "cell_type": "code", @@ -932,9 +938,9 @@ "- `fillColor`---Fill color\n", "- `fillOpacity`---Fill opacity (from `0` to `1`)\n", "\n", - "For example, here is how we can set green fill color and 30% opaque black outline of `nz` polygons in `.explore` (@fig-explore-styling-polygons):" + "For example, here is how we can set green fill color and 30% opaque black outline of `nz` polygons in `.explore` (@fig-explore-styling-polygons):\n" ], - "id": "87c50aed" + "id": "1c4f070a" }, { "cell_type": "code", @@ -964,9 +970,9 @@ "- `'circle'`---A vector circle with radius specified in $m$\n", "- `'circle_marker'`---A vector circle with radius specified in pixels (the default)\n", "\n", - "For example, the following expression draws `'circe_marker`' points with 20 pixel radius, green fill, and black outline (@fig-explore-styling-points):" + "For example, the following expression draws `'circe_marker`' points with 20 pixel radius, green fill, and black outline (@fig-explore-styling-points):\n" ], - "id": "3c4ddaa2" + "id": "9f151f97" }, { "cell_type": "code", @@ -990,9 +996,9 @@ "metadata": {}, "source": [ "The following expression demonstrates the `'marker'` option (@fig-explore-styling-points2).\n", - "Note that the above-mentioned styling properties (other then `opacity`) are not applicable when using `marker_type='marker'`, because the markers are fixed PNG images:" + "Note that the above-mentioned styling properties (other then `opacity`) are not applicable when using `marker_type='marker'`, because the markers are fixed PNG images:\n" ], - "id": "48b613fc" + "id": "ec3e91a0" }, { "cell_type": "code", @@ -1013,9 +1019,9 @@ "source": [ "### Layers\n", "\n", - "To display multiple layers, one on top of another, with `.explore`, we use the `m` argument, which stands for the previous map (@fig-explore-layers):" + "To display multiple layers, one on top of another, with `.explore`, we use the `m` argument, which stands for the previous map (@fig-explore-layers):\n" ], - "id": "422abec5" + "id": "44c0ceaf" }, { "cell_type": "code", @@ -1038,9 +1044,9 @@ "One of the advantages of interactive maps is the ability to turn layers \"on\" and \"off\".\n", "This capability is implemented in [`folium.LayerControl`](https://python-visualization.github.io/folium/latest/user_guide/ui_elements/layer_control.html#LayerControl) from package **folium**, which the **geopandas** `.explore` method is a wrapper of.\n", "For example, this is how we can add a layer control for the `nz` and `nz_height` layers (@fig-explore-layers-controls).\n", - "Note the `name` properties, used to specify layer names in the control, and the `collapsed` property, used to specify whether the control is fully visible at all times (`False`), or on mouse hover (`True`, the default):" + "Note the `name` properties, used to specify layer names in the control, and the `collapsed` property, used to specify whether the control is fully visible at all times (`False`), or on mouse hover (`True`, the default):\n" ], - "id": "99096059" + "id": "e29fc973" }, { "cell_type": "code", @@ -1065,9 +1071,9 @@ "### Symbology {#sec-explore-symbology}\n", "\n", "Symbology can be specified in `.explore` using similar arguments as in `.plot` (@sec-plot-symbology).\n", - "For example, here is an interactive version of @fig-plot-symbology-colors (a)." + "For example, here is an interactive version of @fig-plot-symbology-colors (a).\n" ], - "id": "85374ad8" + "id": "3c7de930" }, { "cell_type": "code", @@ -1088,9 +1094,9 @@ "source": [ "Fixed styling (@sec-explore-symbology) can be combined with symbology settings.\n", "For example, polygon outline colors in @fig-explore-symbology are styled according to `'Median_income'`, however, this layer has overlapping outlines and the color is arbitrarily set according to the order of features (top-most features), which may be misleading and confusing.\n", - "To specify fixed outline colors (e.g., black), we can use the `color` and `weight` properties of `style_kwds` (@fig-explore-symbology2):" + "To specify fixed outline colors (e.g., black), we can use the `color` and `weight` properties of `style_kwds` (@fig-explore-symbology2):\n" ], - "id": "94ec997c" + "id": "7795dd96" }, { "cell_type": "code", @@ -1123,9 +1129,9 @@ "\n", "Other basemaps are available through the **xyzservices** package, which needs to be installed (see `xyzservices.providers` for a list), or using a custom tile server URL.\n", "\n", - "For example, the following expression displays the `'CartoDB positron'` tiles in an `.explore` map (@fig-explore-basemaps):" + "For example, the following expression displays the `'CartoDB positron'` tiles in an `.explore` map (@fig-explore-basemaps):\n" ], - "id": "a851369a" + "id": "bd9d17fa" }, { "cell_type": "code", @@ -1150,9 +1156,9 @@ "The HTML file can then be shared with other people, or published on a server and shared through a URL.\n", "A good free option for publishing a web map is [GitHub Pages](https://pages.github.com/).\n", "\n", - "For example, here is how we can export the map shown in @fig-explore-layers-controls, to a file named `map.html`:" + "For example, here is how we can export the map shown in @fig-explore-layers-controls, to a file named `map.html`:\n" ], - "id": "b7049152" + "id": "8e1dad03" }, { "cell_type": "code", @@ -1164,7 +1170,7 @@ "folium.LayerControl(collapsed=False).add_to(m)\n", "m.save('output/map.html')" ], - "id": "a08d43dd", + "id": "b3a3b59d", "execution_count": null, "outputs": [] }, @@ -1180,7 +1186,7 @@ "\n", "## References" ], - "id": "d6e56dd9" + "id": "0f1749dd" } ], "metadata": { diff --git a/08-mapping.qmd b/08-mapping.qmd index 30890c31..491c92ae 100644 --- a/08-mapping.qmd +++ b/08-mapping.qmd @@ -235,17 +235,23 @@ fig.colorbar(i, ax=ax); ### Labels {#sec-plot-static-labels} Labels are often useful to annotate maps, to identify the location of specific features. -GIS software has specialized algorithms for label placement, e.g., to avoid overlaps. +GIS software has specialized algorithms for label placement, e.g., to avoid overlaps between adjacent labels. Furthermore, editing in graphical editing software is sometimes used for fine tuning of label placement. -Nevertheless, simple labels addend within the Python environment can be a good starting point. +Nevertheless, simple labels added within the Python environment can be a good starting point, both for interactive exploration and sharing analysis results. -To demonstrate, suppose that we have a layer of polygons comprising the New Zealand southern Island: +To demonstrate, suppose that we have a layer `nz1` of regions comprising the New Zealand southern Island: ```{python} nz1 = nz[nz['Island'] == 'South'] ``` -... @fig-labels-polygon. +To add a label in **matplotlib**, we use the [`.annotate`](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.annotate.html) method where the important arguments are the label string and the placement (a `tuple` of the form `(x,y)`). +When labeling vector layers, we typically want to add numerous labels, based on (one or more) attribute of each feature. +To do that, we can run a `for` loop or the `.apply` method, passing the label text and the coordinates of each feature. +For example, in the following example we use the `.apply` method the pass the region name (`'Name'` attribute) and the geometry centroid coordinates, for each region, to `.annotate`. +We are also using `ha='center'` (short for `horizontalalignment`). + +The result is shown in @fig-labels-polygon. ```{python} #| label: fig-labels-polygon diff --git a/08-mapping_files/execute-results/html.json b/08-mapping_files/execute-results/html.json new file mode 100644 index 00000000..171ad6e3 --- /dev/null +++ b/08-mapping_files/execute-results/html.json @@ -0,0 +1,15 @@ +{ + "hash": "8f829f31bbf063562aafb637f04184b1", + "result": { + "markdown": "# Making maps with Python {#sec-map-making}\n\n## Prerequisites {.unnumbered}\n\n\n\nLet's import the required packages:\n\n::: {.cell execution_count=2}\n``` {.python .cell-code}\nimport matplotlib.pyplot as plt\nimport geopandas as gpd\nimport rasterio\nimport rasterio.plot\nimport contextily as cx\nimport folium\n```\n:::\n\n\n\n\nand load the sample data for this chapter:\n\n::: {.cell execution_count=4}\n``` {.python .cell-code}\nnz = gpd.read_file('data/nz.gpkg')\nnz_height = gpd.read_file('data/nz_height.gpkg')\nnz_elev = rasterio.open('data/nz_elev.tif')\ntanzania = gpd.read_file('data/world.gpkg', where='name_long=\"Tanzania\"')\ntanzania_buf = tanzania.to_crs(32736).buffer(50000).to_crs(4326)\ntanzania_neigh = gpd.read_file('data/world.gpkg', mask=tanzania_buf)\n```\n:::\n\n\n## Introduction\n\n\n\n\n\n\n\nA satisfying and important aspect of geographic research is communicating the results.\nMap making---the art of cartography---is an ancient skill that involves communication, intuition, and an element of creativity.\nIn addition to being fun and creative, cartography also has important practical applications.\nA carefully crafted map can be the best way of communicating the results of your work, but poorly designed maps can leave a bad impression.\nCommon design issues include poor placement, size and readability of text and careless selection of colors, as outlined in the style guide of the Journal of Maps.\nFurthermore, poor map making can hinder the communication of results [@brewer_designing_2015]:\n\n> Amateur-looking maps can undermine your audience's ability to understand important information and weaken the presentation of a professional data investigation.\n\nMaps have been used for several thousand years for a wide variety of purposes.\nHistoric examples include maps of buildings and land ownership in the Old Babylonian dynasty more than 3000 years ago and Ptolemy's world map in his masterpiece Geography nearly 2000 years ago [@talbert_ancient_2014].\n\nMap making has historically been an activity undertaken only by, or on behalf of, the elite.\nThis has changed with the emergence of open source mapping software such as mapping packages in Python, R, and other languages, and the \"print composer\" in QGIS, which enable anyone to make high-quality maps, enabling \"citizen science\".\nMaps are also often the best way to present the findings of geocomputational research in a way that is accessible.\nMap making is therefore a critical part of geocomputation and its emphasis not only on describing, but also changing the world.\n\nBasic 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.\nOther, more advaned uses of these methods, were also encountered in subsequent chapters, when demonstrating the various outputs we got.\nIn this chapter, we provide a comprehensive summary of the most useful workflows of these two methods for creating static maps (@sec-static-maps).\nThen, we move on to elaborate on the `.explore` method for creating interactive maps, which was also briefly introduced earlier (@sec-vector-layers).\n\n## Static maps {#sec-static-maps}\n\nStatic maps are the most common type of visual output from geocomputation.\nWhen stored in a file, standard formats include `.png` and `.pdf` for raster and vector outputs, respectively.\nStatic 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.\nInteractive 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.\n\n\n\n\n\nLet's move on to the basics of static mapping with Python.\n\n### Minimal example\n\nA vector layer (`GeoDataFrame`) or a geometry column (`GeoSeries`) can be displayed using their `.plot` method (@sec-vector-layers).\nA minimal example of a vector layer map is obtained using `.plot` with nothing but the defaults (@fig-vector-minimal):\n\n::: {.cell execution_count=5}\n``` {.python .cell-code}\nnz.plot();\n```\n\n::: {.cell-output .cell-output-display}\n![Minimal example of a static vector layer plot with `.plot`](08-mapping_files/figure-html/fig-vector-minimal-output-1.png){#fig-vector-minimal width=306 height=442}\n:::\n:::\n\n\nA `rasterio` raster file connection, or a numpy `ndarray`, can be displayed using `rasterio.plot.show` (@sec-using-rasterio).\nHere is a minimal example of a static raster map (@fig-raster-minimal):\n\n::: {.cell execution_count=6}\n``` {.python .cell-code}\nrasterio.plot.show(nz_elev);\n```\n\n::: {.cell-output .cell-output-display}\n![Minimal example of a static raster plot with `rasterio.plot.show`](08-mapping_files/figure-html/fig-raster-minimal-output-1.png){#fig-raster-minimal width=334 height=442}\n:::\n:::\n\n\n### Styling {#sec-static-styling}\n\nThe most useful visual properties of the geometries, that can be specified in `.plot`, include `color`, `edgecolor`, and `markersize` (for points) (@fig-basic-plot):\n\n::: {#fig-basic-plot .cell layout-ncol='3' execution_count=7}\n``` {.python .cell-code}\nnz.plot(color='grey');\nnz.plot(color='none', edgecolor='blue');\nnz.plot(color='grey', edgecolor='blue');\n```\n\n::: {.cell-output .cell-output-display}\n![Grey fill](08-mapping_files/figure-html/fig-basic-plot-output-1.png){#fig-basic-plot-1 width=306 height=442}\n:::\n\n::: {.cell-output .cell-output-display}\n![No fill, blue edge](08-mapping_files/figure-html/fig-basic-plot-output-2.png){#fig-basic-plot-2 width=306 height=442}\n:::\n\n::: {.cell-output .cell-output-display}\n![Grey fill, blue edge](08-mapping_files/figure-html/fig-basic-plot-output-3.png){#fig-basic-plot-3 width=306 height=442}\n:::\n\nSetting `color` and `edgecolor` in static maps of a vector layer\n:::\n\n\nAnd here is an example of using `markersize` to get larger points (@fig-basic-plot-markersize).\nThis 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:\n\n::: {.cell execution_count=8}\n``` {.python .cell-code}\nfig, ax = plt.subplots(figsize=(4,4))\nnz_height.plot(markersize=100, ax=ax);\n```\n\n::: {.cell-output .cell-output-display}\n![Setting `markersize` in a static map of a vector layer](08-mapping_files/figure-html/fig-basic-plot-markersize-output-1.png){#fig-basic-plot-markersize width=347 height=362}\n:::\n:::\n\n\n### Symbology {#sec-plot-symbology}\n\nWe can set symbology in a `.plot` using the following parameters:\n\n- `column`---A column name\n- `legend`---Whether to show a legend\n- `cmap`---Color map\n\nFor example, here we plot the `nz` polygons colored according to the `'Median_income'` attribute (@fig-plot-symbology):\n\n::: {.cell execution_count=9}\n``` {.python .cell-code}\nnz.plot(column='Median_income', legend=True);\n```\n\n::: {.cell-output .cell-output-display}\n![Symbology in a static map created with `.plot`](08-mapping_files/figure-html/fig-plot-symbology-output-1.png){#fig-plot-symbology width=395 height=442}\n:::\n:::\n\n\nThe default color scale which you see in @fig-plot-symbology is `cmap='viridis'`.\nThe `cmap` (\"color map\") argument can be used to specify any of countless other color scales.\nA first safe choice is often the [ColorBrewer](https://colorbrewer2.org/#type=sequential&scheme=BuGn&n=3) collection of color scales, specifically designed for mapping.\nAny color scale can be reversed, using the `_r` suffic.\nFinally, other color scales are available, see the **matplotlib** [colormaps article](https://matplotlib.org/stable/tutorials/colors/colormaps.html) for details.\nThe following code sections demonstrates three color scale specifications other than the default (@fig-plot-symbology-colors):\n\n::: {#fig-plot-symbology-colors .cell layout-ncol='3' execution_count=10}\n``` {.python .cell-code}\nnz.plot(column='Median_income', legend=True, cmap='Reds');\nnz.plot(column='Median_income', legend=True, cmap='Reds_r');\nnz.plot(column='Median_income', legend=True, cmap='spring');\n```\n\n::: {.cell-output .cell-output-display}\n![The `'Reds'` color scale from ColorBrewer](08-mapping_files/figure-html/fig-plot-symbology-colors-output-1.png){#fig-plot-symbology-colors-1 width=395 height=442}\n:::\n\n::: {.cell-output .cell-output-display}\n![Reversed `'Reds'` color scale](08-mapping_files/figure-html/fig-plot-symbology-colors-output-2.png){#fig-plot-symbology-colors-2 width=395 height=442}\n:::\n\n::: {.cell-output .cell-output-display}\n![The `'spring'` color scale from **matplotlib**](08-mapping_files/figure-html/fig-plot-symbology-colors-output-3.png){#fig-plot-symbology-colors-3 width=395 height=442}\n:::\n\nSymbology in a static map of a vector layer, created with `.plot`\n:::\n\n\nCategorical symbology is also supported, such as when `column` points to an `str` attribute.\nFor example, the following expression sets symbology according to the `'Island'` column.\nFor categorical variables, it makes sense to use a qualitative color scale, such as `'Set1'` from ColorBrewer (@fig-plot-symbology-categorical):\n\n::: {.cell execution_count=11}\n``` {.python .cell-code}\nnz.plot(column='Island', legend=True, cmap='Set1');\n```\n\n::: {.cell-output .cell-output-display}\n![Symbology for a categorical variable](08-mapping_files/figure-html/fig-plot-symbology-categorical-output-1.png){#fig-plot-symbology-categorical width=306 height=442}\n:::\n:::\n\n\nIn 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):\n\n::: {.cell execution_count=12}\n``` {.python .cell-code}\nnz.plot(column='Island', legend=True, cmap='Set1', legend_kwds={'loc': 4});\n```\n\n::: {.cell-output .cell-output-display}\n![Setting legend position in `.plot`](08-mapping_files/figure-html/fig-plot-legend-pos-output-1.png){#fig-plot-legend-pos width=306 height=442}\n:::\n:::\n\n\nThe `rasterio.plot.show` function, based on **matplotlib** as well, supports the same kinds of `cmap` arguments.\nFor example (@fig-plot-symbology-colors-r):\n\n::: {#fig-plot-symbology-colors-r .cell layout-ncol='3' execution_count=13}\n``` {.python .cell-code}\nrasterio.plot.show(nz_elev, cmap='BrBG');\nrasterio.plot.show(nz_elev, cmap='BrBG_r');\nrasterio.plot.show(nz_elev, cmap='nipy_spectral');\n```\n\n::: {.cell-output .cell-output-display}\n![The `'BrBG'` color scale from ColorBrewer](08-mapping_files/figure-html/fig-plot-symbology-colors-r-output-1.png){#fig-plot-symbology-colors-r-1 width=334 height=442}\n:::\n\n::: {.cell-output .cell-output-display}\n![Reversed `'BrBG_r'` color scale](08-mapping_files/figure-html/fig-plot-symbology-colors-r-output-2.png){#fig-plot-symbology-colors-r-2 width=334 height=442}\n:::\n\n::: {.cell-output .cell-output-display}\n![The `'nipy_spectral'` color scale from **matplotlib**](08-mapping_files/figure-html/fig-plot-symbology-colors-r-output-3.png){#fig-plot-symbology-colors-r-3 width=334 height=442}\n:::\n\nSymbology in a static map of a raster, with `rasterio.plot.show`\n:::\n\n\nUnfortunately, there is no built-in option to display a legend in `rasterio.plot.show`.\nThe 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):\n\n::: {.cell execution_count=14}\n``` {.python .cell-code}\nfig, ax = plt.subplots()\ni = ax.imshow(nz_elev.read(1), cmap='BrBG')\nrasterio.plot.show(nz_elev, cmap='BrBG', ax=ax);\nfig.colorbar(i, ax=ax);\n```\n\n::: {.cell-output .cell-output-display}\n![Adding a legend in `rasterio.plot.show`](08-mapping_files/figure-html/fig-plot-symbology-colors-r-scale-output-1.png){#fig-plot-symbology-colors-r-scale width=414 height=442}\n:::\n:::\n\n\n### Labels {#sec-plot-static-labels}\n\n...\n\n::: {.cell execution_count=15}\n``` {.python .cell-code}\nnz1 = nz[nz['Island'] == 'South']\n```\n:::\n\n\n... @fig-labels-polygon.\n\n::: {.cell execution_count=16}\n``` {.python .cell-code}\nfig, ax = plt.subplots()\nnz1.plot(ax=ax, color='lightgrey', edgecolor='grey')\nnz1.apply(\n lambda x: ax.annotate(\n text=x['Name'], \n xy=x.geometry.centroid.coords[0], \n ha='center'\n ), \n axis=1\n);\n```\n\n::: {.cell-output .cell-output-display}\n![Labels at polygon centroids](08-mapping_files/figure-html/fig-labels-polygon-output-1.png){#fig-labels-polygon width=348 height=442}\n:::\n:::\n\n\n...\n\n::: {.cell execution_count=17}\n``` {.python .cell-code}\nctr = nz[['Island', 'geometry']].dissolve(by='Island').reset_index()\nctr['geometry'] = ctr.centroid\nctr\n```\n\n::: {.cell-output .cell-output-display execution_count=430}\n```{=html}\n
\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
Islandgeometry
0NorthPOINT (1834096.904 5732233.908)
1SouthPOINT (1401304.646 5125013.652)
\n
\n```\n:::\n:::\n\n\n... @fig-labels-points1.\n\n::: {.cell execution_count=18}\n``` {.python .cell-code}\nfig, ax = plt.subplots()\nnz.plot(ax=ax, color='none', edgecolor='lightgrey')\nctr.apply(\n lambda x: ax.annotate(\n text=x['Island'], \n xy=x.geometry.coords[0], \n ha='center',\n weight='bold'\n ), \n axis=1\n);\n```\n\n::: {.cell-output .cell-output-display}\n![Labels at points](08-mapping_files/figure-html/fig-labels-points1-output-1.png){#fig-labels-points1 width=306 height=442}\n:::\n:::\n\n\n... @fig-labels-points2.\n\n::: {.cell execution_count=19}\n``` {.python .cell-code}\nfig, ax = plt.subplots()\nnz.plot(ax=ax, color='none', edgecolor='lightgrey')\nax.annotate(\n ctr['Island'].iloc[0], \n xy=(ctr.geometry.iloc[0].x, ctr.geometry.iloc[0].y),\n ha='center', weight='bold'\n)\nax.annotate(\n ctr['Island'].iloc[1], \n xy=(ctr.geometry.iloc[1].x, ctr.geometry.iloc[1].y),\n ha='center', weight='bold'\n);\n```\n\n::: {.cell-output .cell-output-display}\n![Labels at points (manual)](08-mapping_files/figure-html/fig-labels-points2-output-1.png){#fig-labels-points2 width=306 height=442}\n:::\n:::\n\n\n### Layers {#sec-plot-static-layers}\n\nTo display more than one layer in the same static map, we need to:\n\n- store the first plot in a variable (e.g., `base`), and\n- pass it as the `ax` argument of any subsequent plot(s) (e.g., `ax=base`).\n\nFor example, here is how we can plot `nz` and `nz_height` together (@fig-two-layers):\n\n::: {.cell execution_count=20}\n``` {.python .cell-code}\nbase = nz.plot(color='none')\nnz_height.plot(ax=base, color='red');\n```\n\n::: {.cell-output .cell-output-display}\n![Plotting two layers, `nz` (polygons) and `nz_height` (points)](08-mapping_files/figure-html/fig-two-layers-output-1.png){#fig-two-layers width=306 height=442}\n:::\n:::\n\n\nWe can combine rasters and vector layers in the same plot as well, which we already used earlier in the book, for example when explaining masking and cropping (@fig-raster-crop).\nThe technique is to initialize a plot with `fig,ax=plt.subplots()`, then pass `ax` to any of the separate plots, making them appear together.\n\nFor example, @fig-plot-raster-and-vector demonstrated plotting a raster with increasingly complicated additions:\n\n- Panel (a) shows a raster (New Zealand elevation) and a vector layer (New Zealand administrative division)\n- Panel (b) shows the raster with a buffer of 22.2 $km$ around the dissolved administrative borders, representing New Zealand's [territorial waters](https://en.wikipedia.org/wiki/Territorial_waters) (see @sec-global-operations-and-distances)\n- Panel (c) shows the raster with two vector layers: the territorial waters (in red) and elevation measurement points (in yellow)\n\n::: {#fig-plot-raster-and-vector .cell layout-ncol='3' execution_count=21}\n``` {.python .cell-code}\n# Raster + vector layer\nfig, ax = plt.subplots(figsize=(5, 5))\nrasterio.plot.show(nz_elev, ax=ax)\nnz.to_crs(nz_elev.crs).plot(ax=ax, facecolor='none', edgecolor='red');\n\n# Raster + computed vector layer\nfig, ax = plt.subplots(figsize=(5, 5))\nrasterio.plot.show(nz_elev, ax=ax)\ngpd.GeoSeries(nz.unary_union, crs=nz.crs) \\\n .to_crs(nz_elev.crs) \\\n .buffer(22200) \\\n .boundary \\\n .plot(ax=ax, color='red');\n\n# Raster + two vector layers\nfig, ax = plt.subplots(figsize=(5, 5))\nrasterio.plot.show(nz_elev, ax=ax)\ngpd.GeoSeries(nz.unary_union, crs=nz.crs) \\\n .to_crs(nz_elev.crs) \\\n .buffer(22200) \\\n .exterior \\\n .plot(ax=ax, color='red')\nnz_height.to_crs(nz_elev.crs).plot(ax=ax, color='yellow');\n```\n\n::: {.cell-output .cell-output-display}\n![Raster + vector layer](08-mapping_files/figure-html/fig-plot-raster-and-vector-output-1.png){#fig-plot-raster-and-vector-1 width=334 height=442}\n:::\n\n::: {.cell-output .cell-output-display}\n![Raster + computed vector layer](08-mapping_files/figure-html/fig-plot-raster-and-vector-output-2.png){#fig-plot-raster-and-vector-2 width=314 height=442}\n:::\n\n::: {.cell-output .cell-output-display}\n![Raster + two vector layers](08-mapping_files/figure-html/fig-plot-raster-and-vector-output-3.png){#fig-plot-raster-and-vector-3 width=314 height=442}\n:::\n\nCombining a raster and vector layers in the same plot\n:::\n\n\n### Basemaps\n\nBasemaps, or background layers, are often useful to provide context to the displayed layers (which are in the \"foreground\").\nBasemaps are ubiquitous in interactive maps (see @sec-interactive-maps).\nHowever, they are often useful in static maps too.\n\nBasemaps can be added to **geopandas** static plots using the [**contextily**](https://contextily.readthedocs.io/en/latest/index.html) package.\nA preliminary step is to convert our layers to `EPSG:3857` ([\"Web Mercator\"](https://en.wikipedia.org/wiki/Web_Mercator_projection)), to be in agreement with the basemaps, which are typically provided in this CRS.\nFor example, let's take the small `\"Nelson\"` polygon from `nz`, and reproject it to `3857`:\n\n::: {.cell execution_count=22}\n``` {.python .cell-code}\nnzw = nz[nz['Name'] == 'Nelson'].to_crs(epsg=3857)\n```\n:::\n\n\nTo add a basemap, we use the `contextily.add_basemap` function, similarly to the way we added multiple layers (@sec-plot-static-layers).\nThe default basemap is \"Stamen Terrain\".\nYou can specify a different basemap using the `source` parameter.\nThe possible values are given in the `cx.providers`.\nAlso check out the [gallery](https://xyzservices.readthedocs.io/en/stable/gallery.html).\nFinally, custom basemaps (such as from your own raster tile server) can be specified using a [URL](https://contextily.readthedocs.io/en/latest/providers_deepdive.html#Manually-specifying-a-provider).\nFor example (@fig-basemap):\n\n::: {#fig-basemap .cell layout-ncol='3' execution_count=23}\n``` {.python .cell-code}\n# Stamen Terrain\nfig, ax = plt.subplots(figsize=(7, 7))\nax = nzw.plot(color='none', ax=ax)\ncx.add_basemap(ax);\n\n# OpenStreetMap\nfig, ax = plt.subplots(figsize=(7, 7))\nax = nzw.plot(color='none', ax=ax)\ncx.add_basemap(ax, source=cx.providers.OpenStreetMap.Mapnik);\n\n# CartoDB.Positron\nfig, ax = plt.subplots(figsize=(7, 7))\nax = nzw.plot(color='none', ax=ax)\ncx.add_basemap(ax, source=cx.providers.CartoDB.Positron);\n```\n\n::: {.cell-output .cell-output-display}\n!['Stamen Terrain' basemap (the default)](08-mapping_files/figure-html/fig-basemap-output-1.png){#fig-basemap-1 width=519 height=590}\n:::\n\n::: {.cell-output .cell-output-display}\n!['OpenStreetMap' basemap](08-mapping_files/figure-html/fig-basemap-output-2.png){#fig-basemap-2 width=519 height=590}\n:::\n\n::: {.cell-output .cell-output-display}\n!['CartoDB Positron' basemap](08-mapping_files/figure-html/fig-basemap-output-3.png){#fig-basemap-3 width=519 height=590}\n:::\n\nAdding a basemap to a static map, using `contextily`\n:::\n\n\nCheck out the [Adding a background map to plots](https://geopandas.org/en/stable/gallery/plotting_basemap_background.html) tutorial for more examples.\n\n### Faceted maps\n\nFaceted maps are multiple maps displaying the same symbology for the same spatial layers, but with different data in each panel.\nThe data displayed in the different panels typically refer to different properties, or time steps.\nFor example, the `nz` layer has several different properties for each polygon, stored as separate attributes:\n\n::: {.cell execution_count=24}\n``` {.python .cell-code}\nvars = ['Land_area', 'Population', 'Median_income', 'Sex_ratio']\nnz[vars]\n```\n\n::: {.cell-output .cell-output-display execution_count=437}\n```{=html}\n
\n\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n \n
Land_areaPopulationMedian_incomeSex_ratio
012500.561149175500.0234000.942453
14941.5725571657200.0296000.944286
223900.036383460100.0279000.952050
...............
139615.97603551100.0257000.971898
14422.19524251400.0272000.925967
1510457.74548546200.0279000.957792
\n

16 rows × 4 columns

\n
\n```\n:::\n:::\n\n\nWe may want to plot them all in a faceted map, that is, four small maps of `nz` with the different variables.\nTo do that, we initialize the plot with the right number of panels, such as `ncols=len(vars)` if we wish to have one row and four columns, and then go over the variables in a `for` loop, each time plotting `vars[i]` into the `ax[i]` panel (@fig-faceted-map):\n\n::: {.cell execution_count=25}\n``` {.python .cell-code}\nfig, ax = plt.subplots(ncols=4, figsize=(9, 2))\nfor i in range(len(vars)):\n nz.plot(ax=ax[i], column=vars[i], legend=True)\n ax[i].set_title(vars[i])\n```\n\n::: {.cell-output .cell-output-display}\n![Faceted map, four different variables of `nz`](08-mapping_files/figure-html/fig-faceted-map-output-1.png){#fig-faceted-map width=730 height=226}\n:::\n:::\n\n\nIn case we prefer a specific layout, rather than one row or one column, we can:\n\n- initialize the required number or rows and columns, as in `plt.subplots(nrows,ncols)`,\n- \"flatten\" `ax`, so that the facets are still accessible using a single index `ax[i]` (rather than the default `ax[i][j]`), and\n- plot into `ax[i]`\n\nFor example, here is how we can reproduce the last plot, this time in a $2 \\times 2$ layout, instead of a $1 \\times 4$ layout (@fig-faceted-map2).\nOne more modification we are doing here is hiding the axis ticks and labels, to make the map less \"crowded\", using `ax[i].xaxis.set_visible(False)` (and same for `.yaxis`):\n\n::: {.cell execution_count=26}\n``` {.python .cell-code}\nfig, ax = plt.subplots(ncols=2, nrows=int(len(vars)/2), figsize=(6, 6))\nax = ax.flatten()\nfor i in range(len(vars)):\n nz.plot(ax=ax[i], column=vars[i], legend=True)\n ax[i].set_title(vars[i])\n ax[i].xaxis.set_visible(False)\n ax[i].yaxis.set_visible(False)\n```\n\n::: {.cell-output .cell-output-display}\n![2D layout in a faceted map, using a `for` loop](08-mapping_files/figure-html/fig-faceted-map2-output-1.png){#fig-faceted-map2 width=466 height=487}\n:::\n:::\n\n\nIt is also possible to \"manually\" specify the properties of each panel, and which row/column it goes in (e.g., @fig-spatial-aggregation-different-functions).\nThis can be useful when the various panels have different components, or even completely different types of plots (e.g., @fig-zion-transect), making automation with a `for` loop less applicable.\nFor example, here is a plot similar to @fig-faceted-map2, but specifying each panel using a separate expression instead of using a `for` loop (@fig-faceted-map3):\n\n::: {.cell execution_count=27}\n``` {.python .cell-code}\nfig, ax = plt.subplots(ncols=2, nrows=int(len(vars)/2), figsize=(6, 6))\nnz.plot(ax=ax[0][0], column=vars[0], legend=True)\nax[0][0].set_title(vars[0])\nnz.plot(ax=ax[0][1], column=vars[1], legend=True)\nax[0][1].set_title(vars[1])\nnz.plot(ax=ax[1][0], column=vars[2], legend=True)\nax[1][0].set_title(vars[2])\nnz.plot(ax=ax[1][1], column=vars[3], legend=True)\nax[1][1].set_title(vars[3]);\n```\n\n::: {.cell-output .cell-output-display}\n![2D layout in a faceted map, using \"manual\" specification of the panels](08-mapping_files/figure-html/fig-faceted-map3-output-1.png){#fig-faceted-map3 width=501 height=522}\n:::\n:::\n\n\nSee the first code section in @sec-exporting-static-maps for another example of manual panel contents specification.\n\n### Exporting static maps {#sec-exporting-static-maps}\n\nStatic maps can be exported to a file using the [`matplotlib.pyplot.savefig`](https://matplotlib.org/stable/api/_as_gen/matplotlib.pyplot.savefig.html) function.\nFor example, the following code section recreates @fig-read-shp-query (see previous Chapter), but this time the last expression saves the image to a JPG image named `plot_geopandas.jpg`:\n\n::: {.cell execution_count=28}\n``` {.python .cell-code}\nfig, axes = plt.subplots(ncols=2, figsize=(9,5))\ntanzania.plot(ax=axes[0], color='lightgrey', edgecolor='grey')\ntanzania_neigh.plot(ax=axes[1], color='lightgrey', edgecolor='grey')\ntanzania_buf.plot(ax=axes[1], color='none', edgecolor='red')\naxes[0].set_title('where')\naxes[1].set_title('mask')\ntanzania.apply(lambda x: axes[0].annotate(text=x['name_long'], xy=x.geometry.centroid.coords[0], ha='center'), axis=1)\ntanzania_neigh.apply(lambda x: axes[1].annotate(text=x['name_long'], xy=x.geometry.centroid.coords[0], ha='center'), axis=1);\nplt.savefig('output/plot_geopandas.jpg')\n```\n:::\n\n\nFigures with rasters can be exported exactly the same way.\nFor example, the following code section (@sec-plot-static-layers) creates an image of a raster and a vector layer, which is then exported to a file named `plot_rasterio.jpg`:\n\n::: {.cell execution_count=29}\n``` {.python .cell-code}\nfig, ax = plt.subplots(figsize=(5, 5))\nrasterio.plot.show(nz_elev, ax=ax)\nnz.to_crs(nz_elev.crs).plot(ax=ax, facecolor='none', edgecolor='r');\nplt.savefig('output/plot_rasterio.jpg')\n```\n:::\n\n\nImage file properties can be controlled through the `plt.subplots` and `plt.savefig` parameters.\nFor example, the following code section exports the same raster plot to a file named `plot_rasterio2.svg`, which has different dimensions (width = 5 $in$, height = 7 $in$), a different format (SVG), and different resolution (300 $DPI$:)\n\n::: {.cell execution_count=30}\n``` {.python .cell-code}\nfig, ax = plt.subplots(figsize=(5, 7))\nrasterio.plot.show(nz_elev, ax=ax)\nnz.to_crs(nz_elev.crs).plot(ax=ax, facecolor='none', edgecolor='r');\nplt.savefig('output/plot_rasterio2.svg', dpi=300)\n```\n:::\n\n\n\n\n## Interactive maps {#sec-interactive-maps}\n\n### Minimal example\n\nAn interactive map of a `GeoSeries` or `GeoDataFrame` can be created with `.explore` (@sec-vector-layers).\nHere is a minimal example:\n\n::: {.cell execution_count=31}\n``` {.python .cell-code}\nnz.explore()\n```\n\n::: {#fig-explore .cell-output .cell-output-display execution_count=444}\n```{=html}\n
Make this Notebook Trusted to load map: File -> Trust Notebook
\n```\n\nMinimal example of an interactive vector layer plot with `.explore`\n:::\n:::\n\n\n### Styling\n\nThe `.explore` method has a `color` parameter which affects both the fill and outline color.\nOther styling properties are specified using a `dict` through `style_kwds` (for general properties) and the `marker_kwds` (point-layer specific properties), as follows.\n\nThe `style_kwds` keys are mostly used to control the color and opacity of the outline and the fill:\n\n- `stroke`---Whether to draw the outline\n- `color`---Outline color\n- `weight`---Outline width (in pixels)\n- `opacity`---Outline opacity (from `0` to `1`)\n- `fill`---Whether to draw fill\n- `fillColor`---Fill color\n- `fillOpacity`---Fill opacity (from `0` to `1`)\n\nFor example, here is how we can set green fill color and 30% opaque black outline of `nz` polygons in `.explore` (@fig-explore-styling-polygons):\n\n::: {.cell execution_count=32}\n``` {.python .cell-code}\nnz.explore(color='green', style_kwds={'color':'black', 'opacity':0.3})\n```\n\n::: {#fig-explore-styling-polygons .cell-output .cell-output-display execution_count=445}\n```{=html}\n
Make this Notebook Trusted to load map: File -> Trust Notebook
\n```\n\nStyling of polygons in `.explore`\n:::\n:::\n\n\nThe `dict` passed to `marker_kwds` controls the way that points are displayed:\n\n- `radius`---Curcle radius (in $m$ for `circle`, see below) or in pixels (for `circle_marker`)\n- `fill`---Whether to draw fill (for `circle` or `circle_marker`)\n\nAdditionally, for points, we can set the `marker_type`, to one of:\n\n- `'marker'`---A PNG image of a marker\n- `'circle'`---A vector circle with radius specified in $m$\n- `'circle_marker'`---A vector circle with radius specified in pixels (the default)\n\nFor example, the following expression draws `'circe_marker`' points with 20 pixel radius, green fill, and black outline (@fig-explore-styling-points):\n\n::: {.cell execution_count=33}\n``` {.python .cell-code}\nnz_height.explore(\n color='green', \n style_kwds={'color':'black', 'opacity':0.5, 'fillOpacity':0.1}, \n marker_kwds={'color':'black', 'radius':20}\n)\n```\n\n::: {#fig-explore-styling-points .cell-output .cell-output-display execution_count=446}\n```{=html}\n
Make this Notebook Trusted to load map: File -> Trust Notebook
\n```\n\nStyling of points in `.explore` (using `circle_marker`)\n:::\n:::\n\n\nThe following expression demonstrates the `'marker'` option (@fig-explore-styling-points2).\nNote that the above-mentioned styling properties (other then `opacity`) are not applicable when using `marker_type='marker'`, because the markers are fixed PNG images:\n\n::: {.cell execution_count=34}\n``` {.python .cell-code}\nnz_height.explore(marker_type='marker')\n```\n\n::: {#fig-explore-styling-points2 .cell-output .cell-output-display execution_count=447}\n```{=html}\n
Make this Notebook Trusted to load map: File -> Trust Notebook
\n```\n\nStyling of points in `.explore` (using `marker`)\n:::\n:::\n\n\n### Layers\n\nTo display multiple layers, one on top of another, with `.explore`, we use the `m` argument, which stands for the previous map (@fig-explore-layers):\n\n::: {.cell execution_count=35}\n``` {.python .cell-code}\nm = nz.explore()\nnz_height.explore(m=m, color='red')\n```\n\n::: {#fig-explore-layers .cell-output .cell-output-display execution_count=448}\n```{=html}\n
Make this Notebook Trusted to load map: File -> Trust Notebook
\n```\n\nDisplaying multiple layers in an interactive map with `.explore`\n:::\n:::\n\n\nOne of the advantages of interactive maps is the ability to turn layers \"on\" and \"off\".\nThis capability is implemented in [`folium.LayerControl`](https://python-visualization.github.io/folium/latest/user_guide/ui_elements/layer_control.html#LayerControl) from package **folium**, which the **geopandas** `.explore` method is a wrapper of.\nFor example, this is how we can add a layer control for the `nz` and `nz_height` layers (@fig-explore-layers-controls).\nNote the `name` properties, used to specify layer names in the control, and the `collapsed` property, used to specify whether the control is fully visible at all times (`False`), or on mouse hover (`True`, the default):\n\n::: {.cell execution_count=36}\n``` {.python .cell-code}\nm = nz.explore(name='Polygons (adm. areas)')\nnz_height.explore(m=m, color='red', name='Points (elevation)')\nfolium.LayerControl(collapsed=False).add_to(m)\nm\n```\n\n::: {#fig-explore-layers-controls .cell-output .cell-output-display execution_count=449}\n```{=html}\n
Make this Notebook Trusted to load map: File -> Trust Notebook
\n```\n\nDisplaying multiple layers in an interactive map with `.explore`\n:::\n:::\n\n\n### Symbology {#sec-explore-symbology}\n\nSymbology can be specified in `.explore` using similar arguments as in `.plot` (@sec-plot-symbology).\nFor example, here is an interactive version of @fig-plot-symbology-colors (a).\n\n::: {.cell execution_count=37}\n``` {.python .cell-code}\nnz.explore(column='Median_income', legend=True, cmap='Reds')\n```\n\n::: {#fig-explore-symbology .cell-output .cell-output-display execution_count=450}\n```{=html}\n
Make this Notebook Trusted to load map: File -> Trust Notebook
\n```\n\nSymbology in an interactive map of a vector layer, created with `.explore`\n:::\n:::\n\n\nFixed styling (@sec-explore-symbology) can be combined with symbology settings.\nFor example, polygon outline colors in @fig-explore-symbology are styled according to `'Median_income'`, however, this layer has overlapping outlines and the color is arbitrarily set according to the order of features (top-most features), which may be misleading and confusing.\nTo specify fixed outline colors (e.g., black), we can use the `color` and `weight` properties of `style_kwds` (@fig-explore-symbology2):\n\n::: {.cell execution_count=38}\n``` {.python .cell-code}\nnz.explore(column='Median_income', legend=True, cmap='Reds', style_kwds={'color':'black', 'weight': 0.5})\n```\n\n::: {#fig-explore-symbology2 .cell-output .cell-output-display execution_count=451}\n```{=html}\n
Make this Notebook Trusted to load map: File -> Trust Notebook
\n```\n\nSymbology combined with fixed styling in `.explore`\n:::\n:::\n\n\n### Basemaps\n\nThe basemap in `.explore` can be specified using the `tiles` argument.\nSeveral popular built-in basemaps can be specified using a string:\n\n- `'OpenStreetMap'`\n- `'Stamen Terrain'`\n- `'Stamen Toner'`\n- `'Stamen Watercolor'`\n- `'CartoDB positron'`\n- `'CartoDB dark_matter'`\n\nOther basemaps are available through the **xyzservices** package, which needs to be installed (see `xyzservices.providers` for a list), or using a custom tile server URL.\n\nFor example, the following expression displays the `'CartoDB positron'` tiles in an `.explore` map (@fig-explore-basemaps):\n\n::: {.cell execution_count=39}\n``` {.python .cell-code}\nnz.explore(tiles='CartoDB positron')\n```\n\n::: {#fig-explore-basemaps .cell-output .cell-output-display execution_count=452}\n```{=html}\n
Make this Notebook Trusted to load map: File -> Trust Notebook
\n```\n\nSpecifying the basemap in `.explore`\n:::\n:::\n\n\n### Exporting interactive maps\n\nAn interactive map can be exported to an HTML file using the `.save` method of the `map` object.\nThe HTML file can then be shared with other people, or published on a server and shared through a URL.\nA good free option for publishing a web map is [GitHub Pages](https://pages.github.com/).\n\nFor example, here is how we can export the map shown in @fig-explore-layers-controls, to a file named `map.html`:\n\n::: {.cell execution_count=40}\n``` {.python .cell-code}\nm = nz.explore(name='Polygons (adm. areas)')\nnz_height.explore(m=m, color='red', name='Points (elevation)')\nfolium.LayerControl(collapsed=False).add_to(m)\nm.save('output/map.html')\n```\n:::\n\n\n\n\n\n\n## Exercises\n\n## References\n\n", + "supporting": [ + "08-mapping_files" + ], + "filters": [], + "includes": { + "include-in-header": [ + "\n\n\n" + ] + } + } +} \ No newline at end of file diff --git a/08-mapping_files/figure-html/cell-16-output-1.png b/08-mapping_files/figure-html/cell-16-output-1.png new file mode 100644 index 00000000..c055f422 Binary files /dev/null and b/08-mapping_files/figure-html/cell-16-output-1.png differ diff --git a/08-mapping_files/figure-html/cell-17-output-1.png b/08-mapping_files/figure-html/cell-17-output-1.png new file mode 100644 index 00000000..0274af90 Binary files /dev/null and b/08-mapping_files/figure-html/cell-17-output-1.png differ diff --git a/08-mapping_files/figure-html/cell-19-output-1.png b/08-mapping_files/figure-html/cell-19-output-1.png new file mode 100644 index 00000000..9536662b Binary files /dev/null and b/08-mapping_files/figure-html/cell-19-output-1.png differ diff --git a/08-mapping_files/figure-html/cell-19-output-2.png b/08-mapping_files/figure-html/cell-19-output-2.png new file mode 100644 index 00000000..853e621e Binary files /dev/null and b/08-mapping_files/figure-html/cell-19-output-2.png differ diff --git a/08-mapping_files/figure-html/cell-19-output-3.png b/08-mapping_files/figure-html/cell-19-output-3.png new file mode 100644 index 00000000..853e621e Binary files /dev/null and b/08-mapping_files/figure-html/cell-19-output-3.png differ diff --git a/08-mapping_files/figure-html/fig-basemap-output-1.png b/08-mapping_files/figure-html/fig-basemap-output-1.png new file mode 100644 index 00000000..886c06ec Binary files /dev/null and b/08-mapping_files/figure-html/fig-basemap-output-1.png differ diff --git a/08-mapping_files/figure-html/fig-basemap-output-2.png b/08-mapping_files/figure-html/fig-basemap-output-2.png new file mode 100644 index 00000000..7796f2b0 Binary files /dev/null and b/08-mapping_files/figure-html/fig-basemap-output-2.png differ diff --git a/08-mapping_files/figure-html/fig-basemap-output-3.png b/08-mapping_files/figure-html/fig-basemap-output-3.png new file mode 100644 index 00000000..9037d46f Binary files /dev/null and b/08-mapping_files/figure-html/fig-basemap-output-3.png differ diff --git a/08-mapping_files/figure-html/fig-basic-plot-markersize-output-1.png b/08-mapping_files/figure-html/fig-basic-plot-markersize-output-1.png new file mode 100644 index 00000000..4adce4df Binary files /dev/null and b/08-mapping_files/figure-html/fig-basic-plot-markersize-output-1.png differ diff --git a/08-mapping_files/figure-html/fig-basic-plot-output-1.png b/08-mapping_files/figure-html/fig-basic-plot-output-1.png new file mode 100644 index 00000000..1492151a Binary files /dev/null and b/08-mapping_files/figure-html/fig-basic-plot-output-1.png differ diff --git a/08-mapping_files/figure-html/fig-basic-plot-output-2.png b/08-mapping_files/figure-html/fig-basic-plot-output-2.png new file mode 100644 index 00000000..6c7213dd Binary files /dev/null and b/08-mapping_files/figure-html/fig-basic-plot-output-2.png differ diff --git a/08-mapping_files/figure-html/fig-basic-plot-output-3.png b/08-mapping_files/figure-html/fig-basic-plot-output-3.png new file mode 100644 index 00000000..2afacff8 Binary files /dev/null and b/08-mapping_files/figure-html/fig-basic-plot-output-3.png differ diff --git a/08-mapping_files/figure-html/fig-faceted-map-output-1.png b/08-mapping_files/figure-html/fig-faceted-map-output-1.png new file mode 100644 index 00000000..2afbdbe7 Binary files /dev/null and b/08-mapping_files/figure-html/fig-faceted-map-output-1.png differ diff --git a/08-mapping_files/figure-html/fig-faceted-map2-output-1.png b/08-mapping_files/figure-html/fig-faceted-map2-output-1.png new file mode 100644 index 00000000..8650e818 Binary files /dev/null and b/08-mapping_files/figure-html/fig-faceted-map2-output-1.png differ diff --git a/08-mapping_files/figure-html/fig-faceted-map3-output-1.png b/08-mapping_files/figure-html/fig-faceted-map3-output-1.png new file mode 100644 index 00000000..dafb6a49 Binary files /dev/null and b/08-mapping_files/figure-html/fig-faceted-map3-output-1.png differ diff --git a/08-mapping_files/figure-html/fig-labels-points1-output-1.png b/08-mapping_files/figure-html/fig-labels-points1-output-1.png new file mode 100644 index 00000000..596d2083 Binary files /dev/null and b/08-mapping_files/figure-html/fig-labels-points1-output-1.png differ diff --git a/08-mapping_files/figure-html/fig-labels-points2-output-1.png b/08-mapping_files/figure-html/fig-labels-points2-output-1.png new file mode 100644 index 00000000..596d2083 Binary files /dev/null and b/08-mapping_files/figure-html/fig-labels-points2-output-1.png differ diff --git a/08-mapping_files/figure-html/fig-labels-polygon-output-1.png b/08-mapping_files/figure-html/fig-labels-polygon-output-1.png new file mode 100644 index 00000000..0274af90 Binary files /dev/null and b/08-mapping_files/figure-html/fig-labels-polygon-output-1.png differ diff --git a/08-mapping_files/figure-html/fig-plot-legend-pos-output-1.png b/08-mapping_files/figure-html/fig-plot-legend-pos-output-1.png new file mode 100644 index 00000000..93fb9166 Binary files /dev/null and b/08-mapping_files/figure-html/fig-plot-legend-pos-output-1.png differ diff --git a/08-mapping_files/figure-html/fig-plot-raster-and-vector-output-1.png b/08-mapping_files/figure-html/fig-plot-raster-and-vector-output-1.png new file mode 100644 index 00000000..d076b8e1 Binary files /dev/null and b/08-mapping_files/figure-html/fig-plot-raster-and-vector-output-1.png differ diff --git a/08-mapping_files/figure-html/fig-plot-raster-and-vector-output-2.png b/08-mapping_files/figure-html/fig-plot-raster-and-vector-output-2.png new file mode 100644 index 00000000..9a2ce805 Binary files /dev/null and b/08-mapping_files/figure-html/fig-plot-raster-and-vector-output-2.png differ diff --git a/08-mapping_files/figure-html/fig-plot-raster-and-vector-output-3.png b/08-mapping_files/figure-html/fig-plot-raster-and-vector-output-3.png new file mode 100644 index 00000000..db1adb3f Binary files /dev/null and b/08-mapping_files/figure-html/fig-plot-raster-and-vector-output-3.png differ diff --git a/08-mapping_files/figure-html/fig-plot-symbology-categorical-output-1.png b/08-mapping_files/figure-html/fig-plot-symbology-categorical-output-1.png new file mode 100644 index 00000000..ceacbb91 Binary files /dev/null and b/08-mapping_files/figure-html/fig-plot-symbology-categorical-output-1.png differ diff --git a/08-mapping_files/figure-html/fig-plot-symbology-colors-output-1.png b/08-mapping_files/figure-html/fig-plot-symbology-colors-output-1.png new file mode 100644 index 00000000..5e1e445d Binary files /dev/null and b/08-mapping_files/figure-html/fig-plot-symbology-colors-output-1.png differ diff --git a/08-mapping_files/figure-html/fig-plot-symbology-colors-output-2.png b/08-mapping_files/figure-html/fig-plot-symbology-colors-output-2.png new file mode 100644 index 00000000..af4ef91c Binary files /dev/null and b/08-mapping_files/figure-html/fig-plot-symbology-colors-output-2.png differ diff --git a/08-mapping_files/figure-html/fig-plot-symbology-colors-output-3.png b/08-mapping_files/figure-html/fig-plot-symbology-colors-output-3.png new file mode 100644 index 00000000..840b5642 Binary files /dev/null and b/08-mapping_files/figure-html/fig-plot-symbology-colors-output-3.png differ diff --git a/08-mapping_files/figure-html/fig-plot-symbology-colors-r-output-1.png b/08-mapping_files/figure-html/fig-plot-symbology-colors-r-output-1.png new file mode 100644 index 00000000..8809f840 Binary files /dev/null and b/08-mapping_files/figure-html/fig-plot-symbology-colors-r-output-1.png differ diff --git a/08-mapping_files/figure-html/fig-plot-symbology-colors-r-output-2.png b/08-mapping_files/figure-html/fig-plot-symbology-colors-r-output-2.png new file mode 100644 index 00000000..fa6b5e11 Binary files /dev/null and b/08-mapping_files/figure-html/fig-plot-symbology-colors-r-output-2.png differ diff --git a/08-mapping_files/figure-html/fig-plot-symbology-colors-r-output-3.png b/08-mapping_files/figure-html/fig-plot-symbology-colors-r-output-3.png new file mode 100644 index 00000000..6fd77671 Binary files /dev/null and b/08-mapping_files/figure-html/fig-plot-symbology-colors-r-output-3.png differ diff --git a/08-mapping_files/figure-html/fig-plot-symbology-colors-r-scale-output-1.png b/08-mapping_files/figure-html/fig-plot-symbology-colors-r-scale-output-1.png new file mode 100644 index 00000000..40ca1f9d Binary files /dev/null and b/08-mapping_files/figure-html/fig-plot-symbology-colors-r-scale-output-1.png differ diff --git a/08-mapping_files/figure-html/fig-plot-symbology-output-1.png b/08-mapping_files/figure-html/fig-plot-symbology-output-1.png new file mode 100644 index 00000000..50f0f8d1 Binary files /dev/null and b/08-mapping_files/figure-html/fig-plot-symbology-output-1.png differ diff --git a/08-mapping_files/figure-html/fig-raster-minimal-output-1.png b/08-mapping_files/figure-html/fig-raster-minimal-output-1.png new file mode 100644 index 00000000..d0088531 Binary files /dev/null and b/08-mapping_files/figure-html/fig-raster-minimal-output-1.png differ diff --git a/08-mapping_files/figure-html/fig-two-layers-output-1.png b/08-mapping_files/figure-html/fig-two-layers-output-1.png new file mode 100644 index 00000000..5aad5703 Binary files /dev/null and b/08-mapping_files/figure-html/fig-two-layers-output-1.png differ diff --git a/08-mapping_files/figure-html/fig-vector-minimal-output-1.png b/08-mapping_files/figure-html/fig-vector-minimal-output-1.png new file mode 100644 index 00000000..251d95b6 Binary files /dev/null and b/08-mapping_files/figure-html/fig-vector-minimal-output-1.png differ