Nzelect
New Zealand election and census results data in convenient form of two R packages - nzelect and nzcensus
Install / Use
/learn @ellisp/NzelectREADME
nzelect and nzcensus
New Zealand election results, polling data and census results data in convenient form of two R packages. Each of the two packages can be installed separately, but they have been developed together and get good results working together.
Installation
nzelect is on CRAN, but nzcensus is too large so will remain on GitHub only.
# install stable version of nzelect from CRAN:
install.packages("nzelect")
# or install dev version of nzelect (with the very latest data) from GitHub:
devtools::install_github("ellisp/nzelect/pkg1")
# install nzcensus from GitHub:
devtools::install_github("ellisp/nzelect/pkg2")
library(nzelect)
library(nzcensus)
nzelect
Caveat and disclaimer
The New Zealand Electoral Commission had no involvement in preparing this package and bear no responsibility for any errors. In the event of any uncertainty, refer to the definitive source materials on their website.
nzelect is a very small voluntary project. Please report any issues or bugs on GitHub.
Usage - 2002 to 2017 results by voting place
The election results are available in two main data frames:
distinct_voting_placeshas one row for each distinct voting place that could be located in a geographical pointnzgehas one row for each combination of election year, voting place, party, electorate and voting type (Party or Candidate).
The voting_place_id column is shared between distinct_voting_places and nzge and is the only column that should be used to join the two.
Overall results
The code below replicates the published results for the 2011 election at http://www.electionresults.govt.nz/electionresults_2011/e9/html/e9_part1.html
library(nzelect)
library(tidyr)
library(dplyr)
nzge %>%
filter(election_year == 2011) %>%
mutate(voting_type = paste0(voting_type, " Vote")) %>%
group_by(party, voting_type) %>%
summarise(votes = sum(votes)) %>%
spread(voting_type, votes) %>%
ungroup() %>%
arrange(desc(`Party Vote`))
## `summarise()` regrouping output by 'party' (override with `.groups` argument)
## # A tibble: 25 x 3
## party `Candidate Vote` `Party Vote`
## <chr> <dbl> <dbl>
## 1 National Party 1027696 1058636
## 2 Labour Party 762897 614937
## 3 Green Party 155492 247372
## 4 New Zealand First Party 39892 147544
## 5 Conservative Party 51678 59237
## 6 Maori Party 39320 31982
## 7 Mana 29872 24168
## 8 ACT New Zealand 31001 23889
## 9 Informal Party Votes NA 19872
## 10 United Future 18792 13443
## # ... with 15 more rows
Comparing party and candidate votes of several parties
library(ggplot2, quietly = TRUE)
library(scales, quietly = TRUE)
library(GGally, quietly = TRUE) # for ggpairs
library(dplyr)
proportions <- nzge %>%
filter(election_year == 2014) %>%
group_by(voting_place, voting_type) %>%
summarise(`proportion Labour` = sum(votes[party == "Labour Party"]) / sum(votes),
`proportion National` = sum(votes[party == "National Party"]) / sum(votes),
`proportion Greens` = sum(votes[party == "Green Party"]) / sum(votes),
`proportion NZF` = sum(votes[party == "New Zealand First Party"]) / sum(votes),
`proportion Maori` = sum(votes[party == "Maori Party"]) / sum(votes))
## `summarise()` regrouping output by 'voting_place' (override with `.groups` argument)
ggpairs(proportions, aes(colour = voting_type), columns = 3:5)

Geographical location of voting places
These are available from 2008 onwards and can be obtained by joining the nzge and distinct_voting_places data frames by the voting_place_id column.
library(ggthemes) # for theme_map()
nzge %>%
filter(voting_type == "Party" & election_year == 2014) %>%
group_by(voting_place_id, election_year) %>%
summarise(proportion_national = sum(votes[party == "National Party"] / sum(votes))) %>%
left_join(distinct_voting_places, by = c("voting_place_id")) %>%
mutate(mostly_national = ifelse(proportion_national > 0.5,
"Mostly voted National", "Mostly didn't vote National")) %>%
ggplot(aes(x = longitude, y = latitude, colour = proportion_national)) +
geom_point() +
facet_wrap(~mostly_national) +
coord_map() +
borders("nz") +
scale_colour_gradient2(label = percent, mid = "grey80", midpoint = 0.5) +
theme_map() +
theme(legend.position = c(0.04, 0.5)) +
ggtitle("Voting patterns in the 2014 General Election\n")
## `summarise()` regrouping output by 'voting_place_id' (override with `.groups` argument)
## Warning: Removed 1 rows containing missing values (geom_point).

See this detailed interactive map of of the 2014 general election built as a side product of this project.
Rolling up results to Regional Council, Territorial Authority, or Area Unit
Because this package matches the location people actually voted with to boundaries of Regional Council, Territorial Authority and Area Unit it's possible to roll up voting behaviour to those categories. However, a large number of votes cannot be located this way. And it needs to be remembered that people are not necessarily voting near their normal place of residence.
nzge %>%
filter(election_year == 2017) %>%
filter(voting_type == "Party") %>%
left_join(distinct_voting_places, by = "voting_place_id") %>%
group_by(REGC2014_N) %>%
summarise(
total_votes = sum(votes),
proportion_national = round(sum(votes[party == "National Party"]) / total_votes, 3)) %>%
arrange(proportion_national)
## `summarise()` ungrouping output (override with `.groups` argument)
## # A tibble: 17 x 3
## REGC2014_N total_votes proportion_national
## <chr> <dbl> <dbl>
## 1 Gisborne Region 19402 0.347
## 2 Nelson Region 25317 0.354
## 3 <NA> 462345 0.376
## 4 Wellington Region 254815 0.386
## 5 West Coast Region 15959 0.393
## 6 Northland Region 79713 0.404
## 7 Otago Region 112242 0.408
## 8 Manawatu-Wanganui Region 113102 0.431
## 9 Tasman Region 29183 0.432
## 10 Hawke's Bay Region 79729 0.442
## 11 Bay of Plenty Region 140818 0.466
## 12 Canterbury Region 282927 0.48
## 13 Auckland Region 656654 0.483
## 14 Marlborough Region 24602 0.491
## 15 Taranaki Region 56442 0.494
## 16 Waikato Region 201022 0.496
## 17 Southland Region 48417 0.523
# what are some of those NA Regions?:
nzge %>%
filter(voting_type == "Party" & election_year == 2017) %>%
left_join(distinct_voting_places, by = c("voting_place_id")) %>%
filter(is.na(REGC2014_N)) %>%
group_by(voting_place) %>%
summarise(total_votes = sum(votes))
## `summarise()` ungrouping output (override with `.groups` argument)
## # A tibble: 395 x 2
## voting_place total_votes
## <chr> <dbl>
## 1 Advance Voting Place - Mobile Team 210
## 2 Ashburton Hospital & Rest Homes Team - Taken in Rangitata 310
## 3 Auckland Hospital Mobile & Advance Voting 816
## 4 Central Mobile Team 212
## 5 Chatham Islands Council Building, 9 Tuku Road, Waitangi 230
## 6 Christchurch Mobile Voting Facility One, Central Christchurch and South City Mall 982
## 7 Defence Force Team, Powles Road 94
## 8 Duvauchelle Community Centre, Main Road 185
## 9 Herald Island Community Hall, 57 Ferry Parade 274
## 10 Hospital & Rest Homes - Team 1 - Taken in New Plymouth 643
## # ... with 385 more rows
nzge %>%
filter(voting_type == "Party" & election_year == 2017) %>%
left_join(distinct_voting_places, by = "voting_place_id") %>%
group_by(TA2014_NAM) %>%
summarise(
total_votes = sum(votes),
proportion_national = round(sum(votes[party == "National Party"]) / total_votes, 3)) %>%
arrange(desc(proportion_national)) %>%
mutate(TA = ifelse(is.na(TA2014_NAM), "Special or other", as.character(TA2014_NAM)),
TA = gsub(" District", "", TA),
TA = gsu
Related Skills
node-connect
341.0kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
frontend-design
84.4kCreate distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, or applications. Generates creative, polished code that avoids generic AI aesthetics.
openai-whisper-api
341.0kTranscribe audio via OpenAI Audio Transcriptions API (Whisper).
commit-push-pr
84.4kCommit, push, and open a PR
