Hands-on Exercise 7b: Visualising Geospatial Point Data

Published

February 20, 2024

Modified

February 21, 2024

1 Overview

Proportional symbol maps (also known as graduate symbol maps) are a class of maps that use the visual variable of size to represent differences in the magnitude of a discrete, abruptly changing phenomenon, e.g. counts of people. Like choropleth maps, you can create classed or unclassed versions of these maps. The classed ones are known as range-graded or graduated symbols, and the unclassed are called proportional symbols, where the area of the symbols are proportional to the values of the attribute being mapped. In this hands-on exercise, we learn how to create a proportional symbol map showing the number of wins by Singapore Pools’ outlets using tmap.

2 Getting Started

In this exercise, we will be using the following packages:

Package Description
tmap For choropleth mapping.
tidyverse

readr: For importing delimited text file.

tidyr: For tidying data.

dplyr: For data wrangling.

sf For handling geospatial data.
knitr For html tables
pacman::p_load(sf, tmap, tidyverse)

3 Geospatial Data Wrangling

3.1 The Data

The data set use for this hands-on exercise is called SGPools_svy21. The data is in csv file format.

It consists of seven columns. The XCOORD and YCOORD columns are the x-coordinates and y-coordinates of SingPools outlets and branches. They are in Singapore SVY21 Projected Coordinates System.

3.2 Data Import and Preparation

Function Package Description Output
read_csv() readr Import SGPools_svy21.csv into R Tibble data frame
sgpools <- read_csv("data/aspatial/SGPools_svy21.csv")

Let’s examine if the datafile has been imported correctly:

[[1]]
# A tibble: 5 × 7
  NAME            ADDRESS POSTCODE XCOORD YCOORD `OUTLET TYPE` `Gp1Gp2 Winnings`
  <chr>           <chr>      <dbl>  <dbl>  <dbl> <chr>                     <dbl>
1 Livewire (Mari… 2 Bayf…    18972 30842. 29599. Branch                        5
2 Livewire (Reso… 26 Sen…    98138 26704. 26526. Branch                       11
3 SportsBuzz (Kr… Lotus …   738078 20118. 44888. Branch                        0
4 SportsBuzz (Po… 1 Sele…   188306 29777. 31382. Branch                       44
5 Prime Serangoo… Blk 54…   552542 32239. 39519. Branch                        0

3.3 Creating a sf data frame from an aspatial data frame

Function Package Description Output
st_as_sf() sf Converts sgpools data frame into a simple feature data frame Simple feature
sgpools_sf <- st_as_sf(sgpools, 
                       coords = c("XCOORD", "YCOORD"),
                       crs= 3414)

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]>

Things to learn from the arguments above:

  • The coords argument requires you to provide the column name of the x-coordinates first then followed by the column name of the y-coordinates.

  • The crs argument required you to provide the coordinates system in epsg format. EPSG: 3414 is Singapore SVY21 Projected Coordinate System. You can search for other country's epsg code by refering to epsg.io.

Quick Comparison of the 2 datasets:

NAME ADDRESS POSTCODE XCOORD YCOORD OUTLET TYPE Gp1Gp2 Winnings
Livewire (Marina Bay Sands) 2 Bayfront Avenue, #01-01 The Shoppes at Marina Bay Sands Singapore 018972 18972 30841.56 29598.56 Branch 5
Livewire (Resorts World Sentosa) 26 Sentosa Gateway #B1-208 Singapore 098138 98138 26703.87 26525.70 Branch 11
SportsBuzz (Kranji) Lotus Lounge, Level 2, 1 Turf Club Avenue Singapore Racecourse Singapore 738078 738078 20117.93 44888.06 Branch 0
NAME ADDRESS POSTCODE OUTLET TYPE Gp1Gp2 Winnings geometry
Livewire (Marina Bay Sands) 2 Bayfront Avenue, #01-01 The Shoppes at Marina Bay Sands Singapore 018972 18972 Branch 5 POINT (30841.56 29598.56)
Livewire (Resorts World Sentosa) 26 Sentosa Gateway #B1-208 Singapore 098138 98138 Branch 11 POINT (26703.87 26525.7)
SportsBuzz (Kranji) Lotus Lounge, Level 2, 1 Turf Club Avenue Singapore Racecourse Singapore 738078 738078 Branch 0 POINT (20117.93 44888.06)

4 Drawing Proportional Symbol Map

To create an interactive proportional symbol map in R, the view mode of tmap will be used.

The code chunk below will turn on the interactive mode of tmap.

tmap_mode("view")

4.1 Interactive Point Symbol Map

tm_basemap("OpenStreetMap") +
tm_shape(sgpools_sf)+
tm_bubbles(col = "salmon",
           size = 1,
           border.col = "black",
           border.lwd = 1,
           alpha = 0.7)

4.2 Proportional Symbols

To draw a proportional symbol map, we need to assign a numerical variable to the size visual attribute. The code chunks below show that the variable Gp1Gp2Winnings is assigned to size visual attribute.

tm_basemap("OpenStreetMap") +
tm_shape(sgpools_sf)+
tm_bubbles(col = "salmon",
           size = "Gp1Gp2 Winnings",
           border.col = "black",
           border.lwd = 1,
           alpha = 0.7)

4.3 Qualitative Colours

A continuous variable is mapped to size while a categorical variable is mapped to colour.

tm_basemap("OpenStreetMap") +
tm_shape(sgpools_sf)+
tm_bubbles(col = "OUTLET TYPE", 
          size = "Gp1Gp2 Winnings",
          border.col = "black",
          border.lwd = 1,
          alpha = 0.7)

4.4 Coordinated Facet

The argument sync in tm_facets() can be used to produce multiple maps with synchronised zoom and pan settings.

tm_basemap("OpenStreetMap") +
tm_shape(sgpools_sf) +
  tm_bubbles(col = "OUTLET TYPE", 
          size = "Gp1Gp2 Winnings",
          border.col = "black",
          border.lwd = 1,
          id = "Name",
          popup.vars=c("Name: " = "NAME",
                       "Address: " = "ADDRESS",
                       "Winnings: " = "Gp1Gp2 Winnings")
          ) +
  tm_facets(by= "OUTLET TYPE",
            nrow = 1,
            sync = TRUE)

Switch tmap’s Viewer back to plot mode to revert settings back to default.

tmap_mode("plot")

7 Reference