Created
March 21, 2019 12:05
-
-
Save chrishanretty/96d35db95cb7da54f51bed9dcd16e340 to your computer and use it in GitHub Desktop.
Plot signatures to a petition calling for revocation of Article 50
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
library(rjson) | |
library(rio) | |
library(tidyverse) | |
library(hrbrthemes) | |
library(ggrepel) | |
json_to_df <- function(f) { | |
json_obj <- tryCatch(fromJSON(file = f), | |
error = function(e) warning(paste0("No data in ",f))) | |
if (class(json_obj) == "character") { | |
## pass | |
sigs <- NULL | |
} else { | |
sigs <- do.call("rbind", | |
lapply(json_obj$data$attributes$signatures_by_constituency,function(x) { | |
data.frame(name = x$name, ons_code = x$ons_code, signature_count = x$signature_count) | |
})) | |
### Get all the things that can be coerced to a one-row data frame | |
### Except signatures by constituency | |
attrs <- names(which(lapply(json_obj$data$attributes, length) == 1)) | |
attrs <- setdiff(attrs, "signatures_by_constituency") | |
attrs <- as.data.frame(json_obj$data$attributes[attrs]) | |
sigs <- merge(sigs, attrs, by = NULL, | |
suffixes = c(".constituency",".total"), | |
all = T) | |
if (nrow(sigs)>0) { | |
sigs$id <- gsub(".json","", f) | |
} | |
} | |
return(sigs) | |
} | |
if (file.exists("241584.json")) { | |
## pass | |
} else { | |
download.file("https://petition.parliament.uk/petitions/241584.json", | |
destfile = "241584.json") | |
} | |
dat <- json_to_df("241584.json") | |
if (file.exists("BES-2017-General-Election-results-file-v1.0.xlsx")) { | |
## pass | |
} else { | |
download.file("https://www.britishelectionstudy.com/wp-content/uploads/2017/07/BES-2017-General-Election-results-file-v1.0.xlsx", | |
destfile = "BES-2017-General-Election-results-file-v1.0.xlsx") | |
} | |
aux <- import("BES-2017-General-Election-results-file-v1.0.xlsx") | |
dat <- merge(dat, aux, | |
by.x = c("ons_code"), | |
by.y = c("ONSConstID"), | |
all.x = FALSE, | |
all.y = TRUE) | |
dat <- dat %>% | |
mutate(signature_rate = signature_count.constituency / Electorate17, | |
Nation = substr(ons_code, 0, 1), | |
Nation = case_when(Nation == "E" ~ "England", | |
Nation == "S" ~ "Scotland", | |
Nation == "W" ~ "Wales"), | |
party_col = case_when(Winner17 == "Conservative" ~ "#0087dc", | |
Winner17 == "Labour" ~ "#d50000", | |
Winner17 == "Liberal Democrat" ~ "#FDBB30", | |
Winner17 == "Scottish National Party" ~ "#FFF95D", | |
Winner17 == "Green" ~ "#008066", | |
Winner17 == "Speaker" ~ "darkgrey", | |
Winner17 == "Plaid Cymru" ~ "#3F8428")) | |
mod <- lm(I(signature_rate / 100) ~ remainHanretty, data = dat) | |
p <- ggplot(dat, aes(x = remainHanretty, y = signature_rate)) + | |
geom_point(aes(shape = Nation, fill = party_col), | |
alpha = 0.9, size = 4, colour = "black") + | |
scale_x_continuous("Remain % in 2016") + | |
scale_y_continuous("Signatures as % of 2017 electorate", | |
labels = scales::percent, | |
limits = c(0, NA)) + | |
scale_fill_identity("Party") + | |
scale_shape_manual(values = c(21, 22, 23)) + | |
geom_smooth(method = "lm", se = FALSE, colour = "black", lty = 2) + | |
geom_text_repel(data = subset(dat, signature_rate > 0.05), | |
aes(label = name)) + | |
theme_minimal() + | |
theme_ipsum_rc() + | |
labs(title = "Constituencies which voted to Remain sign the Article 50 revocation petition at higher rates", | |
caption = "Source: petition.parliament.uk; Hanretty (2017), 'Areal interpolation and the UK's referendum on EU membership'") | |
ggsave(p, file = "revocation_petition.png", width = 1024/300, height = 512/300, units = "in", dpi = 300, scale = 5) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment