pacman::p_load(sf, tmap, tidyverse)Hands-on Exercise 8.2 - Visualising Geospatial Point Data
1. Overview
Proportional symbol maps (also called graduated symbol maps) use symbol size to represent variations in the magnitude of a discrete, rapidly changing phenomenon, such as population counts. Similar to choropleth maps, they can be classed or unclassed:
Classed (Range-Graded or Graduated Symbols): Symbols are grouped into predefined size categories.
Unclassed (Proportional Symbols): Symbol areas are directly proportional to the mapped attribute values.
In this hands-on exercise, you will learn to create a proportional symbol map in R using the tmap package to visualize the number of wins at Singapore Pools’ outlets.
2. Getting Started
The below code chunk use p_load() to load in the relevant R packages.
3. Geospatial Data Wrangling
3.1. The Data
This hands-on exercise use a dataset called SGPools_svy21.csv.
The dataset consists of seven columns, where the XCOORD and YCOORD columns are the x-coordinates and y-coordinates of SingPools outlets and branches in Singapore SVY21 Projected Coordinates System.
3.2. Data Import and Preparation
The code chunk below uses read_csv() function of readr package to import SGPools_svy21.csv into R as a tibble data frame.
sgpools <- read_csv("data/aspatial/SGPools_svy21.csv")After importing the data file into R, we use list() to examine if the data file has been imported correctly.
list(sgpools) [[1]]
# A tibble: 306 × 7
NAME ADDRESS POSTCODE XCOORD YCOORD `OUTLET TYPE` `Gp1Gp2 Winnings`
<chr> <chr> <dbl> <dbl> <dbl> <chr> <dbl>
1 Livewire (Mar… 2 Bayf… 18972 30842. 29599. Branch 5
2 Livewire (Res… 26 Sen… 98138 26704. 26526. Branch 11
3 SportsBuzz (K… Lotus … 738078 20118. 44888. Branch 0
4 SportsBuzz (P… 1 Sele… 188306 29777. 31382. Branch 44
5 Prime Serango… Blk 54… 552542 32239. 39519. Branch 0
6 Singapore Poo… 1A Woo… 731001 21012. 46987. Branch 3
7 Singapore Poo… Blk 64… 370064 33990. 34356. Branch 17
8 Singapore Poo… Blk 88… 370088 33847. 33976. Branch 16
9 Singapore Poo… Blk 30… 540308 33910. 41275. Branch 21
10 Singapore Poo… Blk 20… 560202 29246. 38943. Branch 25
# ℹ 296 more rows
3.3. Creating a sf data frame from an aspatial data frame
The code chunk below converts sgpools data frame into a simple feature data frame using st_as_sf() of sf packages.
sgpools_sf <- st_as_sf(sgpools,
coords = c("XCOORD", "YCOORD"),
crs= 3414)Key Takeaways from the arguments above:
coordsArgument: The column name for x-coordinates must be specified first, followed by the y-coordinates.crsArgument: Requires the coordinate system in EPSG format. For example, EPSG:3414 represents Singapore’s SVY21 Projected Coordinate System. You can find EPSG codes for other countries at epsg.io.
The basic information of the newly created sgpools_sf can be displayed as below.
list(sgpools_sf)[[1]]
Simple feature collection with 306 features and 5 fields
Geometry type: POINT
Dimension: XY
Bounding box: xmin: 7844.194 ymin: 26525.7 xmax: 45176.57 ymax: 47987.13
Projected CRS: SVY21 / Singapore TM
# A tibble: 306 × 6
NAME ADDRESS POSTCODE `OUTLET TYPE` `Gp1Gp2 Winnings`
* <chr> <chr> <dbl> <chr> <dbl>
1 Livewire (Marina Bay Sands) 2 Bayf… 18972 Branch 5
2 Livewire (Resorts World Sen… 26 Sen… 98138 Branch 11
3 SportsBuzz (Kranji) Lotus … 738078 Branch 0
4 SportsBuzz (PoMo) 1 Sele… 188306 Branch 44
5 Prime Serangoon North Blk 54… 552542 Branch 0
6 Singapore Pools Woodlands C… 1A Woo… 731001 Branch 3
7 Singapore Pools 64 Circuit … Blk 64… 370064 Branch 17
8 Singapore Pools 88 Circuit … Blk 88… 370088 Branch 16
9 Singapore Pools Anchorvale … Blk 30… 540308 Branch 21
10 Singapore Pools Ang Mo Kio … Blk 20… 560202 Branch 25
# ℹ 296 more rows
# ℹ 1 more variable: geometry <POINT [m]>
The output shows that sgppols_sf is in point feature class with epsg ID = 3414. The bbox provides information of the extend of the geospatial data.
4. Drawing Proportional Symbol Map
First we turn on the view mode of tmap.
tmap_mode("view")4.1. It all started with an interactive point symbol map
The code chunks below creates an interactive point symbol map.
tm_shape(sgpools_sf)+
tm_bubbles(col = "red",
size = 1,
border.col = "black",
border.lwd = 1)4.2. Lets make it proportional
Next we need to assign a numerical variable to the size visual attribute. The code chunk below assigns Gp1Gp2Winnings size visual attribute.
tm_shape(sgpools_sf)+
tm_bubbles(col = "red",
size = "Gp1Gp2 Winnings",
border.col = "black",
border.lwd = 1)4.3. Lets give it a different colour
The proportional symbol map can be further improved by using the colour visual attribute. The code chunks below assignes OUTLET_TYPE as the colour attribute variable.
tm_shape(sgpools_sf)+
tm_bubbles(col = "OUTLET TYPE",
size = "Gp1Gp2 Winnings",
border.col = "black",
border.lwd = 1)4.4. I have a twin brothers :)
Tmap’s view mode also works with faceted plots. The argument sync in tm_facets() can be used in this case to produce multiple maps with synchronised zoom and pan settings.
tm_shape(sgpools_sf) +
tm_bubbles(col = "OUTLET TYPE",
size = "Gp1Gp2 Winnings",
border.col = "black",
border.lwd = 1) +
tm_facets(by= "OUTLET TYPE",
nrow = 1,
sync = TRUE)Before ending the session, we switch tmap’s view back to plot mode using the code chunk below.
tmap_mode("plot")