Hands-on Exercise 7b: Visualising Geospatial Point Data

Author

Vanessa Heng

Published

February 28, 2024

Modified

March 9, 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, we can create classed or unclassed versions of these maps. The classed ones are known as range-graded or graduated symbols, and the unclassed ones are called proportional symbols, where the area of the symbols is proportional to the values of the attribute being mapped.

In this exercise, we will learn how to create a proportional symbol map showing the number of wins by Singapore Pools’ outlets using an R package called tmap.

In this exercise, we will do the following tasks:

  • To import an aspatial data file into R.

  • To convert it into a simple point feature data frame and at the same time, to assign an appropriate projection reference to the newly created simple point feature data frame.

  • To plot interactive proportional symbol maps.

2 Getting Started

2.1 Installing and loading the packages

For this exercise, the following R packages will be used:

  • sf for handling geospatial data.
pacman::p_load(sf, tmap, tidyverse)

2.2 Data import

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

sgpools <- read_csv("data/aspatial/SGPools_svy21.csv")
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
head(sgpools, 5)
# 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

The data consists 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.

Note

sgpools data in tibble data frame and not the common R data frame.

2.2.1 Creating a sf data frame from an aspatial data frame

The code chunk below converts sgpools data frame into a simple feature data frame by using st_as_sf() of sf packages

sgpools_sf <- st_as_sf(sgpools, 
                       coords = c("XCOORD", "YCOORD"),
                       crs= 3414)
Note
  • coords argument: states the column name of the x-coordinates first then followed by the column name of the y-coordinates.

  • crs argument: states the coordinates system in epsg format. EPSG: 3414 is Singapore SVY21 Projected Coordinate System. For other country’s epsg code, we can check out here epsg.io.

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

We can see that the data table of sgpools_sf has a new column called geometry.

3 Drawing Proportional Symbol Map

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

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

tmap_mode("view")

The code chunks below are used to create an interactive point symbol map.

tm_shape(sgpools_sf) + 
  tm_bubbles(col = "red", size = 1, border.col = "black", border.lwd = 1)

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_shape(sgpools_sf)+
tm_bubbles(col = "red",
           size = "Gp1Gp2 Winnings",
           border.col = "black",
           border.lwd = 1)

The proportional symbol map can be further improved by using the colour visual attribute. In the code chunks below, OUTLET_TYPE variable is used as the colour attribute variable.

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

An impressive and little-know feature of tmap’s view mode is that it also works with faceted plots. The argument sync in tm_facets() can be used 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)

Finally, it is wiser to switch tmap’s Viewer back to plot mode by using the code chunk below.

tmap_mode("plot")

4 Reference

4.1 All about tmap package

4.2 Geospatial data wrangling

4.3 Data wrangling