ETC5512

Australian election data

Lecturer: Kate Saunders

Department of Econometrics and Business Statistics


  • ETC5512.Clayton-x@monash.edu
  • Wild Caught Data
  • wcd.numbat.space


Today’s Lecture

What we’ll cover

  • Learn about Australian election data
  • Look at results from the last election
  • Learn how to visualise the election results spatially in a few ways

From a coding perspective:

  • This will require learning about spatial mapping in R.

  • You will also need to learn about different mapping projections

Australian Election Data

Australian Election Data


Important Information

  • Much like the census, the election attempts to collect the data from the population.

  • In Australia, it is compulsory by law to vote in elections if you are an Australian citizen or eligible British subject aged 18 years old or over and have lived in your address for at least one month.

  • The Australian Electoral Commission (AEC) is an independent federal agency in charge of federal Australian elections and provides the geographical boundaries of the electoral divisions.

Some questions


Quick quiz

  1. When was the last federal election in Australia?
  2. How often is the federal election conducted in Australia?
  3. How many electoral divisions are there in the last federal election?
  4. What is the population for the Australian federal election?

2022 Australian Federal Election

Aussie Politics

  • Parliament of Australia comprises two houses:
    • Senate (upper house) comprising 76 senators
    • House of Representatives (lower house) comprising 151 members
  • Government is formed by the party or coalition with majority of the seats in the lower house
  • The 2022 Australian Federal Election was held on Sat 21st May 2022
  • The next federal election will likely be held in the next few months!

Parties

Two major parties: Labour and the Coalition. Coalition combines Liberals and Nationals.

There are also minor parties like the Greens and One Nation, and Independents.

Ballots

  • House of Representatives uses the instant-runoff voting system
  • Senate uses the single transferable voting system
.

Data on Voter Counts

2022 Australian Federal Election Data

Let’s download some data

Go to https://results.aec.gov.au

Download the distribution of preferences by candidate by division for the 2022 Australian Federal Election

Select:

  1. 2022 federal election
  2. Downloads
  3. Distribution of preferences by candidate by division

Voting Data

House of Representatives

library(tidyverse)
votes <- read_csv("https://results.aec.gov.au/27966/Website/Downloads/HouseDopByDivisionDownload-27966.csv", skip = 1)
glimpse(votes)
Rows: 35,096
Columns: 14
$ StateAb          <chr> "ACT", "ACT", "ACT", "ACT", "ACT", "ACT", "ACT", "ACT…
$ DivisionID       <dbl> 318, 318, 318, 318, 318, 318, 318, 318, 318, 318, 318…
$ DivisionNm       <chr> "Bean", "Bean", "Bean", "Bean", "Bean", "Bean", "Bean…
$ CountNumber      <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,…
$ BallotPosition   <dbl> 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5,…
$ CandidateID      <dbl> 36239, 36239, 36239, 36239, 37455, 37455, 37455, 3745…
$ Surname          <chr> "CONWAY", "CONWAY", "CONWAY", "CONWAY", "AMBARD", "AM…
$ GivenNm          <chr> "Sean", "Sean", "Sean", "Sean", "Benjamin", "Benjamin…
$ PartyAb          <chr> "UAPP", "UAPP", "UAPP", "UAPP", "ON", "ON", "ON", "ON…
$ PartyNm          <chr> "United Australia Party", "United Australia Party", "…
$ Elected          <chr> "N", "N", "N", "N", "N", "N", "N", "N", "Y", "Y", "Y"…
$ HistoricElected  <chr> "N", "N", "N", "N", "N", "N", "N", "N", "Y", "Y", "Y"…
$ CalculationType  <chr> "Preference Count", "Preference Percent", "Transfer C…
$ CalculationValue <dbl> 2831.00, 2.88, 0.00, 0.00, 2680.00, 2.72, 0.00, 0.00,…

Electoral district of Monash

Let’s have a look at the electoral district named “Monash”

Rows: 224
Columns: 14
$ StateAb          <chr> "VIC", "VIC", "VIC", "VIC", "VIC", "VIC", "VIC", "VIC…
$ DivisionID       <dbl> 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 323…
$ DivisionNm       <chr> "Monash", "Monash", "Monash", "Monash", "Monash", "Mo…
$ CountNumber      <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,…
$ BallotPosition   <dbl> 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5,…
$ CandidateID      <dbl> 36561, 36561, 36561, 36561, 36737, 36737, 36737, 3673…
$ Surname          <chr> "MORGAN", "MORGAN", "MORGAN", "MORGAN", "BROADBENT", …
$ GivenNm          <chr> "Mat", "Mat", "Mat", "Mat", "Russell", "Russell", "Ru…
$ PartyAb          <chr> "GVIC", "GVIC", "GVIC", "GVIC", "LP", "LP", "LP", "LP…
$ PartyNm          <chr> "The Greens", "The Greens", "The Greens", "The Greens…
$ Elected          <chr> "N", "N", "N", "N", "Y", "Y", "Y", "Y", "N", "N", "N"…
$ HistoricElected  <chr> "N", "N", "N", "N", "Y", "Y", "Y", "Y", "N", "N", "N"…
$ CalculationType  <chr> "Preference Count", "Preference Percent", "Transfer C…
$ CalculationValue <dbl> 9533.00, 9.86, 0.00, 0.00, 36546.00, 37.79, 0.00, 0.0…

District: Monash

votes_monash <- votes |>
  # get the preference count only
  filter(CalculationType == "Preference Count") |>
  # get the Monash division
  filter(DivisionNm == "Monash")
glimpse(votes_monash)
Rows: 56
Columns: 14
$ StateAb          <chr> "VIC", "VIC", "VIC", "VIC", "VIC", "VIC", "VIC", "VIC…
$ DivisionID       <dbl> 323, 323, 323, 323, 323, 323, 323, 323, 323, 323, 323…
$ DivisionNm       <chr> "Monash", "Monash", "Monash", "Monash", "Monash", "Mo…
$ CountNumber      <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2,…
$ BallotPosition   <dbl> 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4, 5, 6, 7, 8, 1, 2,…
$ CandidateID      <dbl> 36561, 36737, 36065, 37629, 37637, 36455, 36914, 3603…
$ Surname          <chr> "MORGAN", "BROADBENT", "LEONARD", "HICKEN", "WELSH", …
$ GivenNm          <chr> "Mat", "Russell", "Deb", "Allan", "David Matthew", "J…
$ PartyAb          <chr> "GVIC", "LP", "IND", "ON", "CYA", "ALP", "LDP", "UAPP…
$ PartyNm          <chr> "The Greens", "Liberal", "Independent", "Pauline Hans…
$ Elected          <chr> "N", "Y", "N", "N", "N", "N", "N", "N", "N", "Y", "N"…
$ HistoricElected  <chr> "N", "Y", "N", "N", "N", "N", "N", "N", "N", "Y", "N"…
$ CalculationType  <chr> "Preference Count", "Preference Count", "Preference C…
$ CalculationValue <dbl> 9533, 36546, 10372, 7289, 674, 24759, 3548, 3991, 959…

Visualising the counts

Better

Order candidates by counts!!!

Winner:
Russel
Broadbent

Code

votes_monash_for_plotting |> 
  mutate(Surname = fct_reorder(Surname, CalculationValue, sum))  #<<

ggplot(votes_monahs_for_plotting) +
  geom_col(aes(x = CalculationValue, y = Surname)) +
  geom_text(aes(label = paste("Count", CountNumber + 1)),
    x = 10000, y = 3, size = 16, color = "#ee64a4", alpha = 0.4, hjust = "left"
  ) +
  facet_wrap(~CountNumber) + 
  theme_bw()

Where is the electoral district of Monash?

It doesn’t include Monash Clayton campus- Check here.

Electoral district of Hotham

Does include Monash Clayton campus - Check here.

Maps of Electoral Results

Australian Electorates Divisions

Australia electoral divisions in the 2022 election

There were 151 electorates in 2022.

The geographical boundaries of the electoral divisions are determined by the Redistribution Committee and are redrawn every so often to ensure similar number of electors in each electoral division for a given state or territory.

Electoral Boundaries

Warning!

Electoral boundaries can change across years

Break out discussion

  • Have any boundaries changed from 2022 to 2025?

  • If so which ones?

  • What would that mean for comparing election results between years?

GIS data

GIS

GIS stands for Geographic Information System.

GIS is a framework for capturing and inspecting geographical data.

Federal electoral boundary

Electoral Boundaries

“The Licensee must make End-users aware the data was sourced from the Australian Electoral Commission and is used under licence.”

Note: the federal electoral boundary is provided by Australian Electoral Commission
© Commonwealth of Australia (Australian Electoral Commission) 2025

  • Download the ESRI zip file for Victoria.

  • To work with spatial data, we use the sf R-package.

Working with spatial data

library(sf)
aec_map <- read_sf(here::here("data/vic-july-2021-esri/E_VIC21_region.shp")) |> st_simplify(dTolerance = 250)

head(aec_map)
Simple feature collection with 6 features and 9 fields
Geometry type: MULTIPOLYGON
Dimension:     XY
Bounding box:  xmin: 143.4412 ymin: -38.07451 xmax: 146.191 ymax: -36.38518
Geodetic CRS:  GDA94
# A tibble: 6 × 10
  E_div_numb Elect_div Numccds Actual Projected Total_Popu Australian Area_SqKm
       <dbl> <chr>       <dbl>  <dbl>     <dbl>      <dbl>      <dbl>     <dbl>
1          1 Aston         377 111098    115439          0          0      114.
2          2 Ballarat      340 106745    115696          0          0     5399.
3          3 Bendigo       351 108821    117818          0          0     5285.
4          4 Bruce         450 112619    116317          0          0      115.
5          5 Calwell       314  99781    116976          0          0      221.
6          6 Casey         425 114652    119870          0          0     2481.
# ℹ 2 more variables: Sortname <chr>, geometry <MULTIPOLYGON [°]>

Geometry object

aec_map$geometry[[1]]
MULTIPOLYGON (((145.3452 -37.85979, 145.3362 -37.85105, 145.3321 -37.85102, 145.3328 -37.84744, 145.3063 -37.84047, 145.3011 -37.83784, 145.281 -37.83314, 145.275 -37.83577, 145.2253 -37.83874, 145.2133 -37.84102, 145.2097 -37.85132, 145.2071 -37.85227, 145.2043 -37.85721, 145.1922 -37.87161, 145.1929 -37.88139, 145.2039 -37.89608, 145.2083 -37.89905, 145.2051 -37.90603, 145.2056 -37.92663, 145.2142 -37.93573, 145.2282 -37.95141, 145.2348 -37.94207, 145.2796 -37.9476, 145.2898 -37.95814, 145.289 -37.96284, 145.2934 -37.96398, 145.2999 -37.93146, 145.3038 -37.93259, 145.2964 -37.91047, 145.2928 -37.90734, 145.297 -37.90122, 145.305 -37.90571, 145.3113 -37.90091, 145.3219 -37.89818, 145.3043 -37.88546, 145.3061 -37.86902, 145.3039 -37.86285, 145.3169 -37.86321, 145.327 -37.8661, 145.3306 -37.86181, 145.3336 -37.86157, 145.339 -37.85695, 145.3426 -37.86133, 145.3452 -37.85979)))

Visualisation in ggplot

ggplot(data = aec_map) +
  geom_sf()

Combining election winners and map

winners <- votes |>
  # get the winner
  filter(Elected == "Y" & CountNumber == 0 & CalculationType == "Preference Count") |>
  # join the data
  right_join(aec_map, by = c("DivisionNm" = "Elect_div")) |>
  select(DivisionNm, PartyAb, PartyNm, geometry)

Combining election winners and map

ggplot(winners) +
  geom_sf(aes(fill = PartyAb, geometry = geometry))

Detective work

Caution

Watch out for mismatched Division Names

  • e.g. “McEwen” vs “Mcewen”

  • That caught me out last year, but it seems like its fixed.

  • For cases like these you might need fuzzy/partial string matching

  • Try agrepl() function

Using colors wisely

aus_colours <- c(
  "ALP" = "#DE3533", "LNP" = "#ADD8E6", "KAP" = "#8B0000",
  "GVIC" = "#10C25B", "XEN" = "#ff6300", "LP" = "#0047AB",
  "NP" = "#0a9cca", "IND" = "#000000", "GRN" = "#006400"
)

ggplot(winners) +
  geom_sf(aes(fill = PartyAb, geometry = geometry)) +
  scale_fill_manual(name = "Party", values = aus_colours) +
  theme_void() +
  theme(legend.position = "bottom")

Zoom

ggplot(winners) +
  geom_sf(aes(fill = PartyAb, geometry = geometry)) +
  scale_fill_manual(name = "Party", values = aus_colours) +
  theme_void() +
  theme(legend.position = "bottom") + 
  xlim(c(144.5,145.5)) + 
  ylim(c(-39,-37.5))

Traditional Maps

Reference:

Hex Maps

Reference:

Visualising Maps

Watch out

  • Traditional maps can be mislead you about election results

  • Larger areas don’t mean more votes

  • Better to give equal visual weight

Coordinate reference system (CRS)

Geographic coordinate reference systems

  • Geographic CRSs identify a location on the Earth’s surface by longitude and latitude.
  • Longitude is the East-West direction in angular distance from the Prime Meridian plane.
  • Latitude is the angular distance North or South of the equatorial plane.

Projected coordinate reference systems

  • All projected CRSs are based on a geographic CRS.
  • Map projections convert the three-dimensional surface of the Earth into Easting and Northing (x and y) values (typically meters) in a projected CRS.
  • These projected CRSs are based on Cartesian coordinates on a implicitly flat surface.
  • Some deformations are introduced in the process, e.g. area, direction, distance or shape, while preserving one or two of these properties.

Well Known Text (WKT)

  • Open Geospatial Consortium (OGC) developed an open standard format for describing CRSs called WKT
aus_map <- read_sf(here::here("data/2021-Cwlth_electoral_boundaries_ESRI/2021_ELB_region.shp")) |>
  sf::st_make_valid()|>
  sf::st_simplify(dTolerance = 1000)

sf::st_crs(aus_map)
Coordinate Reference System:
  User input: GDA94 
  wkt:
GEOGCRS["GDA94",
    DATUM["Geocentric Datum of Australia 1994",
        ELLIPSOID["GRS 1980",6378137,298.257222101,
            LENGTHUNIT["metre",1]]],
    PRIMEM["Greenwich",0,
        ANGLEUNIT["degree",0.0174532925199433]],
    CS[ellipsoidal,2],
        AXIS["geodetic latitude (Lat)",north,
            ORDER[1],
            ANGLEUNIT["degree",0.0174532925199433]],
        AXIS["geodetic longitude (Lon)",east,
            ORDER[2],
            ANGLEUNIT["degree",0.0174532925199433]],
    USAGE[
        SCOPE["Horizontal component of 3D system."],
        AREA["Australia including Lord Howe Island, Macquarie Island, Ashmore and Cartier Islands, Christmas Island, Cocos (Keeling) Islands, Norfolk Island. All onshore and offshore."],
        BBOX[-60.55,93.41,-8.47,173.34]],
    ID["EPSG",4283]]

GDA94 Map Projection

ggplot(aus_map) +
  geom_sf()

Changing map projections

  • Map projections may be modified in multiple methods (it’s beyond this unit to delve deep into this).

  • Below uses the Lambert azimuthal equal-area projection centered on the longitude and latitude of (rough) Melbourne coordinates via proj4string:

aus_map_transformed = aus_map |>
  sf::st_transform(crs = "+proj=laea +x_0=0 +y_0=0 +lon_0=145 +lat_0=-38")

ggplot(aus_map_transformed) +
  geom_sf(col = "forestgreen")

Wrap Up

Summary

Australian Election Case Study

  • We went through how to find and use data from the Australian election

  • This included how to deal with preferential voting counts

  • Learnt about how to plot maps in R using the sf package

  • This required learning about coordinate reference systems