Here we author some R to download, parse and examine output from 2017 QLD state elections.
Download the data
ECQ provides the data in XML, wrapped in a zip file. This is trivial to download and injest into R. We print the time stamp on the file.
theURL <- "https://results.ecq.qld.gov.au/elections/state/state2017/results/public.zip"
library(curl)
tmpfile <- curl_download(theURL,destfile = tempfile(fileext = ".zip"))
library(rvest)
library(xml2)
doc <- read_xml(tmpfile)
parseDateTime <- function(str){
as.POSIXct(as.POSIXlt(str,
tz="Australia/Brisbane",
format="%Y-%m-%dT%H:%M:%OS"))
}
getGenTime <- function(doc){
require(xml2)
string <- xml_text(xml_node(doc,xpath="//generationDateTime"))
return(parseDateTime(string))
}
genTime <- getGenTime(doc)
print(genTime)
## [1] "2017-11-28 11:38:32 AEST"
State totals
## enrolment and total votes
getTotVote <- function(doc){
e <- xml_node(doc,xpath = "/election")
out <- as.data.frame(xml_attrs(e))
names(out) <- "value"
out$var <- rownames(out)
out <- rbind(out,
data.frame(var="votes",
value=xml_integer(xml_node(doc,xpath = "/election/totalVotes"))),
data.frame(var="formal",
value=xml_integer(xml_node(doc,xpath = "/election/totalFormalVotes"))),
data.frame(var="informal",
value=xml_integer(xml_node(doc,xpath = "/election/totalInformalVotes"))))
return(out)
}
stotal <- getTotVote(doc)
## formatting
ok <- !is.na(as.numeric(stotal$value))
stotal$value[ok] <- format(as.numeric(stotal$value[ok]),
big.mark = ",",
drop0trailing = TRUE)
kable(stotal[,c("var","value")],
row.names=FALSE,
format.args = list(big.mark=","))
| id |
526 |
| name |
2017 State General Election |
| type |
H |
| state |
QLD |
| date |
2017-11-25 |
| status |
Open |
| enrolment |
3,229,536 |
| percentRollCounted |
76.21 |
| boothCount |
13,977 |
| candidateCount |
453 |
| partyCount |
6 |
| xmlUpdateInterval |
120 |
| votes |
2,461,347 |
| formal |
2,358,065 |
| informal |
103,282 |
Party totals
getPartyTotals <- function(doc){
party <- xml_attr(xml_nodes(doc,xpath = "//party"),attr = "code")
formal <- xml_integer(xml_nodes(doc,xpath = "//party/formalVotes/count"))
out <- data.frame(party,formal)
out$per <- out$formal/sum(out$formal)*100
out$timeStamp <- getGenTime(doc)
return(out)
}
kable(getPartyTotals(doc),format.args = list(big.mark=","),digits=2)
| ALP |
844,889 |
35.83 |
2017-11-28 11:38:32 |
| LNP |
792,397 |
33.60 |
2017-11-28 11:38:32 |
| ONP |
322,717 |
13.69 |
2017-11-28 11:38:32 |
| GRN |
228,215 |
9.68 |
2017-11-28 11:38:32 |
| KAP |
54,900 |
2.33 |
2017-11-28 11:38:32 |
| CR |
5,775 |
0.24 |
2017-11-28 11:38:32 |
| ZZZ |
109,172 |
4.63 |
2017-11-28 11:38:32 |
District level data, as a flat file
getDistrictTotals <- function(doc){
out <- xml_attrs(xml_nodes(doc,xpath="//districts/district"))
out <- lapply(out,
function(x){as.data.frame(as.list(x),stringsAsFactors=FALSE)})
out <- dplyr::bind_rows(out)
out$lastUpdated <- parseDateTime(out$lastUpdated)
out$number <- NULL
out$informalVotes <- xml_integer(xml_find_all(doc,xpath="//districts/district/informalVotes/count"))
out$totalVotes <- xml_integer(xml_find_all(doc,xpath="//districts/district/totalVotes"))
out$informalPer <- out$informalVotes/out$totalVotes * 100
out$enrolment <- as.integer(out$enrolment)
return(out)
}
ddata <- getDistrictTotals(doc)
kable(ddata %>%
arrange(desc(lastUpdated)),
digits=2,
format.args = list(big.mark=","))
| Aspley |
2017-11-28 11:35:11 |
NO |
36,873 |
80.34 |
1,064 |
29,623 |
3.59 |
| Buderim |
2017-11-28 11:18:42 |
NO |
34,822 |
76.28 |
897 |
26,562 |
3.38 |
| Southern Downs |
2017-11-28 11:18:02 |
NO |
35,622 |
83.87 |
1,069 |
29,876 |
3.58 |
| Woodridge |
2017-11-28 11:12:46 |
NO |
36,286 |
70.31 |
1,996 |
25,513 |
7.82 |
| Pine Rivers |
2017-11-28 11:05:14 |
NO |
37,031 |
80.84 |
1,103 |
29,935 |
3.68 |
| Warrego |
2017-11-28 11:05:09 |
NO |
29,615 |
76.43 |
898 |
22,635 |
3.97 |
| Nicklin |
2017-11-28 11:04:13 |
NO |
32,813 |
78.48 |
1,132 |
25,752 |
4.40 |
| Mundingburra |
2017-11-28 11:03:08 |
NO |
33,801 |
78.02 |
1,242 |
26,370 |
4.71 |
| Cook |
2017-11-28 11:01:29 |
NO |
32,394 |
72.90 |
1,014 |
23,616 |
4.29 |
| Gregory |
2017-11-28 10:56:04 |
NO |
24,862 |
74.82 |
575 |
18,602 |
3.09 |
| Stretton |
2017-11-28 10:53:20 |
NO |
33,547 |
78.11 |
1,243 |
26,205 |
4.74 |
| Capalaba |
2017-11-28 10:52:14 |
NO |
35,913 |
78.09 |
1,133 |
28,046 |
4.04 |
| Callide |
2017-11-28 10:51:30 |
NO |
33,540 |
56.42 |
672 |
18,922 |
3.55 |
| Toowoomba South |
2017-11-28 10:47:22 |
NO |
37,415 |
74.61 |
1,020 |
27,915 |
3.65 |
| Oodgeroo |
2017-11-28 10:05:42 |
NO |
32,116 |
76.99 |
1,017 |
24,727 |
4.11 |
| Mansfield |
2017-11-28 10:05:06 |
NO |
33,859 |
78.70 |
1,062 |
26,646 |
3.99 |
| Lockyer |
2017-11-28 10:01:04 |
NO |
33,559 |
78.50 |
1,002 |
26,345 |
3.80 |
| Kawana |
2017-11-28 09:59:00 |
NO |
34,844 |
79.62 |
1,294 |
27,743 |
4.66 |
| Ipswich West |
2017-11-28 09:58:24 |
NO |
33,898 |
79.64 |
1,219 |
26,997 |
4.52 |
| Burleigh |
2017-11-28 09:54:31 |
NO |
34,812 |
74.57 |
1,372 |
25,958 |
5.29 |
| Bancroft |
2017-11-28 09:52:09 |
NO |
34,056 |
73.31 |
1,044 |
24,968 |
4.18 |
| Clayfield |
2017-11-28 09:49:46 |
NO |
38,454 |
74.52 |
1,004 |
28,657 |
3.50 |
| Morayfield |
2017-11-28 09:43:21 |
NO |
34,615 |
77.68 |
1,179 |
26,889 |
4.38 |
| South Brisbane |
2017-11-28 09:23:30 |
NO |
34,460 |
70.77 |
836 |
24,386 |
3.43 |
| Ninderry |
2017-11-28 08:15:41 |
NO |
35,706 |
73.81 |
1,255 |
26,356 |
4.76 |
| Toohey |
2017-11-28 08:00:09 |
NO |
33,588 |
73.02 |
1,183 |
24,526 |
4.82 |
| Stafford |
2017-11-27 19:53:09 |
NO |
37,641 |
75.02 |
1,025 |
28,239 |
3.63 |
| Springwood |
2017-11-27 19:52:38 |
NO |
35,319 |
76.64 |
1,263 |
27,069 |
4.67 |
| Southport |
2017-11-27 19:51:56 |
NO |
34,005 |
67.99 |
1,107 |
23,119 |
4.79 |
| Mudgeeraba |
2017-11-27 19:48:20 |
NO |
36,268 |
74.73 |
1,333 |
27,102 |
4.92 |
| Miller |
2017-11-27 19:47:05 |
NO |
34,567 |
75.45 |
655 |
26,080 |
2.51 |
| Keppel |
2017-11-27 19:32:54 |
NO |
35,307 |
84.67 |
990 |
29,894 |
3.31 |
| Kurwongbah |
2017-11-27 19:29:26 |
NO |
34,780 |
70.45 |
1,078 |
24,502 |
4.40 |
| Hinchinbrook |
2017-11-27 19:27:20 |
NO |
33,488 |
78.98 |
1,070 |
26,448 |
4.05 |
| Gympie |
2017-11-27 19:26:32 |
NO |
36,955 |
82.37 |
1,264 |
30,438 |
4.15 |
| Cooper |
2017-11-27 19:20:11 |
NO |
36,850 |
78.24 |
635 |
28,831 |
2.20 |
| Chatsworth |
2017-11-27 19:18:21 |
NO |
34,815 |
73.79 |
926 |
25,690 |
3.60 |
| Caloundra |
2017-11-27 19:17:11 |
NO |
34,268 |
76.52 |
1,026 |
26,222 |
3.91 |
| Burnett |
2017-11-27 19:15:15 |
NO |
34,015 |
81.01 |
1,056 |
27,556 |
3.83 |
| Bulimba |
2017-11-27 19:12:59 |
NO |
37,824 |
75.56 |
893 |
28,581 |
3.12 |
| Broadwater |
2017-11-27 19:11:58 |
NO |
33,511 |
70.08 |
884 |
23,483 |
3.76 |
| Mirani |
2017-11-27 19:06:49 |
NO |
32,764 |
75.52 |
848 |
24,742 |
3.43 |
| Mermaid Beach |
2017-11-27 18:24:04 |
NO |
34,479 |
73.00 |
1,631 |
25,168 |
6.48 |
| Bundaberg |
2017-11-27 18:12:28 |
NO |
34,757 |
85.02 |
1,378 |
29,549 |
4.66 |
| Glass House |
2017-11-27 17:42:52 |
NO |
33,365 |
79.12 |
875 |
26,397 |
3.31 |
| Thuringowa |
2017-11-27 17:33:11 |
NO |
35,418 |
78.04 |
1,329 |
27,640 |
4.81 |
| Inala |
2017-11-27 17:33:10 |
NO |
33,970 |
77.40 |
1,793 |
26,292 |
6.82 |
| Macalister |
2017-11-27 16:53:10 |
NO |
34,898 |
76.67 |
1,742 |
26,755 |
6.51 |
| Noosa |
2017-11-27 16:45:26 |
NO |
35,759 |
78.37 |
918 |
28,025 |
3.28 |
| Toowoomba North |
2017-11-27 16:35:40 |
NO |
36,602 |
77.58 |
989 |
28,395 |
3.48 |
| Traeger |
2017-11-27 16:21:26 |
NO |
26,132 |
71.87 |
758 |
18,782 |
4.04 |
| Lytton |
2017-11-27 16:19:42 |
NO |
36,237 |
82.36 |
967 |
29,846 |
3.24 |
| Bundamba |
2017-11-27 16:12:52 |
NO |
33,639 |
72.91 |
2,014 |
24,525 |
8.21 |
| Townsville |
2017-11-27 16:11:10 |
NO |
34,926 |
75.22 |
975 |
26,270 |
3.71 |
| Maiwar |
2017-11-27 16:09:56 |
NO |
37,608 |
75.52 |
648 |
28,403 |
2.28 |
| Redcliffe |
2017-11-27 16:08:15 |
NO |
36,684 |
81.44 |
1,343 |
29,877 |
4.50 |
| Maroochydore |
2017-11-27 16:02:50 |
NO |
34,346 |
68.40 |
852 |
23,491 |
3.63 |
| Currumbin |
2017-11-27 15:58:53 |
NO |
34,409 |
71.82 |
1,067 |
24,713 |
4.32 |
| Bonney |
2017-11-27 15:55:39 |
NO |
33,230 |
69.17 |
1,358 |
22,985 |
5.91 |
| Cairns |
2017-11-27 15:23:48 |
NO |
36,569 |
73.09 |
1,071 |
26,729 |
4.01 |
| Whitsunday |
2017-11-27 15:19:49 |
NO |
32,939 |
77.53 |
1,027 |
25,537 |
4.02 |
| Waterford |
2017-11-27 15:13:04 |
NO |
33,029 |
72.11 |
1,380 |
23,817 |
5.79 |
| Scenic Rim |
2017-11-27 15:12:57 |
NO |
36,245 |
77.17 |
1,012 |
27,972 |
3.62 |
| Surfers Paradise |
2017-11-27 15:10:41 |
NO |
33,354 |
64.14 |
1,137 |
21,392 |
5.32 |
| Rockhampton |
2017-11-27 15:07:29 |
NO |
35,801 |
84.29 |
1,260 |
30,178 |
4.18 |
| Redlands |
2017-11-27 15:07:14 |
NO |
34,632 |
70.80 |
990 |
24,521 |
4.04 |
| Nudgee |
2017-11-27 15:06:16 |
NO |
36,606 |
76.11 |
1,066 |
27,862 |
3.83 |
| Maryborough |
2017-11-27 15:05:01 |
NO |
36,130 |
77.78 |
1,062 |
28,102 |
3.78 |
| Mulgrave |
2017-11-27 15:04:12 |
NO |
34,190 |
78.46 |
1,323 |
26,824 |
4.93 |
| Mount Ommaney |
2017-11-27 15:03:40 |
NO |
35,305 |
81.69 |
948 |
28,840 |
3.29 |
| Moggill |
2017-11-27 15:03:12 |
NO |
34,904 |
80.87 |
745 |
28,226 |
2.64 |
| Mackay |
2017-11-27 15:01:11 |
NO |
37,259 |
80.68 |
1,334 |
30,059 |
4.44 |
| Logan |
2017-11-27 15:00:11 |
NO |
33,002 |
74.39 |
1,364 |
24,549 |
5.56 |
| Hill |
2017-11-27 14:59:07 |
NO |
36,893 |
79.56 |
1,015 |
29,352 |
3.46 |
| Nanango |
2017-11-27 14:58:13 |
NO |
36,217 |
77.98 |
922 |
28,241 |
3.26 |
| Gladstone |
2017-11-27 14:56:59 |
NO |
32,216 |
80.62 |
848 |
25,974 |
3.26 |
| Ferny Grove |
2017-11-27 14:56:19 |
NO |
35,461 |
75.03 |
734 |
26,607 |
2.76 |
| Hervey Bay |
2017-11-27 14:55:42 |
NO |
37,620 |
81.40 |
1,204 |
30,621 |
3.93 |
| Condamine |
2017-11-27 14:53:36 |
NO |
36,525 |
73.48 |
866 |
26,838 |
3.23 |
| Burdekin |
2017-11-27 14:51:52 |
NO |
34,295 |
78.29 |
846 |
26,848 |
3.15 |
| Theodore |
2017-11-27 14:37:27 |
NO |
33,243 |
71.15 |
1,285 |
23,651 |
5.43 |
| Sandgate |
2017-11-27 14:34:14 |
NO |
36,123 |
83.30 |
1,025 |
30,089 |
3.41 |
| Pumicestone |
2017-11-27 14:31:43 |
NO |
35,004 |
77.96 |
1,110 |
27,289 |
4.07 |
| Murrumba |
2017-11-27 14:27:19 |
NO |
37,050 |
73.81 |
1,178 |
27,348 |
4.31 |
| McConnel |
2017-11-27 14:15:33 |
NO |
35,013 |
67.99 |
802 |
23,804 |
3.37 |
| Gaven |
2017-11-27 13:47:55 |
NO |
32,785 |
76.12 |
1,636 |
24,955 |
6.56 |
| Jordan |
2017-11-27 12:56:32 |
NO |
33,336 |
77.90 |
1,635 |
25,970 |
6.30 |
| Ipswich |
2017-11-27 12:55:58 |
NO |
31,774 |
78.40 |
1,281 |
24,911 |
5.14 |
| Greenslopes |
2017-11-27 12:52:34 |
NO |
35,771 |
77.12 |
921 |
27,586 |
3.34 |
| Everton |
2017-11-27 12:49:19 |
NO |
36,833 |
76.74 |
1,001 |
28,265 |
3.54 |
| Coomera |
2017-11-27 12:40:57 |
NO |
37,009 |
73.17 |
1,565 |
27,079 |
5.78 |
| Barron River |
2017-11-27 12:26:08 |
NO |
35,423 |
77.76 |
1,175 |
27,546 |
4.27 |
| Algester |
2017-11-27 12:20:51 |
NO |
33,643 |
73.97 |
1,299 |
24,886 |
5.22 |
Candidate level data
candidateProcess <- function(doc){
cnodes <- xml_nodes(doc,xpath="//candidates/candidate")
cdata <- xml_attrs(cnodes)
d <- lapply(cnodes,xml_find_first,xpath="ancestor::district")
d <- unlist(lapply(d,xml_attr,attr="name"))
cdata <- lapply(cdata,function(x){as.data.frame(as.list(x),stringsAsFactors=FALSE)})
cdata <- dplyr::bind_rows(cdata)
cdata$district <- d
return(cdata)
}
candidateShares <- function(doc){
cnodes <- xml_find_all(doc,xpath = "//district/candidates/candidate/primaryVotes")
votes <- xml_integer(xml_find_all(cnodes,xpath="count"))
cinfo <- xml_attrs(xml_parent(cnodes))
cinfo <- lapply(cinfo,
function(obj){
as.data.frame(as.list(obj),stringsAsFactors=FALSE)
})
cinfo <- dplyr::bind_rows(cinfo)
d <- lapply(cnodes,xml_find_first,xpath="ancestor::district")
d <- unlist(lapply(d,xml_attr,attr="name"))
cinfo$votes <- votes
cinfo$district <- d
return(cinfo)
}
cdata <- candidateShares(doc)
## add percentages
cdata <- cdata %>%
group_by(district) %>%
mutate(per=votes/sum(votes)*100)
We also rank order the candidates within districts.
cdata <- cdata %>%
group_by(district) %>%
mutate(r = n() + 1 - rank(votes))
Seats won without preferences
kout <- inner_join(cdata,
cdata %>%
filter(r==1 & per>50)) %>%
select(district,ballotName,party,per) %>%
arrange(desc(per))
kable(kout)
| Inala |
PALASZCZUK, Annastacia |
ALP |
68.56606 |
| Woodridge |
DICK, Cameron |
ALP |
66.19467 |
| Traeger |
KATTER, Robbie |
KAP |
66.05637 |
| Gladstone |
BUTCHER, Glenn |
ALP |
65.00040 |
| Surfers Paradise |
LANGBROEK, John-Paul |
LNP |
63.99901 |
| Kawana |
BLEIJIE, Jarrod |
LNP |
56.61840 |
| Bundamba |
MILLER, Jo-Ann |
ALP |
53.73373 |
| Nudgee |
LINARD, Leanne |
ALP |
53.04523 |
| Oodgeroo |
ROBINSON, Mark |
LNP |
52.93547 |
| Algester |
ENOCH, Leeanne |
ALP |
52.44414 |
| Everton |
MANDER, Tim |
LNP |
52.17136 |
| Stretton |
PEGG, Duncan |
ALP |
50.92941 |
| Burleigh |
HART, Michael |
LNP |
50.29692 |
| Sandgate |
HINCHLIFFE, Stirling |
ALP |
50.02408 |
Plurality winners
foo <- filter(cdata,r==1) %>% select(party,district)
tab <- as.data.frame(xtabs(~party,data=foo))
kable(tab)
| ALP |
47 |
| KAP |
2 |
| LNP |
43 |
| ZZZ |
1 |
Smallest pluralities, most entropy in vote shares
tmp <- full_join(cdata %>% group_by(district) %>%
summarise(StdDev=sd(per)) %>%
arrange(StdDev),
cdata %>% group_by(district) %>%
summarise(maxVoteShare=max(per)) %>%
arrange(maxVoteShare)) %>%
filter(between(row_number(),1,10))
kable(tmp,digits=2)
| Cairns |
9.41 |
30.56 |
| Rockhampton |
9.67 |
31.91 |
| Thuringowa |
10.31 |
32.26 |
| Hinchinbrook |
10.60 |
30.09 |
| Buderim |
10.74 |
37.28 |
| Greenslopes |
11.24 |
42.41 |
| Redlands |
11.76 |
33.18 |
| Mundingburra |
11.77 |
31.65 |
| Cook |
11.89 |
39.25 |
| Callide |
11.94 |
31.24 |
Major party vote share
plotData <- bind_rows(cdata %>%
group_by(district) %>%
summarise(x=per[party=="ALP"] + per[party=="LNP"],
alp=per[party=="ALP"],
lnp=per[party=="LNP"]) %>%
ungroup(),
cdata %>%
ungroup() %>%
summarise(alp0=sum(votes[party=="ALP"]),
lnp0=sum(votes[party=="LNP"]),
x=(alp0+lnp0)/sum(votes)*100,
alp=alp0/sum(votes)*100,
lnp=lnp0/sum(votes)*100,
district="Statewide")) %>%
arrange(x)
plotData$district <- ordered(plotData$district,levels=plotData$district)
plotData$Statewide <- factor(plotData$district=="Statewide")
library(reshape2)
plotData <- melt(plotData,id.vars = "district",measure.vars = c("alp","lnp","x"))
library(ggplot2)
ggplot(plotData,aes(y=district,x=value,color=variable)) +
geom_point() +
scale_color_manual(values=c("alp"="red","lnp"="blue","x"="black")) +
scale_x_continuous("Major party vote share") +
scale_y_discrete("") +
theme(panel.border = element_blank(),
legend.position = "none")

Two-candidate preferred
processTPP <- function(doc){
require(xml2)
nodes <- xml_find_all(doc,"//district/candidates/candidate/n2cpVotes")
tpp <- data.frame(percentage=xml_double(
xml_find_all(doc,"//district/candidates/candidate/n2cpVotes/percentage")),
count=xml_integer(
xml_find_all(doc,"//district/candidates/candidate/n2cpVotes/count"))
)
tpp$party <- unlist(lapply(nodes,
function(x){
xml_attr(xml_find_first(x,
"ancestor::candidate"),
"party")
}))
tpp$district <- unlist(lapply(nodes,
function(x){
xml_attr(xml_find_first(x,
"ancestor::district"),
"name")
}))
return(tpp)
}
tpp <- processTPP(doc)
Maverick seats: no two-candidate preferred count
setdiff(ddata$name,tpp$district)
## [1] "Burnett" "Callide" "Gladstone" "Hervey Bay"
## [5] "Hinchinbrook" "Jordan" "Keppel" "Logan"
## [9] "Morayfield" "Mulgrave" "Rockhampton" "Scenic Rim"
## [13] "Southern Downs" "Traeger" "Warrego" "Waterford"
Difference between TCP and 1st preferences
plotData <- inner_join(cdata,tpp,by=c("party","district"))
ggplot(subset(plotData,party %in% c("ALP","LNP","ONP")),
aes(x=per,y=percentage)) +
geom_abline(slope=1,intercept = 0) +
geom_smooth(method = "lm",se=FALSE,col="blue") +
geom_point() +
scale_x_continuous("1st preferences") +
scale_y_continuous("TCP") +
facet_wrap(~party)

types of 2pp contests
tcp_type <- tpp %>%
group_by(district) %>%
arrange(desc(percentage)) %>%
summarise(p1=party[1],p2=party[2]) %>%
arrange(p1,p2)
kable(tcp_type)
| South Brisbane |
ALP |
GRN |
| Algester |
ALP |
LNP |
| Aspley |
ALP |
LNP |
| Bancroft |
ALP |
LNP |
| Barron River |
ALP |
LNP |
| Bulimba |
ALP |
LNP |
| Bundamba |
ALP |
LNP |
| Cairns |
ALP |
LNP |
| Capalaba |
ALP |
LNP |
| Cooper |
ALP |
LNP |
| Ferny Grove |
ALP |
LNP |
| Gaven |
ALP |
LNP |
| Greenslopes |
ALP |
LNP |
| Inala |
ALP |
LNP |
| Kurwongbah |
ALP |
LNP |
| Lytton |
ALP |
LNP |
| Macalister |
ALP |
LNP |
| Mackay |
ALP |
LNP |
| Maiwar |
ALP |
LNP |
| Mansfield |
ALP |
LNP |
| McConnel |
ALP |
LNP |
| Miller |
ALP |
LNP |
| Mount Ommaney |
ALP |
LNP |
| Mundingburra |
ALP |
LNP |
| Murrumba |
ALP |
LNP |
| Nudgee |
ALP |
LNP |
| Pine Rivers |
ALP |
LNP |
| Redcliffe |
ALP |
LNP |
| Redlands |
ALP |
LNP |
| Sandgate |
ALP |
LNP |
| Springwood |
ALP |
LNP |
| Stafford |
ALP |
LNP |
| Stretton |
ALP |
LNP |
| Toohey |
ALP |
LNP |
| Woodridge |
ALP |
LNP |
| Cook |
ALP |
ONP |
| Ipswich |
ALP |
ONP |
| Ipswich West |
ALP |
ONP |
| Maryborough |
ALP |
ONP |
| Thuringowa |
ALP |
ONP |
| Hill |
KAP |
LNP |
| Bonney |
LNP |
ALP |
| Broadwater |
LNP |
ALP |
| Bundaberg |
LNP |
ALP |
| Burdekin |
LNP |
ALP |
| Burleigh |
LNP |
ALP |
| Caloundra |
LNP |
ALP |
| Chatsworth |
LNP |
ALP |
| Clayfield |
LNP |
ALP |
| Coomera |
LNP |
ALP |
| Currumbin |
LNP |
ALP |
| Everton |
LNP |
ALP |
| Glass House |
LNP |
ALP |
| Kawana |
LNP |
ALP |
| Maroochydore |
LNP |
ALP |
| Mermaid Beach |
LNP |
ALP |
| Moggill |
LNP |
ALP |
| Mudgeeraba |
LNP |
ALP |
| Nicklin |
LNP |
ALP |
| Ninderry |
LNP |
ALP |
| Oodgeroo |
LNP |
ALP |
| Pumicestone |
LNP |
ALP |
| Southport |
LNP |
ALP |
| Surfers Paradise |
LNP |
ALP |
| Theodore |
LNP |
ALP |
| Toowoomba North |
LNP |
ALP |
| Toowoomba South |
LNP |
ALP |
| Townsville |
LNP |
ALP |
| Whitsunday |
LNP |
ALP |
| Buderim |
LNP |
ONP |
| Condamine |
LNP |
ONP |
| Gregory |
LNP |
ONP |
| Gympie |
LNP |
ONP |
| Lockyer |
LNP |
ONP |
| Nanango |
LNP |
ONP |
| Mirani |
ONP |
ALP |
| Noosa |
ZZZ |
LNP |
tab <- xtabs(~p1+p2,data=tcp_type)
kable(tab,caption="1st TCP party tabbed against 2nd TCP party")
1st TCP party tabbed against 2nd TCP party
| ALP |
0 |
1 |
34 |
5 |
| KAP |
0 |
0 |
1 |
0 |
| LNP |
28 |
0 |
0 |
6 |
| ONP |
1 |
0 |
0 |
0 |
| ZZZ |
0 |
0 |
1 |
0 |
Seats where ONP is 1st or 2nd (and no ties!)
theDistricts <- filter(cdata, r<2.5 & party=="ONP") %>% select(district)
print(theDistricts)
## # A tibble: 21 x 1
## # Groups: district [21]
## district
## <chr>
## 1 Buderim
## 2 Burnett
## 3 Callide
## 4 Condamine
## 5 Cook
## 6 Gladstone
## 7 Gregory
## 8 Gympie
## 9 Hinchinbrook
## 10 Ipswich
## # ... with 11 more rows
foo <- inner_join(cdata,theDistricts) %>%
group_by(district) %>%
summarise(p1=party[r==1],p2=party[r==2],p3=party[r==3],
per1=per[r==1],per2=per[r==2],per3=per[r==3],
onp=per[party=="ONP"]) %>%
mutate(delta=per1-onp) %>%
arrange(delta) %>%
select(-onp)
kable(foo,digits=2)
| Lockyer |
LNP |
ONP |
ALP |
36.08 |
34.45 |
22.95 |
1.63 |
| Callide |
LNP |
ONP |
ALP |
31.24 |
25.99 |
22.95 |
5.25 |
| Mirani |
ALP |
ONP |
LNP |
37.32 |
31.66 |
26.85 |
5.67 |
| Gympie |
LNP |
ONP |
ALP |
37.75 |
29.66 |
22.36 |
8.09 |
| Hinchinbrook |
LNP |
ONP |
KAP |
30.09 |
21.93 |
21.13 |
8.15 |
| Buderim |
LNP |
ONP |
ALP |
37.28 |
28.75 |
22.13 |
8.53 |
| Logan |
ALP |
ONP |
LNP |
42.91 |
31.28 |
17.78 |
11.63 |
| Scenic Rim |
LNP |
ONP |
ALP |
41.60 |
27.38 |
21.34 |
14.22 |
| Burnett |
LNP |
ONP |
ALP |
42.93 |
26.37 |
25.41 |
16.56 |
| Maryborough |
ALP |
ONP |
LNP |
47.10 |
29.62 |
17.22 |
17.48 |
| Condamine |
LNP |
ONP |
ALP |
41.80 |
23.83 |
17.83 |
17.97 |
| Ipswich West |
ALP |
ONP |
LNP |
47.87 |
28.16 |
16.34 |
19.71 |
| Cook |
ALP |
ONP |
LNP |
39.25 |
18.89 |
17.89 |
20.36 |
| Gregory |
LNP |
ONP |
ALP |
44.93 |
24.08 |
21.74 |
20.85 |
| Nanango |
LNP |
ONP |
ALP |
48.33 |
27.09 |
19.47 |
21.23 |
| Southern Downs |
LNP |
ONP |
ALP |
41.38 |
20.14 |
16.88 |
21.23 |
| Morayfield |
ALP |
ONP |
LNP |
46.39 |
24.96 |
20.13 |
21.43 |
| Jordan |
ALP |
ONP |
LNP |
39.94 |
18.49 |
14.14 |
21.45 |
| Ipswich |
ALP |
ONP |
LNP |
48.55 |
26.31 |
13.79 |
22.24 |
| Waterford |
ALP |
ONP |
LNP |
48.64 |
20.74 |
19.75 |
27.90 |
| Gladstone |
ALP |
ONP |
LNP |
65.00 |
20.04 |
11.45 |
44.96 |
Seats where ONP is 3rd
theDistricts<- filter(cdata, r==3 & party=="ONP") %>% select(district)
foo <- inner_join(cdata,theDistricts) %>%
summarise(p1=party[r==1],p2=party[r==2],
per1=per[r==1],per2=per[r==2],
onp=per[party=="ONP"]) %>%
arrange(desc(onp))
kable(foo,digits=2,format.args = list(big.mark=","))
| Burdekin |
ALP |
LNP |
36.00 |
31.62 |
29.59 |
| Hervey Bay |
LNP |
ALP |
37.76 |
29.30 |
25.27 |
| Pumicestone |
ALP |
LNP |
35.83 |
30.03 |
22.97 |
| Glass House |
LNP |
ALP |
35.74 |
26.58 |
22.48 |
| Bundaberg |
LNP |
ALP |
35.74 |
34.61 |
22.37 |
| Mulgrave |
ALP |
LNP |
48.23 |
22.92 |
22.34 |
| Mackay |
ALP |
LNP |
43.33 |
24.89 |
22.29 |
| Caloundra |
LNP |
ALP |
38.90 |
28.86 |
21.90 |
| Broadwater |
LNP |
ALP |
47.90 |
23.82 |
21.76 |
| Kurwongbah |
ALP |
LNP |
42.00 |
23.97 |
21.71 |
| Rockhampton |
ALP |
ZZZ |
31.91 |
23.67 |
21.24 |
| Nicklin |
LNP |
ALP |
32.05 |
25.50 |
20.91 |
| Coomera |
LNP |
ALP |
39.58 |
31.34 |
20.50 |
| Thuringowa |
ALP |
LNP |
32.26 |
21.08 |
20.23 |
| Townsville |
ALP |
LNP |
33.51 |
31.38 |
19.89 |
| Whitsunday |
LNP |
ALP |
32.42 |
31.38 |
19.83 |
| Capalaba |
ALP |
LNP |
43.25 |
25.36 |
19.43 |
| Theodore |
LNP |
ALP |
39.48 |
32.04 |
19.09 |
| Murrumba |
ALP |
LNP |
46.21 |
25.79 |
19.04 |
| Bancroft |
ALP |
LNP |
43.58 |
26.83 |
18.68 |
| Algester |
ALP |
LNP |
52.44 |
21.68 |
18.10 |
| Ninderry |
LNP |
ALP |
36.72 |
22.85 |
18.01 |
| Mudgeeraba |
LNP |
ALP |
46.47 |
23.21 |
17.79 |
| Redlands |
ALP |
LNP |
33.18 |
31.37 |
17.53 |
| Mundingburra |
ALP |
LNP |
31.65 |
26.01 |
16.78 |
| Barron River |
ALP |
LNP |
33.69 |
30.50 |
16.71 |
| Toowoomba South |
LNP |
ALP |
46.12 |
27.47 |
16.32 |
| Maroochydore |
LNP |
ALP |
45.08 |
25.50 |
15.96 |
| Lytton |
ALP |
LNP |
49.37 |
24.20 |
15.46 |
| Sandgate |
ALP |
LNP |
50.02 |
23.04 |
14.46 |
| Toowoomba North |
LNP |
ALP |
42.32 |
33.56 |
14.19 |
| Pine Rivers |
ALP |
LNP |
37.55 |
26.43 |
12.16 |
| Stretton |
ALP |
LNP |
50.93 |
28.56 |
12.03 |
| Aspley |
LNP |
ALP |
40.35 |
37.35 |
9.61 |
table(foo$p1,foo$p2)
##
## ALP LNP ZZZ
## ALP 0 18 1
## LNP 15 0 0
Seats where GRN is 1st or 2nd
theDistricts <- filter(cdata, r<3 & party=="GRN") %>% select(district)
foo <- inner_join(cdata,theDistricts) %>%
summarise(p1=party[r==1],p2=party[r==2],p3=party[r==3],
per1=per[r==1],per2=per[r==2],per3=per[r==3],
grn=per[party=="GRN"]) %>%
mutate(delta=per1-grn) %>%
arrange(delta) %>%
select(-grn)
kable(foo,
digits=2,
format.args = list(big.mark=","))
| South Brisbane |
ALP |
GRN |
LNP |
36.34 |
34.61 |
23.72 |
1.73 |
| Maiwar |
LNP |
GRN |
ALP |
42.24 |
27.62 |
27.55 |
14.62 |
foo <- inner_join(cdata,theDistricts) %>%
filter(r==1) %>%
select(party,district)
Seats where GRN has finished 3rd
theDistricts<- filter(cdata, r==3 & party=="GRN") %>% select(district)
foo <- inner_join(cdata,theDistricts) %>%
summarise(p1=party[r==1],p2=party[r==2],
per1=per[r==1],per2=per[r==2],
grn=per[party=="GRN"]) %>%
arrange(desc(grn))
kable(foo,digits=2,format.args = list(big.mark=","))
| McConnel |
LNP |
ALP |
36.45 |
33.78 |
27.18 |
| Miller |
ALP |
LNP |
38.49 |
36.47 |
21.81 |
| Greenslopes |
ALP |
LNP |
42.41 |
36.82 |
20.77 |
| Moggill |
LNP |
ALP |
49.08 |
26.57 |
20.71 |
| Cooper |
ALP |
LNP |
41.14 |
35.90 |
20.22 |
| Clayfield |
LNP |
ALP |
48.43 |
33.04 |
18.53 |
| Stafford |
ALP |
LNP |
48.57 |
33.61 |
17.82 |
| Burleigh |
LNP |
ALP |
50.30 |
34.22 |
15.48 |
| Ferny Grove |
ALP |
LNP |
40.61 |
40.31 |
15.36 |
| Toohey |
ALP |
LNP |
45.23 |
30.02 |
14.26 |
| Oodgeroo |
LNP |
ALP |
52.94 |
33.81 |
13.26 |
| Mount Ommaney |
ALP |
LNP |
43.13 |
36.77 |
13.03 |
| Nudgee |
ALP |
LNP |
53.05 |
28.44 |
12.73 |
| Bulimba |
ALP |
LNP |
49.84 |
34.41 |
12.58 |
| Everton |
LNP |
ALP |
52.17 |
35.84 |
11.99 |
| Chatsworth |
LNP |
ALP |
49.88 |
38.54 |
11.58 |
| Currumbin |
LNP |
ALP |
47.37 |
36.45 |
11.45 |
| Inala |
ALP |
LNP |
68.57 |
20.31 |
11.13 |
| Mansfield |
LNP |
ALP |
40.38 |
39.70 |
10.74 |
| Bundamba |
ALP |
LNP |
53.73 |
14.61 |
10.67 |
| Gaven |
LNP |
ALP |
46.34 |
43.56 |
10.09 |
| Kawana |
LNP |
ALP |
56.62 |
25.47 |
10.08 |
| Bonney |
LNP |
ALP |
43.69 |
36.36 |
9.48 |
| Surfers Paradise |
LNP |
ALP |
64.00 |
22.38 |
8.71 |
| Springwood |
ALP |
LNP |
44.87 |
40.43 |
8.69 |
| Redcliffe |
ALP |
LNP |
45.47 |
37.55 |
7.51 |
table(foo$p1,foo$p2)
##
## ALP LNP
## ALP 0 13
## LNP 13 0
One Nation dotplot
plotData <- inner_join(cdata,
filter(cdata,party=="ONP") %>%
select(district)) %>%
filter(party %in% c("ALP","LNP","ONP","GRN","KAP"))
levs <- filter(plotData,party=="ONP") %>% arrange(desc(per)) %>% select(district)
plotData$district <- ordered(plotData$district,levels=rev(levs$district))
library(ggplot2)
ggplot(plotData,aes(y=district,x=per,color=party,shape=party)) +
geom_point() +
scale_x_continuous("1st preference vote share") +
scale_y_discrete("") +
scale_color_manual(values=c("ALP"="red","LNP"="blue","ONP"="black","GRN"="green","KAP"="orange")) +
scale_shape_manual(values=c("ALP"=1,"LNP"=1,"ONP"=15,"GRN"=1,"KAP"=1)) +
theme(panel.border = element_blank(),
legend.position = "top")

Green dotplot
plotData <- inner_join(cdata,
filter(cdata,party=="GRN") %>%
select(district)) %>%
filter(party %in% c("ALP","LNP","ONP","GRN","KAP"))
levs <- filter(plotData,party=="GRN") %>% arrange(desc(per)) %>% select(district)
plotData$district <- ordered(plotData$district,levels=rev(levs$district))
library(ggplot2)
ggplot(plotData,aes(y=district,x=per,color=party,shape=party)) +
geom_point() +
scale_x_continuous("1st preference vote share") +
scale_y_discrete("") +
scale_color_manual(values=c("ALP"="red","LNP"="blue","ONP"="black","GRN"="green","KAP"="orange")) +
scale_shape_manual(values=c("ALP"=1,"LNP"=1,"ONP"=1,"GRN"=15,"KAP"=1)) +
theme(panel.border = element_blank(),
legend.position = "top")

Interesting seats
theOnes <- c("Hinchinbrook","Maiwar","Mirani","Mundingburra",
"Maryborough","Callide","Jordan","Noosa")
tabFunc <- function(theDistrict){
cat(paste("###",theDistrict))
kout <- kable(cdata %>%
filter(district==theDistrict) %>%
ungroup() %>%
arrange(r) %>%
select(-ballotOrderNumber,-sitting) %>%
select(-district),
digits=2,
format="markdown",
format.args = list(big.mark=","))
return(kout)
}
for(theDistrict in sort(theOnes)){
print(tabFunc(theDistrict))
}
Callide
| BOYCE, Colin |
LNP |
M |
5,701 |
31.24 |
1 |
| LOHSE, Sharon |
ONP |
F |
4,743 |
25.99 |
2 |
| BLACKWOOD, Darren |
ALP |
M |
4,189 |
22.95 |
3 |
| RADEL, Robbie |
KAP |
M |
2,445 |
13.40 |
4 |
| BAKER, Jaiben |
GRN |
M |
695 |
3.81 |
5 |
| ANDERSON, Sandra |
ZZZ |
F |
477 |
2.61 |
6 |
Hinchinbrook
| CRIPPS, Andrew |
LNP |
M |
7,635 |
30.09 |
1 |
| BELL, Margaret |
ONP |
F |
5,566 |
21.93 |
2 |
| DAMETTO, Nick |
KAP |
M |
5,363 |
21.13 |
3 |
| JACOB, Paul |
ALP |
M |
4,840 |
19.07 |
4 |
| RAFFLES, Peter |
ZZZ |
M |
1,207 |
4.76 |
5 |
| BURNESS, Lyle |
GRN |
M |
767 |
3.02 |
6 |
Jordan
| MULLEN, Charis |
ALP |
F |
9,719 |
39.94 |
1 |
| PUCCI, Michael |
ONP |
M |
4,500 |
18.49 |
2 |
| MURRAY, Duncan |
LNP |
M |
3,441 |
14.14 |
3 |
| CUTCLIFFE, Phil |
ZZZ |
M |
2,469 |
10.15 |
4 |
| HODGSON, Steve |
ZZZ |
M |
2,072 |
8.51 |
5 |
| PURCELL, Steven |
GRN |
M |
1,747 |
7.18 |
6 |
| ERVIK, Peter |
CR |
M |
387 |
1.59 |
7 |
Maiwar
| EMERSON, Scott |
LNP |
M |
11,725 |
42.24 |
1 |
| BERKMAN, Michael |
GRN |
M |
7,666 |
27.62 |
2 |
| KING, Ali |
ALP |
F |
7,647 |
27.55 |
3 |
| DIAMOND, Anita |
ZZZ |
F |
717 |
2.58 |
4 |
Maryborough
| SAUNDERS, Bruce |
ALP |
M |
12,735 |
47.10 |
1 |
| HANSEN, James |
ONP |
M |
8,009 |
29.62 |
2 |
| KINGSTON, Richard |
LNP |
M |
4,657 |
17.22 |
3 |
| ARMSTRONG, Craig |
GRN |
M |
889 |
3.29 |
4 |
| CURRIE, Roger M |
ZZZ |
M |
750 |
2.77 |
5 |
Mirani
| PEARCE, Jim |
ALP |
M |
8,918 |
37.32 |
1 |
| ANDREW, Stephen |
ONP |
M |
7,564 |
31.66 |
2 |
| LATTER, Kerry |
LNP |
M |
6,415 |
26.85 |
3 |
| CARLISLE, Christine |
GRN |
F |
997 |
4.17 |
4 |
Mundingburra
| O’ROURKE, Coralee |
ALP |
F |
7,954 |
31.65 |
1 |
| DERLAGEN, Matthew |
LNP |
M |
6,535 |
26.01 |
2 |
| CHARLWOOD, Mal |
ONP |
M |
4,217 |
16.78 |
3 |
| ABRAHAM, Mike |
KAP |
M |
3,542 |
14.10 |
4 |
| BROWN, Jenny |
GRN |
F |
1,862 |
7.41 |
5 |
| EASZON, Dennis |
ZZZ |
M |
392 |
1.56 |
6 |
| VIRGO, Geoff |
ZZZ |
M |
319 |
1.27 |
7 |
| BIRRELL, Alan R |
ZZZ |
M |
307 |
1.22 |
8 |
Noosa
| BOLTON, Sandy |
ZZZ |
F |
8,684 |
32.04 |
1 |
| ELMES, Glen |
LNP |
M |
8,087 |
29.83 |
2 |
| DENHAM, Mark |
ALP |
M |
3,250 |
11.99 |
3 |
| WHITESIDE, Eve-Marie |
ONP |
F |
3,174 |
11.71 |
4 |
| JENKINS, Phillip |
GRN |
M |
3,071 |
11.33 |
5 |
| WHITE, Aaron |
ZZZ |
M |
564 |
2.08 |
6 |
| BRISTOW, Robin |
ZZZ |
M |
277 |
1.02 |
7 |