House of Representatives - Preferences

Preferences are a key aspect of Australia’s preferential voting system. auspol includes two functions to interact with the preference distribution data:

  • get_house_preferences()
  • house_preference_flow_data()
  • house_preference_flow_plot()
  • get_house_2PF()
  • get_house_2PP()

What is this?

If you are unfamiliar with the Australian electoral system and preferential voting, please look at this explainer before proceeding.

Getting the data

get_house_preferences() - provides an interface to access preference flows for a particular division (electorate) on a given year, as published on the AEC’s website. For instance:

get_house_preferences("Wills",2019)
#> # A tibble: 6,120 × 16
#>     Year StateAb DivisionId DivisionNm  PPId PPNm   CountNum BallotPosition CandidateId Surname GivenNm           PartyAb PartyNm                 Sitti…¹ Calcu…² Calcu…³
#>    <dbl> <chr>        <int> <chr>      <int> <chr>     <int>          <int>       <int> <chr>   <chr>             <chr>   <chr>                   <chr>   <chr>     <dbl>
#>  1  2019 VIC            234 Wills          0 ABSENT        0              1       32688 MILES   Christopher James AJP     Animal Justice Party    N       Prefer…  254   
#>  2  2019 VIC            234 Wills          0 ABSENT        0              1       32688 MILES   Christopher James AJP     Animal Justice Party    N       Prefer…    4.65
#>  3  2019 VIC            234 Wills          0 ABSENT        0              1       32688 MILES   Christopher James AJP     Animal Justice Party    N       Transf…    0   
#>  4  2019 VIC            234 Wills          0 ABSENT        0              1       32688 MILES   Christopher James AJP     Animal Justice Party    N       Transf…    0   
#>  5  2019 VIC            234 Wills          0 ABSENT        0              2       32398 BOLTON  Susanne Alison    VNS     Victorian Socialists    N       Prefer…  238   
#>  6  2019 VIC            234 Wills          0 ABSENT        0              2       32398 BOLTON  Susanne Alison    VNS     Victorian Socialists    N       Prefer…    4.35
#>  7  2019 VIC            234 Wills          0 ABSENT        0              2       32398 BOLTON  Susanne Alison    VNS     Victorian Socialists    N       Transf…    0   
#>  8  2019 VIC            234 Wills          0 ABSENT        0              2       32398 BOLTON  Susanne Alison    VNS     Victorian Socialists    N       Transf…    0   
#>  9  2019 VIC            234 Wills          0 ABSENT        0              3       33251 KILLIN  Peter John        LP      Liberal Party of Austr… N       Prefer…  862   
#> 10  2019 VIC            234 Wills          0 ABSENT        0              3       33251 KILLIN  Peter John        LP      Liberal Party of Austr… N       Prefer…   15.8 
#> # … with 6,110 more rows, and abbreviated variable names ¹​SittingMemberFl, ²​CalculationType, ³​CalculationValue

Results can be also retrieved disaggregated by polling place:

get_house_preferences("Wills",2019,aggregation = FALSE) |> head(10)
#> # A tibble: 10 × 16
#>     Year StateAb DivisionId DivisionNm  PPId PPNm   CountNum BallotPosition CandidateId Surname GivenNm           PartyAb PartyNm                 Sitti…¹ Calcu…² Calcu…³
#>    <dbl> <chr>        <int> <chr>      <int> <chr>     <int>          <int>       <int> <chr>   <chr>             <chr>   <chr>                   <chr>   <chr>     <dbl>
#>  1  2019 VIC            234 Wills          0 ABSENT        0              1       32688 MILES   Christopher James AJP     Animal Justice Party    N       Prefer…  254   
#>  2  2019 VIC            234 Wills          0 ABSENT        0              1       32688 MILES   Christopher James AJP     Animal Justice Party    N       Prefer…    4.65
#>  3  2019 VIC            234 Wills          0 ABSENT        0              1       32688 MILES   Christopher James AJP     Animal Justice Party    N       Transf…    0   
#>  4  2019 VIC            234 Wills          0 ABSENT        0              1       32688 MILES   Christopher James AJP     Animal Justice Party    N       Transf…    0   
#>  5  2019 VIC            234 Wills          0 ABSENT        0              2       32398 BOLTON  Susanne Alison    VNS     Victorian Socialists    N       Prefer…  238   
#>  6  2019 VIC            234 Wills          0 ABSENT        0              2       32398 BOLTON  Susanne Alison    VNS     Victorian Socialists    N       Prefer…    4.35
#>  7  2019 VIC            234 Wills          0 ABSENT        0              2       32398 BOLTON  Susanne Alison    VNS     Victorian Socialists    N       Transf…    0   
#>  8  2019 VIC            234 Wills          0 ABSENT        0              2       32398 BOLTON  Susanne Alison    VNS     Victorian Socialists    N       Transf…    0   
#>  9  2019 VIC            234 Wills          0 ABSENT        0              3       33251 KILLIN  Peter John        LP      Liberal Party of Austr… N       Prefer…  862   
#> 10  2019 VIC            234 Wills          0 ABSENT        0              3       33251 KILLIN  Peter John        LP      Liberal Party of Austr… N       Prefer…   15.8 
#> # … with abbreviated variable names ¹​SittingMemberFl, ²​CalculationType, ³​CalculationValue

It is also possible to filter by Polling Place Name (PPNm in the source):

get_house_preferences("Wills",2019, polling_places=c("ABSENT"),aggregation = FALSE) |> head(10)
#> # A tibble: 10 × 16
#>     Year StateAb DivisionId DivisionNm  PPId PPNm   CountNum BallotPosition CandidateId Surname GivenNm           PartyAb PartyNm                 Sitti…¹ Calcu…² Calcu…³
#>    <dbl> <chr>        <int> <chr>      <int> <chr>     <int>          <int>       <int> <chr>   <chr>             <chr>   <chr>                   <chr>   <chr>     <dbl>
#>  1  2019 VIC            234 Wills          0 ABSENT        0              1       32688 MILES   Christopher James AJP     Animal Justice Party    N       Prefer…  254   
#>  2  2019 VIC            234 Wills          0 ABSENT        0              1       32688 MILES   Christopher James AJP     Animal Justice Party    N       Prefer…    4.65
#>  3  2019 VIC            234 Wills          0 ABSENT        0              1       32688 MILES   Christopher James AJP     Animal Justice Party    N       Transf…    0   
#>  4  2019 VIC            234 Wills          0 ABSENT        0              1       32688 MILES   Christopher James AJP     Animal Justice Party    N       Transf…    0   
#>  5  2019 VIC            234 Wills          0 ABSENT        0              2       32398 BOLTON  Susanne Alison    VNS     Victorian Socialists    N       Prefer…  238   
#>  6  2019 VIC            234 Wills          0 ABSENT        0              2       32398 BOLTON  Susanne Alison    VNS     Victorian Socialists    N       Prefer…    4.35
#>  7  2019 VIC            234 Wills          0 ABSENT        0              2       32398 BOLTON  Susanne Alison    VNS     Victorian Socialists    N       Transf…    0   
#>  8  2019 VIC            234 Wills          0 ABSENT        0              2       32398 BOLTON  Susanne Alison    VNS     Victorian Socialists    N       Transf…    0   
#>  9  2019 VIC            234 Wills          0 ABSENT        0              3       33251 KILLIN  Peter John        LP      Liberal Party of Austr… N       Prefer…  862   
#> 10  2019 VIC            234 Wills          0 ABSENT        0              3       33251 KILLIN  Peter John        LP      Liberal Party of Austr… N       Prefer…   15.8 
#> # … with abbreviated variable names ¹​SittingMemberFl, ²​CalculationType, ³​CalculationValue

Built on top of the basic functions, preference_flow_data() - provides an interface to access preference flows for a particular division (electorate) in a given year. This function returns a list, in which each element is a data frame with the results for each counting round. In its most basic use:

house_preference_flow_data(division = "Wills", year=2019)
#> $`Round 0`
#> # A tibble: 6 × 15
#>    Year StateAb DivisionId DivisionNm CountNum BallotPosition CandidateId Surname GivenNm           PartyAb PartyNm                         Prefe…¹ Trans…² Round…³ Last 
#>   <dbl> <chr>        <int> <chr>         <int>          <int>       <int> <chr>   <chr>             <chr>   <chr>                             <dbl>   <dbl>   <int> <lgl>
#> 1  2019 VIC            234 Wills             0              6       32350 KHALIL  Peter             ALP     Australian Labor Party (Victor…   42355       0       1 FALSE
#> 2  2019 VIC            234 Wills             0              4       32657 PULFORD Adam Ross         GVIC    The Australian Greens - Victor…   25575       0       2 FALSE
#> 3  2019 VIC            234 Wills             0              3       33251 KILLIN  Peter John        LP      Liberal Party of Australia (Vi…   17241       0       3 FALSE
#> 4  2019 VIC            234 Wills             0              2       32398 BOLTON  Susanne Alison    VNS     Victorian Socialists               4344       0       4 FALSE
#> 5  2019 VIC            234 Wills             0              1       32688 MILES   Christopher James AJP     Animal Justice Party               3596       0       5 FALSE
#> 6  2019 VIC            234 Wills             0              5       32329 VENKAT  Manju             UAPP    United Australia Party             2979       0       6 TRUE 
#> # … with abbreviated variable names ¹​`Preference Count`, ²​`Transfer Count`, ³​RoundPosition
#> 
#> $`Round 1`
#> # A tibble: 5 × 15
#>    Year StateAb DivisionId DivisionNm CountNum BallotPosition CandidateId Surname GivenNm           PartyAb PartyNm                         Prefe…¹ Trans…² Round…³ Last 
#>   <dbl> <chr>        <int> <chr>         <int>          <int>       <int> <chr>   <chr>             <chr>   <chr>                             <dbl>   <dbl>   <int> <lgl>
#> 1  2019 VIC            234 Wills             1              6       32350 KHALIL  Peter             ALP     Australian Labor Party (Victor…   43301     946       1 FALSE
#> 2  2019 VIC            234 Wills             1              4       32657 PULFORD Adam Ross         GVIC    The Australian Greens - Victor…   25811     236       2 FALSE
#> 3  2019 VIC            234 Wills             1              3       33251 KILLIN  Peter John        LP      Liberal Party of Australia (Vi…   18521    1280       3 FALSE
#> 4  2019 VIC            234 Wills             1              2       32398 BOLTON  Susanne Alison    VNS     Victorian Socialists               4511     167       4 FALSE
#> 5  2019 VIC            234 Wills             1              1       32688 MILES   Christopher James AJP     Animal Justice Party               3946     350       5 TRUE 
#> # … with abbreviated variable names ¹​`Preference Count`, ²​`Transfer Count`, ³​RoundPosition
#> 
#> $`Round 2`
#> # A tibble: 4 × 15
#>    Year StateAb DivisionId DivisionNm CountNum BallotPosition CandidateId Surname GivenNm        PartyAb PartyNm                            Prefe…¹ Trans…² Round…³ Last 
#>   <dbl> <chr>        <int> <chr>         <int>          <int>       <int> <chr>   <chr>          <chr>   <chr>                                <dbl>   <dbl>   <int> <lgl>
#> 1  2019 VIC            234 Wills             2              6       32350 KHALIL  Peter          ALP     Australian Labor Party (Victorian…   43982     681       1 FALSE
#> 2  2019 VIC            234 Wills             2              4       32657 PULFORD Adam Ross      GVIC    The Australian Greens - Victoria     27083    1272       2 FALSE
#> 3  2019 VIC            234 Wills             2              3       33251 KILLIN  Peter John     LP      Liberal Party of Australia (Victo…   19108     587       3 FALSE
#> 4  2019 VIC            234 Wills             2              2       32398 BOLTON  Susanne Alison VNS     Victorian Socialists                  5917    1406       4 TRUE 
#> # … with abbreviated variable names ¹​`Preference Count`, ²​`Transfer Count`, ³​RoundPosition
#> 
#> $`Round 3`
#> # A tibble: 3 × 15
#>    Year StateAb DivisionId DivisionNm CountNum BallotPosition CandidateId Surname GivenNm    PartyAb PartyNm                                Prefe…¹ Trans…² Round…³ Last 
#>   <dbl> <chr>        <int> <chr>         <int>          <int>       <int> <chr>   <chr>      <chr>   <chr>                                    <dbl>   <dbl>   <int> <lgl>
#> 1  2019 VIC            234 Wills             3              6       32350 KHALIL  Peter      ALP     Australian Labor Party (Victorian Bra…   45442    1460       1 FALSE
#> 2  2019 VIC            234 Wills             3              4       32657 PULFORD Adam Ross  GVIC    The Australian Greens - Victoria         30254    3171       2 FALSE
#> 3  2019 VIC            234 Wills             3              3       33251 KILLIN  Peter John LP      Liberal Party of Australia (Victorian…   20394    1286       3 TRUE 
#> # … with abbreviated variable names ¹​`Preference Count`, ²​`Transfer Count`, ³​RoundPosition
#> 
#> $`Round 4`
#> # A tibble: 2 × 15
#>    Year StateAb DivisionId DivisionNm CountNum BallotPosition CandidateId Surname GivenNm   PartyAb PartyNm                               Prefe…¹ Trans…² Round…³ Elected
#>   <dbl> <chr>        <int> <chr>         <int>          <int>       <int> <chr>   <chr>     <chr>   <chr>                                   <dbl>   <dbl>   <int> <lgl>  
#> 1  2019 VIC            234 Wills             4              6       32350 KHALIL  Peter     ALP     Australian Labor Party (Victorian Br…   55898   10456       1 TRUE   
#> 2  2019 VIC            234 Wills             4              4       32657 PULFORD Adam Ross GVIC    The Australian Greens - Victoria        40192    9938       2 FALSE  
#> # … with abbreviated variable names ¹​`Preference Count`, ²​`Transfer Count`, ³​RoundPosition

The function also includes other variables, which are better explained through its use as part of the next function, house_preference_flow_plot().

Plotting Preference flows.

Perhaps it is most interesting to see how each round of counting assigns votes until a candidate is chosen. This package comes with the convenience function house_preference_flow_plot(), which calls preference_flow_data() and plots the results in an alluvial format. Using the previous example:

house_preference_flow_plot(division = "Wills",year=2019) +
  labs(title="Preference Flow for Wills, 2019")

plot of chunk plot1

By default the vote is present as a percentage, which can be changed by changing the value of var:

house_preference_flow_plot(division = "Wills",year=2019,var="Preference Count") +
  labs(title="Preference Flow for Wills, 2019")

plot of chunk plot2

For analysis, it may be interesting to remove some parties from the initial round - e.g. to see how votes flow to the finalists. This can be done using exclude_parties:

house_preference_flow_plot(division = "Warringah",year=2022) +
  labs(title="Preference Flow for Warringah, 2022")

plot of chunk plot3

house_preference_flow_plot(division = "Warringah",year=2022, exclude_parties = c("LP","IND-STEGGALL")) +
  labs(title="Flow of preference votes to Liberal and Teal in Warringah, 2022")

plot of chunk plot4

Like the other plotting functions, it is possible to override the colour scheme by providing an additional named vector:

#adding teal
house_preference_flow_plot(division = "Warringah",year=2022, 
                     exclude_parties = c("LP","IND-STEGGALL"),
                     extra_colours = c("IND-STEGGALL"="#008080")) +
  labs(title="Flow of preference votes to Liberal and Teal in Warringah, 2022")

plot of chunk plot5

Similarly, it is possible to get the results of house_preference_flow_plot() directly, via include_data:

p <- house_preference_flow_plot(division = "Warringah",year=2022, 
                     exclude_parties = c("LP","IND-STEGGALL"),
                     extra_colours = c("IND-STEGGALL"="#008080"),
                     include_data=TRUE
                     )

p$source_data[[1]]
#> # A tibble: 5 × 15
#>    Year StateAb DivisionId DivisionNm CountNum BallotPosition CandidateId Surname     GivenNm       PartyAb PartyNm                         Prefe…¹ Trans…² Round…³ Last 
#>   <dbl> <chr>        <int> <chr>         <int>          <int>       <int> <chr>       <chr>         <chr>   <chr>                             <dbl>   <dbl>   <int> <lgl>
#> 1  2022 NSW            151 Warringah         0              6       36808 MICKLEBURGH David Edward  ALP     Australian Labor Party (N.S.W.…    7806       0       1 FALSE
#> 2  2022 NSW            151 Warringah         0              4       36675 GLANVILLE   Kristyn Maree GRN     The Greens NSW                     6910       0       2 FALSE
#> 3  2022 NSW            151 Warringah         0              3       36271 ROBERTSON   Andrew Colin  UAPP    United Australia Party             2202       0       3 FALSE
#> 4  2022 NSW            151 Warringah         0              1       37516 TRIPP       Steven Leslie ON      Pauline Hanson's One Nation        1980       0       4 FALSE
#> 5  2022 NSW            151 Warringah         0              7       36396 PATERSON    Kate Anne     AJP     Animal Justice Party               1475       0       5 TRUE 
#> # … with abbreviated variable names ¹​`Preference Count`, ²​`Transfer Count`, ³​RoundPosition

Flow from primary vote to last round

Although the last plot can be informative, The AEC also records how o understand how the votes have flowed from primary votes to the two last candidates. This can be accessed through get_house_2PF()

get_house_2PF(division = "Lingiari",year=2013,aggregation = TRUE)
#> # A tibble: 16 × 17
#>     Year StateAb DivisionId DivisionNm FromCandidateId FromCandidatePartyAb FromCandida…¹ FromC…² FromC…³ FromC…⁴ ToCan…⁵ ToCan…⁶ ToCan…⁷ ToCan…⁸ ToCan…⁹ ToCan…˟ Trans…˟
#>    <dbl> <chr>        <int> <chr>                <int> <chr>                <chr>         <chr>   <chr>     <int>   <int> <chr>   <chr>   <chr>   <chr>     <int>   <int>
#>  1  2013 NT             306 Lingiari             24971 IND                  Independent   GOULD   Alfred        3   28735 ALP     Austra… SNOWDON Warren        2     257
#>  2  2013 NT             306 Lingiari             24971 IND                  Independent   GOULD   Alfred        3   28827 CLP     Countr… MacFAR… Tina          9     170
#>  3  2013 NT             306 Lingiari             28006 CEC                  Citizens Ele… FLYNN   Peter         7   28735 ALP     Austra… SNOWDON Warren        2     138
#>  4  2013 NT             306 Lingiari             28006 CEC                  Citizens Ele… FLYNN   Peter         7   28827 CLP     Countr… MacFAR… Tina          9     123
#>  5  2013 NT             306 Lingiari             28016 IND                  Independent   EARLEY  Braedon       5   28735 ALP     Austra… SNOWDON Warren        2     986
#>  6  2013 NT             306 Lingiari             28016 IND                  Independent   EARLEY  Braedon       5   28827 CLP     Countr… MacFAR… Tina          9     822
#>  7  2013 NT             306 Lingiari             28555 GRN                  Australian G… HOAD    Rob           8   28735 ALP     Austra… SNOWDON Warren        2    2716
#>  8  2013 NT             306 Lingiari             28555 GRN                  Australian G… HOAD    Rob           8   28827 CLP     Countr… MacFAR… Tina          9     589
#>  9  2013 NT             306 Lingiari             28561 RUA                  Rise Up Aust… McCART… Regina        6   28735 ALP     Austra… SNOWDON Warren        2     756
#> 10  2013 NT             306 Lingiari             28561 RUA                  Rise Up Aust… McCART… Regina        6   28827 CLP     Countr… MacFAR… Tina          9     742
#> 11  2013 NT             306 Lingiari             28735 ALP                  Australian L… SNOWDON Warren        2   28735 ALP     Austra… SNOWDON Warren        2   17056
#> 12  2013 NT             306 Lingiari             28827 CLP                  Country Libe… MacFAR… Tina          9   28827 CLP     Countr… MacFAR… Tina          9   13605
#> 13  2013 NT             306 Lingiari             28849 ASP                  Shooters, Fi… RIGHTON Chris         1   28735 ALP     Austra… SNOWDON Warren        2    1864
#> 14  2013 NT             306 Lingiari             28849 ASP                  Shooters, Fi… RIGHTON Chris         1   28827 CLP     Countr… MacFAR… Tina          9    1197
#> 15  2013 NT             306 Lingiari             29433 IND                  Independent   GUYULA  Yingiy…       4   28735 ALP     Austra… SNOWDON Warren        2    1275
#> 16  2013 NT             306 Lingiari             29433 IND                  Independent   GUYULA  Yingiy…       4   28827 CLP     Countr… MacFAR… Tina          9     579
#> # … with abbreviated variable names ¹​FromCandidatePartyNm, ²​FromCandidateSurname, ³​FromCandidateGivenNm, ⁴​FromCandidateBallotPosition, ⁵​ToCandidateId,
#> #   ⁶​ToCandidatePartyAb, ⁷​ToCandidatePartyNm, ⁸​ToCandidateSurname, ⁹​ToCandidateGivenNm, ˟​ToCandidateBallotPosition, ˟​TransferCount

These results can be charted using house_2PF_plot(). This function can present the results either in an alluvial or bar chart format.

house_2PF_plot("Lingiari",2013,plot_format = "alluvial")

plot of chunk plot6

house_2PF_plot(division="Burt",
               year=2022,
               plot_format = "bar")

plot of chunk plot7

Two-party preferred

The AEC also publishes Two-Party-Preferred summaries (Coalition against Labor). These are available through * get_house_2PP()*, which allows filtering by division and year, and can be displayed by division or polling place

get_house_2PP(division = "Fraser",year=2004,aggregation = TRUE)
#> # A tibble: 1 × 9
#>    Year StateAb DivisionID DivisionNm `Liberal/National Coalition Votes` `Australian Labor Party Votes` TotalVotes `Liberal/National Coalition Percentage` Australian L…¹
#>   <dbl> <chr>        <int> <chr>                                   <int>                          <int>      <int>                                   <dbl>          <dbl>
#> 1  2004 ACT            102 Fraser                                  30546                          53134      83680                                   0.365          0.635
#> # … with abbreviated variable name ¹​`Australian Labor Party Percentage`

The package includes two plots to visualise this data. The first (house_2PP_comparison_plot()), displays the results for a given election, for one or many electorates.

house_2PP_comparison_plot(year=2022,state="VIC")

plot of chunk plot8

The second function - house_2PP_historical_plot() - shows the historical results for a given division.

house_2PP_historical_plot(division="Aston")

plot of chunk plot9