From feacb4713365deb8f79fdb951bbc9cf1271fe446 Mon Sep 17 00:00:00 2001 From: Robinlovelace Date: Wed, 25 Sep 2024 12:52:31 +0000 Subject: [PATCH] Deploy commit: improves 09 (#1125) 8e5af760462e04f2f99309c5e84a9f03c9202511 --- 09-mapping.md | 171 +++++++++++++++-------------- 13-transport.md | 3 +- adv-map.html | 172 +++++++++++++++--------------- figures/circle-intersection-1.png | Bin 13642 -> 13642 bytes figures/cycleways-1.png | Bin 133768 -> 107988 bytes figures/points-1.png | Bin 15698 -> 15698 bytes figures/rnetvis-1.png | Bin 51765 -> 53514 bytes figures/rnetvis-2.png | Bin 60980 -> 44331 bytes figures/routes-1.png | Bin 163794 -> 130691 bytes figures/wayssln-1.png | Bin 141017 -> 116559 bytes search.json | 2 +- transport.html | 5 +- 12 files changed, 176 insertions(+), 177 deletions(-) diff --git a/09-mapping.md b/09-mapping.md index b1f09575d..597464629 100644 --- a/09-mapping.md +++ b/09-mapping.md @@ -35,7 +35,7 @@ library(leaflet) # for interactive maps library(ggplot2) # tidyverse data visualization package ``` -- You also need to read in a couple of datasets as follows for Section \@ref(spatial-ras): +- You also need to read-in a couple of datasets as follows for Section \@ref(spatial-ras): ``` r @@ -54,7 +54,7 @@ Map-making is no exception, hence this chapter's coverage of one package (**tmap In addition to being fun and creative, cartography also has important practical applications. A carefully crafted map can be the best way of communicating the results of your work, but poorly designed maps can leave a bad impression. -Common design issues include poor placement, size and readability of text and careless selection of colors, as outlined in the style [guide](https://files.taylorandfrancis.com/TJOM-suppmaterial-quick-guide.pdf) of the Journal of Maps. +Common design issues include poor placement, size and readability of text and careless selection of colors, as outlined in the [style guide](https://files.taylorandfrancis.com/TJOM-suppmaterial-quick-guide.pdf) of the *Journal of Maps*. Furthermore, poor map-making can hinder the communication of results [@brewer_designing_2015]: > Amateur-looking maps can undermine your audience’s ability to understand important information and weaken the presentation of a professional data investigation. @@ -62,9 +62,9 @@ Maps have been used for several thousand years for a wide variety of purposes. Historic 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*\index{geography} nearly 2000 years ago [@talbert_ancient_2014]. Map-making has historically been an activity undertaken only by, or on behalf of, the elite. -This has changed with the emergence of open source mapping software such as the R package **tmap** and the 'print layout' in QGIS\index{QGIS} which enable anyone to make high-quality maps, enabling 'citizen science'. +This has changed with the emergence of open source mapping software such as the R package **tmap** and the 'print layout' in QGIS\index{QGIS}, which allow anyone to make high-quality maps, enabling 'citizen science'. Maps are also often the best way to present the findings of geocomputational research in a way that is accessible. -Map-making is therefore a critical part of geocomputation\index{geocomputation} and its emphasis not only on describing, but also *changing* the world. +Map-making is therefore a critical part of geocomputation\index{geocomputation} and its emphasis is not only on describing, but also *changing* the world. This chapter shows how to make a wide range of maps. The next section covers a range of static maps, including aesthetic considerations, facets and inset maps. @@ -80,10 +80,10 @@ Initially, static maps were the only type of maps that R could produce. Things have advanced with the release of **sp** [see @pebesma_classes_2005], and many map-making techniques, functions, and packages have been developed since then. However, despite the innovation of interactive mapping, static plotting was still the emphasis of geographic data visualization in R a decade later [@cheshire_spatial_2015]. -The generic `plot()` function is often the fastest way to create static maps from vector and raster spatial objects (see sections \@ref(basic-map) and \@ref(basic-map-raster)). +The generic `plot()` function is often the fastest way to create static maps from vector and raster spatial objects (see Sections \@ref(basic-map) and \@ref(basic-map-raster)). Sometimes, simplicity and speed are priorities, especially during the development phase of a project, and this is where `plot()` excels. The base R approach is also extensible, with `plot()` offering dozens of arguments. -Another approach is the **grid** package which allows low-level control of static maps, as illustrated in Chapter [14](https://www.stat.auckland.ac.nz/~paul/RG2e/chapter14.html) of @murrell_r_2016. +Another approach is the **grid** package which allows low-level control of static maps, as illustrated in chapter [14](https://www.stat.auckland.ac.nz/~paul/RG2e/chapter14.html) of @murrell_r_2016. This part of the book focuses on **tmap** and emphasizes the essential aesthetic and layout options. \index{tmap (package)} @@ -127,13 +127,13 @@ This is an intuitive approach to map-making: the common task of *adding* new layers is undertaken by the addition operator `+`, followed by `tm_*()`. The asterisk (\*) refers to a wide range of layer types which have self-explanatory names including: -- `tm_fill()`: shaded areas for (mutli)polygons -- `tm_borders()`: border outlines for (mutli)polygons -- `tm_polygons()`: both, shaded areas and border outlines for (mutli)polygons -- `tm_lines()`: lines for (mutli)linestrings -- `tm_symbols()`: symbols for (mutli)points, (mutli)linestrings, and (mutli)polygons +- `tm_fill()`: shaded areas for (multi)polygons +- `tm_borders()`: border outlines for (multi)polygons +- `tm_polygons()`: both, shaded areas and border outlines for (multi)polygons +- `tm_lines()`: lines for (multi)linestrings +- `tm_symbols()`: symbols for (multi)points, (multi)linestrings, and (multi)polygons - `tm_raster()`: colored cells of raster data (there is also `tm_rgb()` for rasters with three layers) -- `tm_text()`: text information for (mutli)points, (mutli)linestrings, and (mutli)polygons +- `tm_text()`: text information for (multi)points, (multi)linestrings, and (multi)polygons This layering is illustrated in the right panel of Figure \@ref(fig:tmshape), the result of adding a border *on top of* the fill layer. @@ -155,7 +155,7 @@ class(map_nz) #> [1] "tmap" ``` -`map_nz` can be plotted later, for example by adding additional layers (as shown below) or simply running `map_nz` in the console, which is equivalent to `print(map_nz)`. +`map_nz` can be plotted later, for example by adding other layers (as shown below) or simply running `map_nz` in the console, which is equivalent to `print(map_nz)`. New *shapes* can be added with `+ tm_shape(new_obj)`. In this case, `new_obj` represents a new spatial object to be plotted on top of preceding layers. @@ -200,8 +200,8 @@ tmap_arrange(map_nz1, map_nz2, map_nz3) ```
-Maps with additional layers added to the final map of Figure 9.1. -

(\#fig:tmlayers)Maps with additional layers added to the final map of Figure 9.1.

+Maps with added layers to the final map of Figure 9.1. +

(\#fig:tmlayers)Maps with added layers to the final map of Figure 9.1.

More elements can also be added with the `+` operator. @@ -246,8 +246,8 @@ tmap_arrange(ma1, ma2, ma3, ma4, ma5, ma6) ```
-The impact of changing commonly used fill and border aesthetics to fixed values. -

(\#fig:tmstatic)The impact of changing commonly used fill and border aesthetics to fixed values.

+Impact of changing commonly used fill and border aesthetics to fixed values. +

(\#fig:tmstatic)Impact of changing commonly used fill and border aesthetics to fixed values.

Like base R plots, arguments defining aesthetics can also receive values that vary. @@ -281,7 +281,7 @@ The `.free` argument is relevant only for maps with many facets to determine if ### Scales \index{tmap (package)!scales} -Scales control how the values are represented on the map and in the legend, and largely depend on the selected visual variable. +Scales control how the values are represented on the map and in the legend, and they largely depend on the selected visual variable. For example, when our visual variable is `col`, then `col.scale` controls how the colors of spatial objects are related to the provided values; and when our visual variable is `size`, then `size.scale` controls how the sizes represent the provided values. By default, the used scale is `tm_scale()`, which selects the visual settings automatically given by the input data type (factor, numeric, and integer). @@ -307,8 +307,8 @@ tm_shape(nz) + tm_polygons(fill = "Median_income", ```
-Illustration of settings that affect color settings. The results show (from left to right): default settings, manual breaks, n breaks, and the impact of changing the palette. -

(\#fig:tmpal)Illustration of settings that affect color settings. The results show (from left to right): default settings, manual breaks, n breaks, and the impact of changing the palette.

+Illustration of color settings. The results show (from left to right): default settings, manual breaks, n breaks, and the impact of changing the palette. +

(\#fig:tmpal)Illustration of color settings. The results show (from left to right): default settings, manual breaks, n breaks, and the impact of changing the palette.

\BeginKnitrBlock{rmdnote}
All of the above arguments (`breaks`, `n`, and `values`) also work for other types of visual variables. @@ -326,7 +326,7 @@ In addition to manually setting `breaks`, **tmap** allows users to specify algor The default is `tm_scale_intervals(style = "pretty")`, which rounds breaks into whole numbers where possible and spaces them evenly. Other options are listed below and presented in Figure \@ref(fig:break-styles). -- `style = "equal"`: divides input values into bins of equal range and is appropriate for variables with a uniform distribution (not recommended for variables with a skewed distribution as the resulting map may end-up having little color diversity) +- `style = "equal"`: divides input values into bins of equal range and is appropriate for variables with a uniform distribution (not recommended for variables with a skewed distribution as the resulting map may end up having little color diversity) - `style = "quantile"`: ensures the same number of observations fall into each category (with the potential downside that bin ranges can vary widely) - `style = "jenks"`: identifies groups of similar values in the data and maximizes the differences between categories - `style = "log10_pretty"`: a common logarithmic (the logarithm to base 10) version of the regular pretty style used for variables with a right-skewed distribution @@ -334,28 +334,28 @@ Other options are listed below and presented in Figure \@ref(fig:break-styles). \BeginKnitrBlock{rmdnote}
Although `style` is an argument of **tmap** functions, in fact it originates as an argument in `classInt::classIntervals()` --- see the help page of this function for details.
\EndKnitrBlock{rmdnote}
-Illustration of different interval scales' methods set using the style argument in tmap. -

(\#fig:break-styles)Illustration of different interval scales' methods set using the style argument in tmap.

+Different interval scale methods set using the style argument in tmap. +

(\#fig:break-styles)Different interval scale methods set using the style argument in tmap.

\index{tmap (package)!continuous scale} The `tm_scale_continuous()` function presents a continuous color field and is particularly suited for continuous rasters (Figure \@ref(fig:concat), left panel). -In case of variables with skewed distribution you can also use its variants -- `tm_scale_continuous_log()` and `tm_scale_continuous_log1p()`. +In case of variables with q skewed distribution, you can also use its variants -- `tm_scale_continuous_log()` and `tm_scale_continuous_log1p()`. \index{tmap (package)!categorical scale} -Finally, `tm_scale_categorical()` was designed to represent categorical values and assures that each category receives a unique color (Figure \@ref(fig:concat), right panel). +Finally, `tm_scale_categorical()` was designed to represent categorical values and ensures that each category receives a unique color (Figure \@ref(fig:concat), right panel).
-Illustration of continuous and categorical scales in tmap. -

(\#fig:concat)Illustration of continuous and categorical scales in tmap.

+Continuous and categorical scales in tmap. +

(\#fig:concat)Continuous and categorical scales in tmap.

\index{tmap (package)!palettes} Palettes define the color ranges associated with the bins and determined by the `tm_scale_*()` functions, and its `breaks` and `n` arguments described above. -It expects a vector of colors or a new color palette name, which can be find interactively with `cols4all::c4a_gui()`. +It expects a vector of colors or a new color palette name, which can be found interactively with `cols4all::c4a_gui()`. You can also add a `-` as the color palette name prefix to reverse the palette order. \BeginKnitrBlock{rmdnote}
All of the default `values` of the visual variables, such as default color palettes for different types of input variables, can be found with `tmap_options()`. -For example run `tmap_options()$values.var`.
\EndKnitrBlock{rmdnote} +For example, run `tmap_options()$values.var`.
\EndKnitrBlock{rmdnote} \index{color palettes} There are three main groups of color palettes\index{map-making!color palettes}: categorical, sequential and diverging (Figure \@ref(fig:colpal)), and each of them serves a different purpose.^[ @@ -398,7 +398,7 @@ tm_shape(nz) + There are two important principles for consideration when working with colors: perceptibility and accessibility. Firstly, colors on maps should match our perception. This means that certain colors are viewed through our experience and also cultural lenses. -For example, green colors usually represent vegetation or lowlands and blue is connected with water or cool. +For example, green colors usually represent vegetation or lowlands, and blue is connected with water or coolness. Color palettes should also be easy to understand to effectively convey information. It should be clear which values are lower and which are higher, and colors should change gradually. Secondly, changes in colors should be accessible to the largest number of people. @@ -410,7 +410,7 @@ Therefore, it is important to use colorblind friendly palettes as often as possi After we decided on our visual variable and its properties, we should move our attention toward the related map legend style. Using the `tm_legend()` function, we may change its title, position, orientation, or even disable it. The most important argument in this function is `title`, which sets the title of the associated legend. -In general, a map legend title should provide two pieces of information: what the legend represents and what are the units of the presented variable. +In general, a map legend title should provide two pieces of information: what the legend represents and what the units are of the presented variable. The following code chunk demonstrates this functionality by providing a more attractive name than the variable name `Land_area` (note the use of `expression()` to create superscript text): @@ -448,7 +448,7 @@ Alternatively, we may just provide a vector of two values (or two numbers betwee \index{tmap (package)!layouts} The map layout refers to the combination of all map elements into a cohesive map. -Map elements include among others the objects to be mapped, the map grid, the scale bar, the title, and margins, while the color settings covered in the previous section relate to the palette and break-points used to affect how the map looks. +Map elements include among others the objects to be mapped, the map grid, the scale bar, the title, and margins, while the color settings covered in the previous section relate to the palette and breakpoints used to affect how the map looks. Both may result in subtle changes that can have an equally large impact on the impression left by your maps. Additional map elements such as graticules \index{tmap (package)!graticules}, north arrows\index{tmap (package)!north arrows}, scale bars\index{tmap (package)!scale bars} and map titles have their own functions: `tm_graticules()`, `tm_compass()`, `tm_scalebar()`, and `tm_title()` (Figure \@ref(fig:na-sb)).^[Another additional map elements include `tm_grid()`, `tm_logo()` and `tm_credits()`.] @@ -463,8 +463,8 @@ map_nz + ```
-Map with additional elements - a north arrow and scale bar. -

(\#fig:na-sb)Map with additional elements - a north arrow and scale bar.

+Map with additional elements: a north arrow and scale bar. +

(\#fig:na-sb)Map with additional elements: a north arrow and scale bar.

**tmap** also allows a wide variety of layout settings to be changed, some of which, produced using the following code (see `args(tm_layout)` or `?tm_layout` for a full list), are illustrated in Figure \@ref(fig:layout1). @@ -477,8 +477,8 @@ map_nz + tm_layout(frame = FALSE) ```
-Layout options specified by (from left to right) scale, bg.color and frame arguments. -

(\#fig:layout1)Layout options specified by (from left to right) scale, bg.color and frame arguments.

+Layout options specified by (from left to right) scale, bg.color, and frame arguments. +

(\#fig:layout1)Layout options specified by (from left to right) scale, bg.color, and frame arguments.

The other arguments in `tm_layout()` provide control over many more aspects of the map in relation to the canvas on which it is placed. @@ -491,8 +491,8 @@ Here are some useful layout settings (some of which are illustrated in Figure \@ - Color settings controlling `color.sepia.intensity` (how *yellowy* the map looks) and `color.saturation` (a color-grayscale)
-Illustration of selected layout options. -

(\#fig:layout2)Illustration of selected layout options.

+Selected layout options. +

(\#fig:layout2)Selected layout options.

### Faceted maps @@ -507,7 +507,7 @@ However, this risks cluttering the map because it will involve multiple overlapp Typically all individual facets in a faceted map contain the same geometry data repeated multiple times, once for each column in the attribute data (this is the default plotting method for `sf` objects, see Chapter \@ref(spatial-class)). However, facets can also represent shifting geometries such as the evolution of a point pattern over time. -This use case of faceted plot is illustrated in Figure \@ref(fig:urban-facet). +This use case of a faceted plot is illustrated in Figure \@ref(fig:urban-facet). ``` r @@ -528,7 +528,7 @@ tm_shape(world) + The preceding code chunk demonstrates key features of faceted maps created using the `tm_facets_wrap()` function: -- Shapes that do not have a facet variable are repeated (the countries in `world` in this case) +- Shapes that do not have a facet variable are repeated (countries in `world` in this case) - The `by` argument which varies depending on a variable (`"year"` in this case) - The `nrow`/`ncol` setting specifying the number of rows and columns that facets should be arranged into @@ -556,7 +556,7 @@ nz_region = st_bbox(c(xmin = 1340000, xmax = 1450000, st_as_sfc() ``` -In the second step, we create a base map showing the New Zealand's Southern Alps area. +In the second step, we create a base-map showing New Zealand's Southern Alps area. This is a place where the most important message is stated. @@ -629,11 +629,11 @@ print(nz_map, vp = ins_vp) ```
-Inset map providing a context - location of the central part of the Southern Alps in New Zealand. -

(\#fig:insetmap1)Inset map providing a context - location of the central part of the Southern Alps in New Zealand.

+Inset map providing a context -- location of the central part of the Southern Alps in New Zealand. +

(\#fig:insetmap1)Inset map providing a context -- location of the central part of the Southern Alps in New Zealand.

-Inset map can be saved to file either by using a graphic device (see Section \@ref(visual-outputs)) or the `tmap_save()` function and its arguments - `insets_tm` and `insets_vp`. +Inset maps can be saved to file either by using a graphic device (see Section \@ref(visual-outputs)) or the `tmap_save()` function and its arguments: `insets_tm` and `insets_vp`. Inset maps are also used to create one map of non-contiguous areas. Probably, the most often used example is a map of the United States, which consists of the contiguous United States, Hawaii and Alaska. @@ -676,7 +676,7 @@ print(alaska_map, vp = grid::viewport(0.15, 0.15, width = 0.3, height = 0.3))

(\#fig:insetmap2)Map of the United States.

-The code presented above is compact and can be used as the basis for other inset maps but the results, in Figure \@ref(fig:insetmap2), provide a poor representation of the locations and sizes of Hawaii and Alaska. +The code presented above is compact and can be used as the basis for other inset maps, but the results, in Figure \@ref(fig:insetmap2), provide a poor representation of the locations and sizes of Hawaii and Alaska. For a more in-depth approach, see the [`us-map`](https://geocompx.github.io/geocompkg/articles/us-map.html) vignette from the **geocompkg**. ## Animated maps @@ -689,7 +689,7 @@ Furthermore, the fact that each facet is physically separated on the screen or p Animated maps solve these issues. Although they depend on digital publication, this is becoming less of an issue as more and more content moves online. -Animated maps can still enhance paper reports: you can always link readers to a web-page containing an animated (or interactive) version of a printed map to help make it come alive. +Animated maps can still enhance paper reports: you can always link readers to a webpage containing an animated (or interactive) version of a printed map to help make it come alive. There are several ways to generate animations in R, including with animation packages such as **gganimate**, which builds on **ggplot2** (see Section \@ref(other-mapping-packages)). This section focuses on creating animated maps with **tmap** because its syntax will be familiar from previous sections and the flexibility of the approach. @@ -720,7 +720,7 @@ urb_anim = tm_shape(world) + tm_polygons() + The resulting `urb_anim` represents a set of separate maps for each year. The final stage is to combine them and save the result as a `.gif` file with `tmap_animation()`. -The following command creates the animation illustrated in Figure \@ref(fig:urban-animated), with a few elements missing, that we will add in during the exercises: +The following command creates the animation illustrated in Figure \@ref(fig:urban-animated), with a few elements missing, that we will add during the exercises: ``` r @@ -748,7 +748,7 @@ Less advanced interactivity levels include pop-ups which appear when you click o More advanced levels of interactivity include the ability to tilt and rotate maps, as demonstrated in the **mapdeck** example below, and the provision of "dynamically linked" sub-plots which automatically update when the user pans and zooms [@pezanowski_senseplace3_2018]. The most important type of interactivity, however, is the display of geographic data on interactive or 'slippy' web maps. -The release of the **leaflet** package in 2015 (that uses the leaflet JavaScript library) revolutionized interactive web map creation from within R and a number of packages have built on these foundations adding new features (e.g., **leaflet.extras2**) and making the creation of web maps as simple as creating static maps (e.g., **mapview** and **tmap**). +The release of the **leaflet** package in 2015 (that uses the leaflet JavaScript library) revolutionized interactive web map creation from within R, and a number of packages have built on these foundations adding new features (e.g., **leaflet.extras2**) and making the creation of web maps as simple as creating static maps (e.g., **mapview** and **tmap**). This section illustrates each approach in the opposite order. We will explore how to make slippy maps with **tmap** (the syntax of which we have already learned), **mapview**\index{mapview (package)}, **mapdeck**\index{mapdeck (package)} and finally **leaflet**\index{leaflet (package)} (which provides low-level control over interactive maps). @@ -812,7 +812,7 @@ mapview::mapview(nz)

(\#fig:mapview)Illustration of mapview in action.

-**mapview** has a concise syntax yet is powerful. +**mapview** has a concise syntax, yet, it is powerful. By default, it has some standard GIS functionality such as mouse position information, attribute queries (via pop-ups), scale bar, and zoom-to-layer buttons. It also offers advanced controls including the ability to 'burst' datasets into multiple layers and the addition of multiple layers with `+` followed by the name of a geographic object. Additionally, it provides automatic coloring of attributes via the `zcol` argument. @@ -834,8 +834,8 @@ trails |> ```
-Using mapview at the end of a sf-based pipe expression. -

(\#fig:mapview2)Using mapview at the end of a sf-based pipe expression.

+Using mapview at the end of an sf-based pipe expression. +

(\#fig:mapview2)Using mapview at the end of an sf-based pipe expression.

One important thing to keep in mind is that **mapview** layers are added via the `+` operator (similar to **ggplot2** or **tmap**). @@ -873,8 +873,8 @@ mapdeck(style = ms, pitch = 45, location = c(0, 52), zoom = 4) |> ```
-Map generated by mapdeck, representing road traffic casualties across the UK. Height of 1 km cells represents number of crashes. -

(\#fig:mapdeck)Map generated by mapdeck, representing road traffic casualties across the UK. Height of 1 km cells represents number of crashes.

+Map generated by mapdeck, representing road traffic casualties across the UK. Height of 1-km cells represents number of crashes. +

(\#fig:mapdeck)Map generated by mapdeck, representing road traffic casualties across the UK. Height of 1-km cells represents number of crashes.

You can zoom and drag the map in the browser, in addition to rotating and tilting it when pressing `Cmd`/`Ctrl`. @@ -883,7 +883,7 @@ Multiple layers can be added with the pipe operator, as demonstrated in the [`ma -Last but not least is **leaflet** which is the most mature and widely used interactive mapping package in R\index{leaflet (package)}. +Last is **leaflet** which is the most mature and widely used interactive mapping package in R\index{leaflet (package)}. **leaflet** provides a relatively low-level interface to the Leaflet JavaScript library and many of its arguments can be understood by reading the documentation of the original JavaScript library (see [leafletjs.com](https://leafletjs.com/)). Leaflet maps are created with `leaflet()`, the result of which is a `leaflet` map object which can be piped to other **leaflet** functions. @@ -910,26 +910,26 @@ leaflet(data = cycle_hire) |> \index{map-making!mapping applications} The interactive web maps demonstrated in Section \@ref(interactive-maps) can go far. -Careful selection of layers to display, base-maps and pop-ups can be used to communicate the main results of many projects involving geocomputation. -But the web mapping approach to interactivity has limitations: +Careful selection of layers to display, basemaps and pop-ups can be used to communicate the main results of many projects involving geocomputation. +But the web-mapping approach to interactivity has limitations: - Although the map is interactive in terms of panning, zooming and clicking, the code is static, meaning the user interface is fixed - All map content is generally static in a web map, meaning that web maps cannot scale to handle large datasets easily -- Additional layers of interactivity, such a graphs showing relationships between variables and 'dashboards' are difficult to create using the web-mapping approach +- Additional layers of interactivity, such a graphs showing relationships between variables and 'dashboards', are difficult to create using the web-mapping-approach -Overcoming these limitations involves going beyond static web mapping and towards geospatial frameworks and map servers. +Overcoming these limitations involves going beyond static web mapping and toward geospatial frameworks and map servers. Products in this field include [GeoDjango](https://docs.djangoproject.com/en/4.0/ref/contrib/gis/)\index{GeoDjango} (which extends the Django web framework and is written in [Python](https://github.com/django/django))\index{Python}, [MapServer](https://github.com/mapserver/mapserver)\index{MapServer} (a framework for developing web applications, largely written in C and C++)\index{C++} and [GeoServer](https://github.com/geoserver/geoserver) (a mature and powerful map server written in Java\index{Java}). Each of these is scalable, enabling maps to be served to thousands of people daily, assuming there is sufficient public interest in your maps! -The bad news is that such server-side solutions require much skilled developer time to set-up and maintain, often involving teams of people with roles such as a dedicated geospatial database administrator ([DBA](https://wiki.gis.com/wiki/index.php/Database_administrator)). +The bad news is that such server-side solutions require much skilled developer time to set up and maintain, often involving teams of people with roles such as a dedicated geospatial database administrator ([DBA](https://wiki.gis.com/wiki/index.php/Database_administrator)). -Fortunately for R programmers, web mapping applications can now be rapidly created with **shiny**.\index{shiny (package)} +Fortunately for R programmers, web-mapping applications can now be rapidly created with **shiny**.\index{shiny (package)} As described in the open source book [Mastering Shiny](https://mastering-shiny.org/), **shiny** is an R package and framework for converting R code into interactive web applications [@wickham_mastering_2021]. You can embed interactive maps in shiny apps thanks to functions such as [`leaflet::renderLeaflet()`](https://rstudio.github.io/leaflet/shiny.html). -This section gives some context, teaches the basics of **shiny** from a web mapping perspective and culminates in a full-screen mapping application in less than 100 lines of code. +This section gives some context, teaches the basics of **shiny** from a web-mapping perspective, and culminates in a full-screen mapping application in less than 100 lines of code. **shiny** is well documented at [shiny.posit.co](https://shiny.posit.co/), which highlights the two components of every **shiny** app: 'front end' (the bit the user sees) and 'back end' code. In **shiny** apps, these elements are typically created in objects named `ui` and `server` within an R script named `app.R`, which lives in an 'app folder'. -This allows web mapping applications to be represented in a single file, such as the [`CycleHireApp/app.R`](https://github.com/geocompx/geocompr/blob/main/apps/CycleHireApp/app.R) file in the book's GitHub repo. +This allows web-mapping applications to be represented in a single file, such as the [`CycleHireApp/app.R`](https://github.com/geocompx/geocompr/blob/main/apps/CycleHireApp/app.R) file in the book's GitHub repo. \BeginKnitrBlock{rmdnote}
In **shiny** apps these are often split into `ui.R` (short for user interface) and `server.R` files, naming conventions used by `shiny-server`, a server-side Linux application for serving shiny apps on public-facing websites. `shiny-server` also serves apps defined by a single `app.R` file in an 'app folder'. @@ -959,8 +959,8 @@ shinyApp(ui, server) ```
-Screenshot showing minimal example of a web mapping application created with shiny. -

(\#fig:lifeApp)Screenshot showing minimal example of a web mapping application created with shiny.

+Screenshot showing minimal example of a web-mapping application created with shiny. +

(\#fig:lifeApp)Screenshot showing minimal example of a web-mapping application created with shiny.

The **user interface** (`ui`) of lifeApp is created by `fluidPage()`. @@ -974,12 +974,12 @@ The function `shinyApp()` combines both the `ui` and `server` elements and serve When you move the slider in the map shown in Figure \@ref(fig:lifeApp), you are actually causing R code to re-run, although this is hidden from view in the user interface. Building on this basic example and knowing where to find help (see `?shiny`), the best way forward now may be to stop reading and start programming! -The recommended next step is to open the previously mentioned [`CycleHireApp/app.R`](https://github.com/geocompx/geocompr/blob/main/apps/CycleHireApp/app.R) script in an IDE of choice, modify it and re-run it repeatedly. +The recommended next step is to open the previously mentioned [`CycleHireApp/app.R`](https://github.com/geocompx/geocompr/blob/main/apps/CycleHireApp/app.R) script in an integrated development environment (IDE) of choice, modify it and re-run it repeatedly. The example contains some of the components of a web mapping application implemented in **shiny** and should 'shine' a light on how they behave. -The `CycleHireApp/app.R` script contains **shiny** functions that go beyond those demonstrated in the simple 'lifeApp' example. +The `CycleHireApp/app.R` script contains **shiny** functions that go beyond those demonstrated in the simple 'lifeApp' example (Figure \@ref(fig:CycleHireApp-html)). These include `reactive()` and `observe()` (for creating outputs that respond to the user interface --- see `?reactive`) and `leafletProxy()` (for modifying a `leaflet` object that has already been created). -Such elements are critical to the creation of web mapping applications implemented in **shiny**. +Such elements are critical to the creation of web-mapping applications implemented in **shiny**. A range of 'events' can be programmed including advanced functionality such as drawing new layers or subsetting data, as described in the shiny section of RStudio's **leaflet** [website](https://rstudio.github.io/leaflet/shiny.html). \BeginKnitrBlock{rmdnote}
There are a number of ways to run a **shiny** app. @@ -987,12 +987,12 @@ For RStudio users, the simplest way is probably to click on the 'Run App' button **shiny** apps can also be initiated by using `runApp()` with the first argument being the folder containing the app code and data: `runApp("CycleHireApp")` in this case (which assumes a folder named `CycleHireApp` containing the `app.R` script is in your working directory). You can also launch apps from a Unix command line with the command `Rscript -e 'shiny::runApp("CycleHireApp")'`.
\EndKnitrBlock{rmdnote} -Experimenting with apps such as `CycleHireApp` will build not only your knowledge of web mapping applications in R, but also your practical skills. +Experimenting with apps such as `CycleHireApp` will build not only your knowledge of web-mapping applications in R, but also your practical skills. Changing the contents of `setView()`, for example, will change the starting bounding box that the user sees when the app is initiated. Such experimentation should not be done at random, but with reference to relevant documentation, starting with `?shiny`, and motivated by a desire to solve problems such as those posed in the exercises. **shiny** used in this way can make prototyping mapping applications faster and more accessible than ever before (deploying **shiny** apps, https://shiny.posit.co/deploy/, is a separate topic beyond the scope of this chapter). -Even if your applications are eventually deployed using different technologies, **shiny** undoubtedly allows web mapping applications to be developed in relatively few lines of code (86 in the case of CycleHireApp). +Even if your applications are eventually deployed using different technologies, **shiny** undoubtedly allows web-mapping applications to be developed in relatively few lines of code (86 in the case of CycleHireApp). That does not stop shiny apps getting rather large. The Propensity to Cycle Tool (PCT) hosted at [pct.bike](https://www.pct.bike/), for example, is a national mapping tool funded by the UK's Department for Transport. The PCT is used by dozens of people each day and has multiple interactive elements based on more than 1000 lines of [code](https://github.com/npct/pct-shiny/blob/master/regions_www/m/server.R) [@lovelace_propensity_2017]. @@ -1004,7 +1004,7 @@ This way your prototype web applications should be limited not by technical cons
-

(\#fig:CycleHireApp-html)CycleHireApp, a simple web mapping application for finding the closest cycle hiring station based on your location and requirement of cycles. Interactive version available online at r.geocompx.org.

+

(\#fig:CycleHireApp-html)CycleHireApp, a simple web-mapping application for finding the closest cycle hiring station based on your location and requirement of cycles. Interactive version available online at: r.geocompx.org.

@@ -1013,7 +1013,7 @@ This way your prototype web applications should be limited not by technical cons **tmap** provides a powerful interface for creating a wide range of static maps (Section \@ref(static-maps)) and also supports interactive maps (Section \@ref(interactive-maps)). But there are many other options for creating maps in R. -The aim of this section is to provide a taster of some of these and pointers for additional resources: map-making is a surprisingly active area of R package development, so there is more to learn than can be covered here. +The aim of this section is to provide a taste of some of these and pointers for additional resources: map-making is a surprisingly active area of R package development, so there is more to learn than can be covered here. The most mature option is to use `plot()` methods provided by core spatial packages **sf** and **terra**, covered in Sections \@ref(basic-map) and \@ref(basic-map-raster), respectively. What we have not mentioned in those sections was that plot methods for vector and raster objects can be combined when the results draw onto the same plot area (elements such as keys in **sf** plots and multi-band rasters will interfere with this). @@ -1129,7 +1129,7 @@ Before we cover mapping packages for plotting a specific type of map (in the nex Table \@ref(tab:map-gpkg) shows a range of mapping packages that are available, and there are many others not listed in this table. -Of note is **mapsf**, which can generate range of geographic visualizations including choropleth, 'proportional symbol' and 'flow' maps. +Of note is **mapsf**, which can generate a range of geographic visualizations including choropleth, 'proportional symbol' and 'flow' maps. These are documented in the [`mapsf`](https://cran.r-project.org/package=mapsf/vignettes/mapsf.html)\index{mapsf (package)} vignette. Several packages focus on specific map types, as illustrated in Table \@ref(tab:map-spkg). @@ -1156,13 +1156,13 @@ In the next paragraph, we focus solely on the **cartogram** package [@R-cartogra Therefore, we suggest to read the [geogrid](https://github.com/jbaileyh/geogrid)\index{geogrid (package)}, [geofacet](https://github.com/hafen/geofacet)\index{geofacet (package)}, [linemap](https://github.com/riatelab/linemap)\index{linemap (package)}, [tanaka](https://github.com/riatelab/tanaka)\index{tanaka (package)}, and [rayshader](https://github.com/tylermorganwall/rayshader)\index{rayshader (package)} documentations to learn more about them. A cartogram is a map in which the geometry is proportionately distorted to represent a mapping variable. -Creation of this type of map is possible in R with **cartogram**, which allows for creating continuous and non-contiguous area cartograms. +Creation of this type of map is possible in R with **cartogram**, which allows for creating contiguous and non-contiguous area cartograms. It is not a mapping package per se, but it allows for construction of distorted spatial objects that could be plotted using any generic mapping package. -The `cartogram_cont()` function creates continuous area cartograms. +The `cartogram_cont()` function creates contiguous area cartograms. It accepts an `sf` object and name of the variable (column) as inputs. -Additionally, it is possible to modify the `intermax` argument - maximum number of iterations for the cartogram transformation. -For example, we could represent median income in New Zeleand's regions as a continuous cartogram (Figure \@ref(fig:cartomap1), right panel) as follows: +Additionally, it is possible to modify the `intermax` argument -- maximum number of iterations for the cartogram transformation. +For example, we could represent median income in New Zeleand's regions as a contiguous cartogram (Figure \@ref(fig:cartomap1), right panel) as follows: ``` r @@ -1172,8 +1172,8 @@ tm_shape(nz_carto) + tm_polygons("Median_income") ```
-Comparison of standard map (left) and continuous area cartogram (right). -

(\#fig:cartomap1)Comparison of standard map (left) and continuous area cartogram (right).

+Comparison of standard map (left) and contiguous area cartogram (right). +

(\#fig:cartomap1)Comparison of standard map (left) and contiguous area cartogram (right).

**cartogram** also offers creation of non-contiguous area cartograms using `cartogram_ncont()` and Dorling cartograms using `cartogram_dorling()`. @@ -1189,8 +1189,8 @@ us_states9311_dorling = cartogram_dorling(us_states9311, "total_pop_15") ```
-Comparison of non-continuous area cartogram (left) and Dorling cartogram (right). -

(\#fig:cartomap2)Comparison of non-continuous area cartogram (left) and Dorling cartogram (right).

+Comparison of non-contiguous area cartogram (left) and Dorling cartogram (right). +

(\#fig:cartomap2)Comparison of non-contiguous area cartogram (left) and Dorling cartogram (right).

## Exercises @@ -1225,9 +1225,8 @@ E1. Create a map showing the geographic distribution of the Human Development In -E2. Extend the **tmap** created for the previous exercise so the legend has three bins: "High" (`HDI` above 0.7), "Medium" (`HDI` between 0.55 and 0.7) and "Low" (`HDI` below 0.55). - -- Bonus: improve the map aesthetics, for example by changing the legend title, class labels and color palette. +E2. Extend the **tmap** created for the previous exercise so the legend has three bins: "High" (`HDI` above 0.7), "Medium" (`HDI` between 0.55 and 0.7) and "Low" (`HDI` below 0.55). +Bonus: improve the map aesthetics, for example by changing the legend title, class labels and color palette. @@ -1237,11 +1236,11 @@ Next, combine this map and the map created in the previous exercise into a singl -E4. Create a land cover map of the Zion National Park. +E4. Create a land cover map of Zion National Park. - Change the default colors to match your perception of the land cover categories - Add a scale bar and north arrow and change the position of both to improve the map's aesthetic appeal -- Bonus: Add an inset map of Zion National Park's location in the context of the Utah state. (Hint: an object representing Utah can be subset from the `us_states` dataset.) +- Bonus: Add an inset map of Zion National Park's location in the context of the state of Utah. (Hint: an object representing Utah can be subset from the `us_states` dataset.) @@ -1270,7 +1269,7 @@ E7. Create an interactive map of HDI in Africa: -E8. Sketch on paper ideas for a web mapping app that could be used to make transport or land-use policies more evidence based: +E8. Sketch on paper ideas for a web-mapping application that could be used to make transport or land-use policies more evidence-based: - In the city you live, for a couple of users per day - In the country you live, for dozens of users per day diff --git a/13-transport.md b/13-transport.md index 4eae149ee..fe28f1b2d 100644 --- a/13-transport.md +++ b/13-transport.md @@ -511,6 +511,7 @@ This is done using the publicly available OSRM service with the **stplanr** func ``` r routes_short = route(l = desire_lines_short, route_fun = route_osrm, osrm.profile = "bike") +#> ``` The output is `routes_short`, an `sf` object representing routes on the transport network\index{network} that are suitable for cycling (according to the OSRM routing engine at least), one for each desire line. @@ -569,7 +570,7 @@ routes_short_scenario = routes_short |> mutate(bicycle = bicycle + car_driver * uptake, car_driver = car_driver * (1 - uptake)) sum(routes_short_scenario$bicycle) - sum(routes_short$bicycle) -#> [1] 3850 +#> [1] 558 ``` Having created a scenario in which approximately 4000 trips have switched from driving to cycling, we can now model where this updated modeled cycling activity will take place. diff --git a/adv-map.html b/adv-map.html index 7077a1f82..5d76dcc75 100644 --- a/adv-map.html +++ b/adv-map.html @@ -135,7 +135,7 @@

Prerequisites< library(leaflet) # for interactive maps library(ggplot2) # tidyverse data visualization package

 nz_elev = rast(system.file("raster/nz_elev.tif", package = "spDataLarge"))
@@ -153,7 +153,7 @@

Map-making is no exception, hence this chapter’s coverage of one package (tmap) in depth rather than many superficially.

In addition to being fun and creative, cartography also has important practical applications. A carefully crafted map can be the best way of communicating the results of your work, but poorly designed maps can leave a bad impression. -Common 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. +Common 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. Furthermore, poor map-making can hinder the communication of results (Brewer 2015):

Amateur-looking maps can undermine your audience’s ability to understand important information and weaken the presentation of a professional data investigation. @@ -161,9 +161,9 @@

Historic 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 2014).

Map-making has historically been an activity undertaken only by, or on behalf of, the elite. -This has changed with the emergence of open source mapping software such as the R package tmap and the ‘print layout’ in QGIS which enable anyone to make high-quality maps, enabling ‘citizen science’. +This has changed with the emergence of open source mapping software such as the R package tmap and the ‘print layout’ in QGIS, which allow anyone to make high-quality maps, enabling ‘citizen science’. Maps are also often the best way to present the findings of geocomputational research in a way that is accessible. -Map-making is therefore a critical part of geocomputation and its emphasis not only on describing, but also changing the world.

+Map-making is therefore a critical part of geocomputation and its emphasis is not only on describing, but also changing the world.

This chapter shows how to make a wide range of maps. The next section covers a range of static maps, including aesthetic considerations, facets and inset maps. Sections 9.3 to 9.5 cover animated and interactive maps (including web maps and mapping applications). @@ -179,10 +179,10 @@

Initially, static maps were the only type of maps that R could produce. Things have advanced with the release of sp (see Pebesma and Bivand 2005), and many map-making techniques, functions, and packages have been developed since then. However, despite the innovation of interactive mapping, static plotting was still the emphasis of geographic data visualization in R a decade later (Cheshire and Lovelace 2015).

-

The generic plot() function is often the fastest way to create static maps from vector and raster spatial objects (see sections 2.2.3 and 2.3.3). +

The generic plot() function is often the fastest way to create static maps from vector and raster spatial objects (see Sections 2.2.3 and 2.3.3). Sometimes, simplicity and speed are priorities, especially during the development phase of a project, and this is where plot() excels. The base R approach is also extensible, with plot() offering dozens of arguments. -Another approach is the grid package which allows low-level control of static maps, as illustrated in Chapter 14 of Murrell (2016). +Another approach is the grid package which allows low-level control of static maps, as illustrated in chapter 14 of Murrell (2016). This part of the book focuses on tmap and emphasizes the essential aesthetic and layout options.

tmap is a powerful and flexible map-making package with sensible defaults. @@ -223,20 +223,20 @@

The asterisk (*) refers to a wide range of layer types which have self-explanatory names including:

This layering is illustrated in the right panel of Figure 9.1, the result of adding a border on top of the fill layer.

@@ -258,7 +258,7 @@

map_nz = tm_shape(nz) + tm_polygons() class(map_nz) #> [1] "tmap" -

map_nz can be plotted later, for example by adding additional layers (as shown below) or simply running map_nz in the console, which is equivalent to print(map_nz).

+

map_nz can be plotted later, for example by adding other layers (as shown below) or simply running map_nz in the console, which is equivalent to print(map_nz).

New shapes can be added with + tm_shape(new_obj). In this case, new_obj represents a new spatial object to be plotted on top of preceding layers. When a new shape is added in this way, all subsequent aesthetic functions refer to it, until another new shape is added. @@ -287,8 +287,8 @@

tmap_arrange(map_nz1, map_nz2, map_nz3)
-Maps with additional layers added to the final map of Figure 9.1.

-FIGURE 9.2: Maps with additional layers added to the final map of Figure 9.1. +Maps with added layers to the final map of Figure 9.1.

+FIGURE 9.2: Maps with added layers to the final map of Figure 9.1.

More elements can also be added with the + operator. @@ -334,8 +334,8 @@

tmap_arrange(ma1, ma2, ma3, ma4, ma5, ma6)
-The impact of changing commonly used fill and border aesthetics to fixed values.

-FIGURE 9.3: The impact of changing commonly used fill and border aesthetics to fixed values. +Impact of changing commonly used fill and border aesthetics to fixed values.

+FIGURE 9.3: Impact of changing commonly used fill and border aesthetics to fixed values.

Like base R plots, arguments defining aesthetics can also receive values that vary. @@ -364,7 +364,7 @@

9.2.4 Scales

-Scales control how the values are represented on the map and in the legend, and largely depend on the selected visual variable. +Scales control how the values are represented on the map and in the legend, and they largely depend on the selected visual variable. For example, when our visual variable is col, then col.scale controls how the colors of spatial objects are related to the provided values; and when our visual variable is size, then size.scale controls how the sizes represent the provided values. By default, the used scale is tm_scale(), which selects the visual settings automatically given by the input data type (factor, numeric, and integer).

@@ -391,8 +391,8 @@

fill.scale = tm_scale(values = "BuGn"))
-Illustration of settings that affect color settings. The results show (from left to right): default settings, manual breaks, n breaks, and the impact of changing the palette.

-FIGURE 9.5: Illustration of settings that affect color settings. The results show (from left to right): default settings, manual breaks, n breaks, and the impact of changing the palette. +Illustration of color settings. The results show (from left to right): default settings, manual breaks, n breaks, and the impact of changing the palette.

+FIGURE 9.5: Illustration of color settings. The results show (from left to right): default settings, manual breaks, n breaks, and the impact of changing the palette.

@@ -410,7 +410,7 @@

Other options are listed below and presented in Figure 9.6.

-Illustration of selected layout options.

-FIGURE 9.11: Illustration of selected layout options. +Selected layout options.

+FIGURE 9.11: Selected layout options.

@@ -581,7 +581,7 @@

However, this risks cluttering the map because it will involve multiple overlapping points (cities do not tend to move over time!).

Typically all individual facets in a faceted map contain the same geometry data repeated multiple times, once for each column in the attribute data (this is the default plotting method for sf objects, see Chapter 2). However, facets can also represent shifting geometries such as the evolution of a point pattern over time. -This use case of faceted plot is illustrated in Figure 9.12.

+This use case of a faceted plot is illustrated in Figure 9.12.

 urb_1970_2030 = urban_agglomerations |> 
   filter(year %in% c(1970, 1990, 2010, 2030))
@@ -599,7 +599,7 @@ 

The preceding code chunk demonstrates key features of faceted maps created using the tm_facets_wrap() function:

    -
  • Shapes that do not have a facet variable are repeated (the countries in world in this case)
  • +
  • Shapes that do not have a facet variable are repeated (countries in world in this case)
  • The by argument which varies depending on a variable ("year" in this case)
  • The nrow/ncol setting specifying the number of rows and columns that facets should be arranged into
@@ -622,7 +622,7 @@

ymin = 5130000, ymax = 5210000), crs = st_crs(nz_height)) |> st_as_sfc() -

In the second step, we create a base map showing the New Zealand’s Southern Alps area. +

In the second step, we create a base-map showing New Zealand’s Southern Alps area. This is a place where the most important message is stated.

 nz_height_map = tm_shape(nz_elev, bbox = nz_region) +
@@ -672,11 +672,11 @@ 

print(nz_map, vp = ins_vp)

-Inset map providing a context - location of the central part of the Southern Alps in New Zealand.

-FIGURE 9.13: Inset map providing a context - location of the central part of the Southern Alps in New Zealand. +Inset map providing a context -- location of the central part of the Southern Alps in New Zealand.

+FIGURE 9.13: Inset map providing a context – location of the central part of the Southern Alps in New Zealand.

-

Inset map can be saved to file either by using a graphic device (see Section 8.9) or the tmap_save() function and its arguments - insets_tm and insets_vp.

+

Inset maps can be saved to file either by using a graphic device (see Section 8.9) or the tmap_save() function and its arguments: insets_tm and insets_vp.

Inset maps are also used to create one map of non-contiguous areas. Probably, the most often used example is a map of the United States, which consists of the contiguous United States, Hawaii and Alaska. It is very important to find the best projection for each individual inset in these types of cases (see Chapter 7 to learn more). @@ -707,7 +707,7 @@

FIGURE 9.14: Map of the United States.

-

The code presented above is compact and can be used as the basis for other inset maps but the results, in Figure 9.14, provide a poor representation of the locations and sizes of Hawaii and Alaska. +

The code presented above is compact and can be used as the basis for other inset maps, but the results, in Figure 9.14, provide a poor representation of the locations and sizes of Hawaii and Alaska. For a more in-depth approach, see the us-map vignette from the geocompkg.

@@ -721,7 +721,7 @@

Furthermore, the fact that each facet is physically separated on the screen or page means that subtle differences between facets can be hard to detect.

Animated maps solve these issues. Although they depend on digital publication, this is becoming less of an issue as more and more content moves online. -Animated maps can still enhance paper reports: you can always link readers to a web-page containing an animated (or interactive) version of a printed map to help make it come alive. +Animated maps can still enhance paper reports: you can always link readers to a webpage containing an animated (or interactive) version of a printed map to help make it come alive. There are several ways to generate animations in R, including with animation packages such as gganimate, which builds on ggplot2 (see Section 9.6). This section focuses on creating animated maps with tmap because its syntax will be familiar from previous sections and the flexibility of the approach.

Figure 9.15 is a simple example of an animated map. @@ -747,7 +747,7 @@

tm_facets_wrap(by = "year", nrow = 1, ncol = 1, free.coords = FALSE)

The resulting urb_anim represents a set of separate maps for each year. The final stage is to combine them and save the result as a .gif file with tmap_animation(). -The following command creates the animation illustrated in Figure 9.15, with a few elements missing, that we will add in during the exercises:

+The following command creates the animation illustrated in Figure 9.15, with a few elements missing, that we will add during the exercises:

 tmap_animation(urb_anim, filename = "urb_anim.gif", delay = 25)

Another illustration of the power of animated maps is provided in Figure 9.16. @@ -770,7 +770,7 @@

Less advanced interactivity levels include pop-ups which appear when you click on different features, a kind of interactive label. More advanced levels of interactivity include the ability to tilt and rotate maps, as demonstrated in the mapdeck example below, and the provision of “dynamically linked” sub-plots which automatically update when the user pans and zooms (Pezanowski et al. 2018).

The most important type of interactivity, however, is the display of geographic data on interactive or ‘slippy’ web maps. -The release of the leaflet package in 2015 (that uses the leaflet JavaScript library) revolutionized interactive web map creation from within R and a number of packages have built on these foundations adding new features (e.g., leaflet.extras2) and making the creation of web maps as simple as creating static maps (e.g., mapview and tmap). +The release of the leaflet package in 2015 (that uses the leaflet JavaScript library) revolutionized interactive web map creation from within R, and a number of packages have built on these foundations adding new features (e.g., leaflet.extras2) and making the creation of web maps as simple as creating static maps (e.g., mapview and tmap). This section illustrates each approach in the opposite order. We will explore how to make slippy maps with tmap (the syntax of which we have already learned), mapview, mapdeck and finally leaflet (which provides low-level control over interactive maps).

A unique feature of tmap mentioned in Section 9.2 is its ability to create static and interactive maps using the same code. @@ -818,7 +818,7 @@

FIGURE 9.19: Illustration of mapview in action.

-

mapview has a concise syntax yet is powerful. +

mapview has a concise syntax, yet, it is powerful. By default, it has some standard GIS functionality such as mouse position information, attribute queries (via pop-ups), scale bar, and zoom-to-layer buttons. It also offers advanced controls including the ability to ‘burst’ datasets into multiple layers and the addition of multiple layers with + followed by the name of a geographic object. Additionally, it provides automatic coloring of attributes via the zcol argument. @@ -837,8 +837,8 @@

breweries
-Using mapview at the end of a sf-based pipe expression.

-FIGURE 9.20: Using mapview at the end of a sf-based pipe expression. +Using mapview at the end of an sf-based pipe expression.

+FIGURE 9.20: Using mapview at the end of an sf-based pipe expression.

One important thing to keep in mind is that mapview layers are added via the + operator (similar to ggplot2 or tmap). @@ -871,14 +871,14 @@

elevation_scale = 50, colour_range = hcl.colors(6, "plasma"))
-Map generated by mapdeck, representing road traffic casualties across the UK. Height of 1 km cells represents number of crashes.

-FIGURE 9.21: Map generated by mapdeck, representing road traffic casualties across the UK. Height of 1 km cells represents number of crashes. +Map generated by mapdeck, representing road traffic casualties across the UK. Height of 1-km cells represents number of crashes.

+FIGURE 9.21: Map generated by mapdeck, representing road traffic casualties across the UK. Height of 1-km cells represents number of crashes.

You can zoom and drag the map in the browser, in addition to rotating and tilting it when pressing Cmd/Ctrl. Multiple layers can be added with the pipe operator, as demonstrated in the mapdeck vignettes. mapdeck also supports sf objects, as can be seen by replacing the add_grid() function call in the preceding code chunk with add_polygon(data = lnd, layer_id = "polygon_layer"), to add polygons representing London to an interactive tilted map.

-

Last but not least is leaflet which is the most mature and widely used interactive mapping package in R. +

Last is leaflet which is the most mature and widely used interactive mapping package in R. leaflet provides a relatively low-level interface to the Leaflet JavaScript library and many of its arguments can be understood by reading the documentation of the original JavaScript library (see leafletjs.com).

Leaflet maps are created with leaflet(), the result of which is a leaflet map object which can be piped to other leaflet functions. This allows multiple map layers and control settings to be added interactively, as demonstrated in the code below which generates Figure 9.22 (see rstudio.github.io/leaflet/ for details).

@@ -904,24 +904,24 @@

The interactive web maps demonstrated in Section 9.4 can go far. -Careful selection of layers to display, base-maps and pop-ups can be used to communicate the main results of many projects involving geocomputation. -But the web mapping approach to interactivity has limitations:

+Careful selection of layers to display, basemaps and pop-ups can be used to communicate the main results of many projects involving geocomputation. +But the web-mapping approach to interactivity has limitations:

-

Overcoming these limitations involves going beyond static web mapping and towards geospatial frameworks and map servers. +

Overcoming these limitations involves going beyond static web mapping and toward geospatial frameworks and map servers. Products in this field include GeoDjango (which extends the Django web framework and is written in Python), MapServer (a framework for developing web applications, largely written in C and C++) and GeoServer (a mature and powerful map server written in Java). Each of these is scalable, enabling maps to be served to thousands of people daily, assuming there is sufficient public interest in your maps! -The bad news is that such server-side solutions require much skilled developer time to set-up and maintain, often involving teams of people with roles such as a dedicated geospatial database administrator (DBA).

-

Fortunately for R programmers, web mapping applications can now be rapidly created with shiny. +The bad news is that such server-side solutions require much skilled developer time to set up and maintain, often involving teams of people with roles such as a dedicated geospatial database administrator (DBA).

+

Fortunately for R programmers, web-mapping applications can now be rapidly created with shiny. As described in the open source book Mastering Shiny, shiny is an R package and framework for converting R code into interactive web applications (Wickham 2021). You can embed interactive maps in shiny apps thanks to functions such as leaflet::renderLeaflet(). -This section gives some context, teaches the basics of shiny from a web mapping perspective and culminates in a full-screen mapping application in less than 100 lines of code.

+This section gives some context, teaches the basics of shiny from a web-mapping perspective, and culminates in a full-screen mapping application in less than 100 lines of code.

shiny is well documented at shiny.posit.co, which highlights the two components of every shiny app: ‘front end’ (the bit the user sees) and ‘back end’ code. In shiny apps, these elements are typically created in objects named ui and server within an R script named app.R, which lives in an ‘app folder’. -This allows web mapping applications to be represented in a single file, such as the CycleHireApp/app.R file in the book’s GitHub repo.

+This allows web-mapping applications to be represented in a single file, such as the CycleHireApp/app.R file in the book’s GitHub repo.

In shiny apps these are often split into ui.R (short for user interface) and server.R files, naming conventions used by shiny-server, a server-side Linux application for serving shiny apps on public-facing websites. @@ -948,8 +948,8 @@

shinyApp(ui, server)

-Screenshot showing minimal example of a web mapping application created with shiny.

-FIGURE 9.23: Screenshot showing minimal example of a web mapping application created with shiny. +Screenshot showing minimal example of a web-mapping application created with shiny.

+FIGURE 9.23: Screenshot showing minimal example of a web-mapping application created with shiny.

The user interface (ui) of lifeApp is created by fluidPage(). @@ -961,11 +961,11 @@

The function shinyApp() combines both the ui and server elements and serves the results interactively via a new R process. When you move the slider in the map shown in Figure 9.23, you are actually causing R code to re-run, although this is hidden from view in the user interface.

Building on this basic example and knowing where to find help (see ?shiny), the best way forward now may be to stop reading and start programming! -The recommended next step is to open the previously mentioned CycleHireApp/app.R script in an IDE of choice, modify it and re-run it repeatedly. +The recommended next step is to open the previously mentioned CycleHireApp/app.R script in an integrated development environment (IDE) of choice, modify it and re-run it repeatedly. The example contains some of the components of a web mapping application implemented in shiny and should ‘shine’ a light on how they behave.

-

The CycleHireApp/app.R script contains shiny functions that go beyond those demonstrated in the simple ‘lifeApp’ example. +

The CycleHireApp/app.R script contains shiny functions that go beyond those demonstrated in the simple ‘lifeApp’ example (Figure 9.24). These include reactive() and observe() (for creating outputs that respond to the user interface — see ?reactive) and leafletProxy() (for modifying a leaflet object that has already been created). -Such elements are critical to the creation of web mapping applications implemented in shiny. +Such elements are critical to the creation of web-mapping applications implemented in shiny. A range of ‘events’ can be programmed including advanced functionality such as drawing new layers or subsetting data, as described in the shiny section of RStudio’s leaflet website.

@@ -974,11 +974,11 @@

shiny apps can also be initiated by using runApp() with the first argument being the folder containing the app code and data: runApp("CycleHireApp") in this case (which assumes a folder named CycleHireApp containing the app.R script is in your working directory). You can also launch apps from a Unix command line with the command Rscript -e 'shiny::runApp("CycleHireApp")'.

-

Experimenting with apps such as CycleHireApp will build not only your knowledge of web mapping applications in R, but also your practical skills. +

Experimenting with apps such as CycleHireApp will build not only your knowledge of web-mapping applications in R, but also your practical skills. Changing the contents of setView(), for example, will change the starting bounding box that the user sees when the app is initiated. Such experimentation should not be done at random, but with reference to relevant documentation, starting with ?shiny, and motivated by a desire to solve problems such as those posed in the exercises.

shiny used in this way can make prototyping mapping applications faster and more accessible than ever before (deploying shiny apps, https://shiny.posit.co/deploy/, is a separate topic beyond the scope of this chapter). -Even if your applications are eventually deployed using different technologies, shiny undoubtedly allows web mapping applications to be developed in relatively few lines of code (86 in the case of CycleHireApp). +Even if your applications are eventually deployed using different technologies, shiny undoubtedly allows web-mapping applications to be developed in relatively few lines of code (86 in the case of CycleHireApp). That does not stop shiny apps getting rather large. The Propensity to Cycle Tool (PCT) hosted at pct.bike, for example, is a national mapping tool funded by the UK’s Department for Transport. The PCT is used by dozens of people each day and has multiple interactive elements based on more than 1000 lines of code (Lovelace et al. 2017).

@@ -991,7 +991,7 @@

-FIGURE 9.24: CycleHireApp, a simple web mapping application for finding the closest cycle hiring station based on your location and requirement of cycles. Interactive version available online at r.geocompx.org. +FIGURE 9.24: CycleHireApp, a simple web-mapping application for finding the closest cycle hiring station based on your location and requirement of cycles. Interactive version available online at: r.geocompx.org.

@@ -1001,7 +1001,7 @@

tmap provides a powerful interface for creating a wide range of static maps (Section 9.2) and also supports interactive maps (Section 9.4). But there are many other options for creating maps in R. -The aim of this section is to provide a taster of some of these and pointers for additional resources: map-making is a surprisingly active area of R package development, so there is more to learn than can be covered here.

+The aim of this section is to provide a taste of some of these and pointers for additional resources: map-making is a surprisingly active area of R package development, so there is more to learn than can be covered here.

The most mature option is to use plot() methods provided by core spatial packages sf and terra, covered in Sections 2.2.3 and 2.3.3, respectively. What we have not mentioned in those sections was that plot methods for vector and raster objects can be combined when the results draw onto the same plot area (elements such as keys in sf plots and multi-band rasters will interfere with this). This behavior is illustrated in the subsequent code chunk which generates Figure 9.25. @@ -1133,7 +1133,7 @@

Table 9.1 shows a range of mapping packages that are available, and there are many others not listed in this table. -Of note is mapsf, which can generate range of geographic visualizations including choropleth, ‘proportional symbol’ and ‘flow’ maps. +Of note is mapsf, which can generate a range of geographic visualizations including choropleth, ‘proportional symbol’ and ‘flow’ maps. These are documented in the mapsf vignette.

Several packages focus on specific map types, as illustrated in Table 9.3. Such packages create cartograms that distort geographical space, create line maps, transform polygons into regular or hexagonal grids, visualize complex data on grids representing geographic topologies, and create 3D visualizations.

@@ -1175,20 +1175,20 @@

In the next paragraph, we focus solely on the cartogram package (Jeworutzki 2023). Therefore, we suggest to read the geogrid, geofacet, linemap, tanaka, and rayshader documentations to learn more about them.

A cartogram is a map in which the geometry is proportionately distorted to represent a mapping variable. -Creation of this type of map is possible in R with cartogram, which allows for creating continuous and non-contiguous area cartograms. +Creation of this type of map is possible in R with cartogram, which allows for creating contiguous and non-contiguous area cartograms. It is not a mapping package per se, but it allows for construction of distorted spatial objects that could be plotted using any generic mapping package.

-

The cartogram_cont() function creates continuous area cartograms. +

The cartogram_cont() function creates contiguous area cartograms. It accepts an sf object and name of the variable (column) as inputs. -Additionally, it is possible to modify the intermax argument - maximum number of iterations for the cartogram transformation. -For example, we could represent median income in New Zeleand’s regions as a continuous cartogram (Figure 9.27, right panel) as follows:

+Additionally, it is possible to modify the intermax argument – maximum number of iterations for the cartogram transformation. +For example, we could represent median income in New Zeleand’s regions as a contiguous cartogram (Figure 9.27, right panel) as follows:

 library(cartogram)
 nz_carto = cartogram_cont(nz, "Median_income", itermax = 5)
 tm_shape(nz_carto) + tm_polygons("Median_income")
-Comparison of standard map (left) and continuous area cartogram (right).

-FIGURE 9.27: Comparison of standard map (left) and continuous area cartogram (right). +Comparison of standard map (left) and contiguous area cartogram (right).

+FIGURE 9.27: Comparison of standard map (left) and contiguous area cartogram (right).

cartogram also offers creation of non-contiguous area cartograms using cartogram_ncont() and Dorling cartograms using cartogram_dorling(). @@ -1201,8 +1201,8 @@

us_states9311_dorling = cartogram_dorling(us_states9311, "total_pop_15")
-Comparison of non-continuous area cartogram (left) and Dorling cartogram (right).

-FIGURE 9.28: Comparison of non-continuous area cartogram (left) and Dorling cartogram (right). +Comparison of non-contiguous area cartogram (left) and Dorling cartogram (right).

+FIGURE 9.28: Comparison of non-contiguous area cartogram (left) and Dorling cartogram (right).

@@ -1231,18 +1231,16 @@

  • Name three other mapping packages and an advantage of each.
  • Bonus: create three more maps of Africa using these three other packages.
  • -

    E2. Extend the tmap created for the previous exercise so the legend has three bins: “High” (HDI above 0.7), “Medium” (HDI between 0.55 and 0.7) and “Low” (HDI below 0.55).

    - +

    E2. Extend the tmap created for the previous exercise so the legend has three bins: “High” (HDI above 0.7), “Medium” (HDI between 0.55 and 0.7) and “Low” (HDI below 0.55). +Bonus: improve the map aesthetics, for example by changing the legend title, class labels and color palette.

    E3. Represent africa’s subregions on the map. Change the default color palette and legend title. Next, combine this map and the map created in the previous exercise into a single plot.

    -

    E4. Create a land cover map of the Zion National Park.

    +

    E4. Create a land cover map of Zion National Park.

    E5. Create facet maps of countries in Eastern Africa:

    -

    E8. Sketch on paper ideas for a web mapping app that could be used to make transport or land-use policies more evidence based:

    +

    E8. Sketch on paper ideas for a web-mapping application that could be used to make transport or land-use policies more evidence-based: