This is especially true when presenting spacial data. A well presented map can often communicate more effectively than data tables.

The Australian Marriage Law Postal Survey was an integral step towards legislating marriage equality in Australia.

This vignette will be using data from the ABS and the tmap library, to visualise the Australian Marriage Law Postal Vote response of Australian Federal Electoral Divisions. The focus of the vignette will be on presenting different maps and layers using the tmap package. Hence only a quick overview of the importing, cleaning and intial plotting of the dataset will be provided below.

Importing, cleaning and quick plotting

Libraries

library(tidyverse) #to cleaning data
library(rgdal) #read shapefile containing geospatial data
library(tmap) #create thematic maps

Importing voting data

The Australian Marriage Law Postal Survey Response data at a federal electorate division (FED) level can be found at http://stat.data.abs.gov.au/#.

Note: Using an API key for the SDMX did not import the federal electorate names (required for joining the data sets further along), hence to import the data set, I downloaded a csv file to load.

#load voting data
aus_vote_raw <- read_csv("AMLPS_RESP_2017_14082019213322035.csv")
glimpse(aus_vote_raw)
## Observations: 2,226
## Variables: 13
## $ RESPONSE_CAT                 <chr> "EP_TOT", "EP_CLR", "EP_NCLR", "E...
## $ Response                     <chr> "Eligible Participant - Total", "...
## $ MEASURE                      <dbl> 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, ...
## $ Measure                      <chr> "Number (No.)", "Number (No.)", "...
## $ REGIONTYPE                   <chr> "AUS", "AUS", "AUS", "AUS", "AUS"...
## $ `Geography Level`            <chr> "Australia", "Australia", "Austra...
## $ AEC_FED_2017                 <chr> "0", "0", "0", "0", "0", "0", "0"...
## $ `Federal Electoral Division` <chr> "Australia", "Australia", "Austra...
## $ TIME                         <dbl> 2017, 2017, 2017, 2017, 2017, 201...
## $ Year                         <dbl> 2017, 2017, 2017, 2017, 2017, 201...
## $ Value                        <dbl> 16006180.0, 12691234.0, 36686.0, ...
## $ `Flag Codes`                 <lgl> NA, NA, NA, NA, NA, NA, NA, NA, N...
## $ Flags                        <lgl> NA, NA, NA, NA, NA, NA, NA, NA, N...

Importing geospatial data

A shapefile is a geospatial vector dataform that stores the geometric location and attributes of geographical features.
The Australian Electoral Commission stores GIS files on Federal Electoral Boundaries at https://www.aec.gov.au/Electorates/gis/gis_datadownload.htm

#download and unzip the shapefile
download.file("https://www.aec.gov.au/Electorates/gis/files/national-esri-fe2019.zip", destfile = "Electorate_Boundaries.zip") 
unzip("Electorate_Boundaries.zip")

#read the shapefile using the `rgdal` library
aus_electorate_map <- readOGR(dsn = "COM_ELB_region.shp")
## OGR data source with driver: ESRI Shapefile 
## Source: "C:\Users\pfspl\Documents\R\STDS\AT1 - Vignette\COM_ELB_region.shp", layer: "COM_ELB_region"
## with 151 features
## It has 9 fields
## Integer64 fields read as strings:  Numccds Actual Projected Total_Popu Australian
#to easily read the data within the shapefile, convert the data section into a dataframe
aus_electorate_df <- as.data.frame(aus_electorate_map)
glimpse(aus_electorate_df)
## Observations: 151
## Variables: 9
## $ Elect_div  <fct> Bean, Canberra, Fenner, Lingiari, Solomon, Blair, B...
## $ State      <fct> ACT, ACT, ACT, NT, NT, QLD, QLD, QLD, QLD, QLD, QLD...
## $ Numccds    <fct> 351, 311, 274, 327, 223, 390, 352, 345, 364, 398, 4...
## $ Actual     <fct> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...
## $ Projected  <fct> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...
## $ Total_Popu <fct> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...
## $ Australian <fct> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...
## $ Area_SqKm  <dbl> 1.913970e+03, 3.122631e+02, 2.382121e+02, 1.348158e...
## $ Sortname   <fct> Bean, Canberra, Fenner, Lingiari, Solomon, BLAIR, B...

Cleaning voting data

#cleaning data
aus_vote_clean <- aus_vote_raw %>%
  select(-TIME, -Year, -`Flag Codes`,-Flags,-`Geography Level`,-Response) %>% #remove same/blank values
  spread(key = "RESPONSE_CAT", value = "Value") %>% #convert from long to wide data
  filter(MEASURE == 2)%>% #I have chosen to visualise % of votes in each FED rather than no. of votes
  dplyr::rename("Elect_div" = "Federal Electoral Division") #renamed to facilitate the joining of datasets

glimpse(aus_vote_clean)
## Observations: 159
## Variables: 12
## $ MEASURE      <dbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2...
## $ Measure      <chr> "Percentage (%)", "Percentage (%)", "Percentage (...
## $ REGIONTYPE   <chr> "AUS", "FED", "FED", "FED", "FED", "FED", "FED", ...
## $ AEC_FED_2017 <chr> "0", "ADEL", "ASTO", "BALL", "BANK", "BARK", "BAR...
## $ Elect_div    <chr> "Australia", "Adelaide", "Aston", "Ballarat", "Ba...
## $ EP_CLR       <dbl> 79.3, 81.2, 81.4, 81.4, 79.9, 76.8, 77.8, 79.0, 8...
## $ EP_NCLR      <dbl> 0.2, 0.2, 0.2, 0.3, 0.2, 0.2, 0.2, 0.2, 0.3, 0.3,...
## $ EP_NR        <dbl> 20.5, 18.6, 18.4, 18.3, 19.9, 23.0, 22.0, 20.8, 1...
## $ EP_TOT       <dbl> 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,...
## $ RESPCLR_N    <dbl> 38.4, 29.9, 38.0, 29.5, 55.1, 47.7, 56.4, 38.3, 2...
## $ RESPCLR_TOT  <dbl> 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,...
## $ RESPCLR_Y    <dbl> 61.6, 70.1, 62.0, 70.5, 44.9, 52.3, 43.6, 61.7, 7...

Joining the Voting Data to the Shapefile

Both the vote data and the map shapefile include a Federal Electoral Division attribute, hence the two data sets will be joined via this attribute.

#join the vote data to the electorate map by column Elect_div using the join function in diplyr
aus_electorate_map@data <- left_join(aus_electorate_map@data,aus_vote_clean,by = "Elect_div")

head(aus_electorate_map)
## class       : SpatialPolygonsDataFrame 
## features    : 6 
## extent      : 96.81694, 167.998, -35.92076, -10.41236  (xmin, xmax, ymin, ymax)
## crs         : +proj=longlat +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +no_defs 
## variables   : 20
## names       : Elect_div, State, Numccds, Actual, Projected, Total_Popu, Australian,  Area_SqKm, Sortname, MEASURE,        Measure, REGIONTYPE, AEC_FED_2017, EP_CLR, EP_NCLR, ... 
## min values  :      Bean,   ACT,     223,      0,         0,          0,          0,     190.61,     Bean,       2, Percentage (%),        FED,         BLAI,     50,     0.2, ... 
## max values  :   Solomon,   QLD,     390,      0,         0,          0,          0, 1348157.94,  Solomon,       2, Percentage (%),        FED,         SOLO,   83.1,     0.2, ...

Initial plot of Australian Federal Electoral Divisions

Using the quick thematic map (qtm) function in tmap, we can create a quick choropleth map, using colour to show the % of the population voting Yes.

qtm(aus_electorate_map, fill = "RESPCLR_Y")

Note: the Yes % refers to number of yes votes relative to the total number of clear responses received from the survey.

tmap Plotting

Thematic maps are designed to empahsise a topic or theme, using geographic information as reference points.
The tmap package allows for easy and flexible creation of thematic maps.

There are two plotting modes in tmap:"plot" - to create static maps and "view" - to create interactive maps. We will focus on creating static maps below.

Static tmap

There are a multitude of adjustments you can make to the base map. ?'tmap-element' will provide the complete list of elements for each layer and outline their functions.

The code below is just an example of many formatting changes you can make to the map.

tmap_mode("plot")                                          #static map
## tmap mode set to plotting
tm_shape(aus_electorate_map)+
  tm_polygons("RESPCLR_Y",                                 #determines fill
              title = "Yes %",                             #legend title
              border.col = "saddlebrown")+                 #border colour of polygons
  
  #general level layout attributes
  tm_layout(title = "Australian Marriage Law 
            \nPostal Vote",                                #title inside the map border (\n for new line)
            title.color = "midnightblue",                  
            bg.color = ("whitesmoke"))+                    #background map colour
  
  #format the map legend
  tm_legend(legend.title.color = "white",
            legend.title.size = 1.2,
            legend.text.color = "white",
            legend.text.size = .8,
            legend.width = 2,                              #adjust width of legend for text size
            legend.position = c("right","top"),
            legend.bg.color = "slategray",
            legend.bg.alpha = 0.8)+                        #transparency of legend background colour
  
  #create a compass on the map
  tm_compass(north = 0,                                    #direction of north compass
             type = "8star",
             size = 4,                                     #size of the compass
             position = c("right","bottom"),
             color.dark = "dimgray",                       #colour of shaded parts of compass
             text.color = "dimgray")

Facet tmap

The tmap package also allows to facet maps by multiple variables or by splitting the spatial data. This can be both a static and interactive map!
Below is an example of a static facet by multiple variables on the state of Tasmania.
Note: A limit of 4 facets in an interactive map

tmap_mode("plot")                                    #static map
## tmap mode set to plotting
aus_TAS_electoral_map <- aus_electorate_map[aus_electorate_map@data$State == "TAS",] #Tasmanian dataset

tm_shape(aus_TAS_electoral_map)+
  tm_polygons(c("RESPCLR_Y","EP_CLR"),               #variables to facet by
              palette= list("Blues","Purples"),      #allows different palettes for each variable
              title = c("% Responded","% Yes"))+     #legend title for each facet
  tm_layout(main.title = "Australian Marriage Law Postal Vote - Tasmania", #title above the map
            main.title.position = "center",
            main.title.color = "darkblue",
            panel.show = TRUE,                       #show panels at the top of each facet
            panel.labels = c("% of clear responses","% voted yes"),
            panel.label.color = "white",             
            panel.label.bg.color = "midnightblue")+
  tm_legend(legend.bg.color = "dimgray",
            legend.text.color = "white",
            legend.title.color = "white")

Note: The aus_electorate_map already had the voting data joined to it, so filtering on just the state of Tasmania will include the voting data for the state.

Multiple layer tmap

tmap also allows you to create maps with multiple layers from different data sources. As an example, the map below includes two additional data sets from tmaps.

data(metro) #adding an additional dataset from tmap to show layering
data(rivers) #adding an additional dataset from tmap to show layering

tmap_mode("plot")
## tmap mode set to plotting
  tm_shape(aus_electorate_map)+
    tm_polygons("RESPCLR_Y",
              title = "Yes %",    
              alpha = 0.85)+       #transparency of the polygon
    tm_shape(metro)+               #add another layer to the interactive map
    tm_bubbles(size = "pop2020",   #maps the points on the second layer
             col = "deeppink",     #fill colour of the shapes
             scale = 5,            #magnifies the size of the points
             alpha = 0.7,
             title.size = "2020 Population",  # rename legend of population
             legend.size.is.portrait = TRUE)+ #shows population legend stacked
    tm_shape (rivers)+             #add another layer to the interactive map
    tm_lines("blue")+              #line colour
    tm_legend(legend.position = c("left","bottom"))

Conclusion

The tmap package is great for visualising spatial data and creating thematic plots, both static and interactive.