Proportional Symbol Mapping with R

IS415 Geospatial Analytics and Application

Instructor: Dr. Kam Tin Seong.

Assoc. Professor of Information Systems (Practice)

1. Overview

Proportional symbol maps / Graduate symbol maps - class of maps that use visual variable of size to represent differences in magnitude of a discrete value

Two types:

  • classed = graduated symbols (diff gradient of colour to show magnitude of discrete variable)
  • unclassed = proportional symbols (area of symbols are proportional to the discrete values)

2. Getting Started

packages = c('sf', 'tmap', 'tidyverse')
for (p in packages){
  if(!require(p, character.only = T)){
    install.packages(p)
  }
  library(p, character.only = T)
}

3. Geospatial Data Wrangling

Dataset - SGPools_svy21.csv, containing x-coords and y-coords of SingPools outlets and branches

sgpools <- read_csv("data/aspatial/SGPools_svy21.csv")
## Parsed with column specification:
## cols(
##   NAME = col_character(),
##   ADDRESS = col_character(),
##   POSTCODE = col_double(),
##   XCOORD = col_double(),
##   YCOORD = col_double(),
##   `OUTLET TYPE` = col_character(),
##   `Gp1Gp2 Winnings` = col_double()
## )
knitr::kable(head(sgpools))
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
SportsBuzz (PoMo) 1 Selegie Rd PoMo #01-01 Singapore 188306 188306 29776.95 31382.18 Branch 44
Prime Serangoon North Blk 542B Serangoon North Ave 3 #02-01 Singapore 552542 552542 32238.69 39518.76 Branch 0
Singapore Pools Woodlands Centre 1A Woodlands Centre Road #01-26 Singapore 731001 731001 21012.15 46987.32 Branch 3

Examining the tibble data frame using list(),

list(sgpools)
## [[1]]
## # A tibble: 306 x 7
##    NAME      ADDRESS       POSTCODE XCOORD YCOORD `OUTLET TYPE` `Gp1Gp2 Winning~
##    <chr>     <chr>            <dbl>  <dbl>  <dbl> <chr>                    <dbl>
##  1 Livewire~ 2 Bayfront A~    18972 30842. 29599. Branch                       5
##  2 Livewire~ 26 Sentosa G~    98138 26704. 26526. Branch                      11
##  3 SportsBu~ Lotus Lounge~   738078 20118. 44888. Branch                       0
##  4 SportsBu~ 1 Selegie Rd~   188306 29777. 31382. Branch                      44
##  5 Prime Se~ Blk 542B Ser~   552542 32239. 39519. Branch                       0
##  6 Singapor~ 1A Woodlands~   731001 21012. 46987. Branch                       3
##  7 Singapor~ Blk 64 Circu~   370064 33990. 34356. Branch                      17
##  8 Singapor~ Blk 88 Circu~   370088 33847. 33976. Branch                      16
##  9 Singapor~ Blk 308 Anch~   540308 33910. 41275. Branch                      21
## 10 Singapor~ Blk 202 Ang ~   560202 29246. 38943. Branch                      25
## # ... with 296 more rows

Since the sgpools is a tibble data frame and not the common R data frame,

It needs to be converted into a simple feature data frame by using st_as_sf() from the sf package

The st_as_sf() function requires:

  • coords argument = column name in string format of x-coordinates and y-coordinates
  • crs argument = coordinates system in EPSG format, EPSG 3413 is equal to Singapore SVY21 Projected Coordinate System (2D, while 3D is geographic coordinate system)
sgpools_sf <- st_as_sf(sgpools, coords = c('XCOORD','YCOORD'), crs=3414)
knitr::kable(head(sgpools_sf))
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)
SportsBuzz (PoMo) 1 Selegie Rd PoMo #01-01 Singapore 188306 188306 Branch 44 POINT (29776.95 31382.18)
Prime Serangoon North Blk 542B Serangoon North Ave 3 #02-01 Singapore 552542 552542 Branch 0 POINT (32238.69 39518.76)
Singapore Pools Woodlands Centre 1A Woodlands Centre Road #01-26 Singapore 731001 731001 Branch 3 POINT (21012.15 46987.32)

Examining the simple feature data frame using list(),

list(sgpools_sf)
## [[1]]
## Simple feature collection with 306 features and 5 fields
## geometry type:  POINT
## dimension:      XY
## bbox:           xmin: 7844.194 ymin: 26525.7 xmax: 45176.57 ymax: 47987.13
## projected CRS:  SVY21 / Singapore TM
## # A tibble: 306 x 6
##    NAME  ADDRESS POSTCODE `OUTLET TYPE` `Gp1Gp2 Winning~
##  * <chr> <chr>      <dbl> <chr>                    <dbl>
##  1 Live~ 2 Bayf~    18972 Branch                       5
##  2 Live~ 26 Sen~    98138 Branch                      11
##  3 Spor~ Lotus ~   738078 Branch                       0
##  4 Spor~ 1 Sele~   188306 Branch                      44
##  5 Prim~ Blk 54~   552542 Branch                       0
##  6 Sing~ 1A Woo~   731001 Branch                       3
##  7 Sing~ Blk 64~   370064 Branch                      17
##  8 Sing~ Blk 88~   370088 Branch                      16
##  9 Sing~ Blk 30~   540308 Branch                      21
## 10 Sing~ Blk 20~   560202 Branch                      25
## # ... with 296 more rows, and 1 more variable: geometry <POINT [m]>

4. Drawing Proportional Symbol Map

Firstly, turn on the interactive mode of tmap using view mode

tmap_mode("view")
## tmap mode set to interactive viewing
tm_shape(sgpools_sf)+
  tm_bubbles(col = "red", size = 1, border.col = "black", border.lwd = 1)

Notice that as you zoom, the size of the bubbles/points does not change, it looks too big when zoomed in, not proportional.

How do you draw a proportional map?

By assigning a numerical variable to the size argument in tm_bubbles() function

tm_shape(sgpools_sf)+
  tm_bubbles(col = "red", size = "Gp1Gp2 Winnings", border.col = "black", border.lwd = 0.1)
## Legend for symbol sizes not available in view mode.

How do we give colour to the proportional map?

By assigning a discrete variable to the col argument in the tm_bubbles() function

tm_shape(sgpools_sf)+
  tm_bubbles(col = "OUTLET TYPE", size = "Gp1Gp2 Winnings", alpha = 0.5, border.col = "green", border.lwd = 1)
## Legend for symbol sizes not available in view mode.

Faceted plots for proportional symbol map

tm_facets() function - can produce multiple maps with synchronized 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)
## Legend for symbol sizes not available in view mode.

End the tmap VIEW MODE to switch it back to tmap PLOT MODE

tmap_mode("plot")
## tmap mode set to plotting

Reference

Rpubs link