Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
needs(tidyverse, magrittr, png)
# Create a folder for storing the charts
dir.create("BFB_images")
# Loop though constituency codes in England and Wales, downloading the chart for each on from BfB
for(pcon in c(B4B_MRP$westminster_constituency[B4B_MRP$region != "Scotland"])){
tryCatch(download.file(paste0("https://www.getvoting.org/charts/",pcon,"_1.png"), destfile = paste0("BFB_images/", pcon, ".png")), error = function(e){message("No chart")})
}
# Function for inferring each party’s projected vote share from the chart
process_chart <- function(constituency_code){
# Read in the chart as a matrix of red, green and blue colour values
img <- readPNG(paste0("BFB_images/",constituency_code,".png"))
# Multiply each colour band by 255 to turn the 0-1 values into standard RGB integer values
r <- img[,,1] * 255
g <- img[,,2] * 255
b <- img[,,3] * 255
# Find the pixel coordinate associated with a vote share of zero by identifying the left-most pixel of the Labour vote share bar
zero <- c(1:330) %>%
map_dbl(~{
min(which(
# The line below finds pixels that are rgb(213,0,0), the colour of the Labour bars
r[.x,1:615]==213 & g[.x,1:615]==0 & b[.x,1:615]==0
)) %>% replace(!is.finite(.), 999)
}) %>%
reduce(min)
# Find the pixel value associated with Labour’s projected vote share by identifying the right-most pixel of the Labour vote share bar
lab <- c(1:330) %>%
map_dbl(~{
max(which(
r[.x,1:615]==213 & g[.x,1:615]==0 & b[.x,1:615]==0
)) %>% replace(!is.finite(.), 0)
}) %>%
reduce(max) %>%
# Then subtract the pixel number associated with zero, to find the number of horizontal pixels used for Labour’s projected vote share
subtract(zero)
# Repeat the above step for all other parties
con <- c(1:330) %>%
map_dbl(~{
max(which(
r[.x,1:615]==0 & g[.x,1:615]==155 & b[.x,1:615]==227
)) %>% replace(!is.finite(.), 0)
}) %>%
reduce(max) %>%
subtract(zero)
lib <- c(1:330) %>%
map_dbl(~{
max(which(
r[.x,1:615]==253 & g[.x,1:615]==187 & b[.x,1:615]==48
)) %>% replace(!is.finite(.), 0)
}) %>%
reduce(max) %>%
subtract(zero)
bxp <- c(1:330) %>%
map_dbl(~{
max(which(
r[.x,1:615]==18 & g[.x,1:615]==182 & b[.x,1:615]==207
)) %>% replace(!is.finite(.), 0)
}) %>%
reduce(max) %>%
subtract(zero)
grn <- c(1:330) %>%
map_dbl(~{
max(which(
r[.x,1:615]==0 & g[.x,1:615]==128 & b[.x,1:615]==102
)) %>% replace(!is.finite(.), 0)
}) %>%
reduce(max) %>%
subtract(zero)
pc <- c(1:330) %>%
map_dbl(~{
max(which(
r[.x,1:615]==64 & g[.x,1:615]==132 & b[.x,1:615]==40
)) %>% replace(!is.finite(.), 0)
}) %>%
reduce(max) %>%
subtract(zero)
oth <- c(1:330) %>%
map_dbl(~{
max(which(
r[.x,1:615]==191 & g[.x,1:615]==191 & b[.x,1:615]==191
)) %>% replace(!is.finite(.), 0)
}) %>%
reduce(max) %>%
subtract(zero)
# If there was no value for Plaid Cymru, the method I’ve used will have returned a negative number (zero minus the pixel associated with zero), so change this to zero
if(pc < 0){
pc <- 0
}
# Now return a little table of party names, vote shares and the constituency code
tibble(
party = c("con", "lab", "lib", "bxp", "pc", "grn", "oth"),
share = c(con, lab, lib, bxp, pc, grn, oth)
) %>%
transmute(constituency_code, party, share = share/sum(share)*100)
}
# Loop through all downloaded images, and process each chart, finally returning a big table of all projected vote shares for all parties in all seats
inferred_shares <- list.files(path="BFB_images/") %>%
str_replace("(\\.png)", "") %>%
imap_dfr(~{
message(.y)
return(process_chart(.x))
}) %>%
spread(party, share, 2:3) %>%
left_join(B4B_MRP %>% dplyr::select(constituency, constituency_code=westminster_constituency)) %>%
dplyr::select(1,9, everything())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment