DR er så venlig at lave en side som viser alle valgresulterne efter område i et fint kort. Uheldigvis er det ikke så nemt at få fat i dataene.
Så er det godt at vi kan skrabe dem. 🙂
Data til download:
Lidt detaljer om koden
Siden loader først et kort (vist ovenfor) og en række mindre områder på kortet (storkredse og kredse) i json format. De egentlige data bliver loadet senere, så vidt jeg kan se. Dataene om kortet indeholder ikke selve valgstederne, som i stedet findes i en liste på siden. Når man vælger et valgsted, så henter browseren en json fil med tallene. Disse filer følger et simpelt ID format, så man kan hente dem alle sammen med et loop. Underligt nok er der en del huller, nemlig IDer som ikke svarer til et valgsted. Når man forsøger at hente en af dem (fx id=4) så gir DR bare en 404. Så hvordan ved man hvor mange der er? Jeg prøver bare alle sammen indtil jeg har fået 100 fejl i træk. Det virker usandsynligt at der skulle være flere bagefter det. Hvis man følger denne regel, så er der 1386 valgsteder. Ved valget til EU i 2014 var der 1396, så det tal lyder plausibelt.
De enkelte json filer indeholder ikke valgstederne beliggenhed, uheldigvis. De indeholder dog id’et på den kreds valgstedet er i, og dette id finder man i dataene fra valgkortet. De indeholder også valgstedets navn, men det er ikke altid brugbart. Fx “Østre” eller “1. Nord”. Sætter man det sammen med kredsens navn, så gir det dog mening: “Østre – Svendborg”, “1. Nord – Østerbro” (Københavns Storkreds).
R kode til skrabning
# udtræk stemmedata fra DR ------------------------------------------------
#json
library(pacman)
p_load(stringr, rjson)
#hent json
json = fromJSON(file = "http://www.dr.dk/tjenester/fa15-result-data/map/fa2015")
#inspicer
#lad hellere vær for det er noget rod! lister i lister i liste
str(json)
#lav en flad version
json_flat = unlist(json)
#for at lave om til 2D, så skal de finde hver kolonne
#det kan gøres efter navnene. Der er 7 slags.
v_kolonnenavne = names(json_flat)[1:7]
#df
d = list()
#loop di loop
for (kolonne in v_kolonnenavne) {
logi = str_detect(names(json_flat), kolonne)
#kan godt fejle hvis en kolonne ikke findes alle steder
try({d[[kolonne]] = json_flat[logi]})
}
#lav om til df
#gir en fejl hvis vektorne ikke er lige lange
d = as.data.frame(d)
# download valgsteddata ---------------------------------------------------------
#startobjekter
json2 = list()
fejl_i_træk = 0
#loopy loop
for (id in 1:5000) {
#stop hvis ikke mere data, måske
#stop efter 100 fejl i træk
if (fejl_i_træk == 100) break
#progression
str_c("prøver id", id) %>% message
#lav url
url = str_c("http://www.dr.dk/tjenester/fa15-result-data/results/fa2015/afstemningssted/", id)
#download med try
trial = try({get = fromJSON(file = url)}, T)
if ("try-error" %in% class(trial)) {
str_c("id ", id, " fejlede") %>% message
fejl_i_træk = fejl_i_træk + 1
next
}
#ellers gem
json2[[id]] = get
fejl_i_træk = 0
}
#gem data
save(json2, file = "valgdata.RDS")
#navne
names(json2) = 1:length(json2)
#fjern de tomme id'er
json2 = json2[sapply(json2, Negate(is.null))]
#konverter til 2D df
#hvilke data vil vi gemme?
v_kolonnenavne2 = c("AreaType", "ID", "ParentID", "GrandParentID", "Name", "Eligable", "Turnout", "Yes", "No", "Invalid", "Abstained")
#objekt
d2 = as.data.frame(matrix(nrow = length(json2), ncol = length(v_kolonnenavne2)))
colnames(d2) = v_kolonnenavne2
#loop de loop
for (idx in seq_along(json2)) {
#main
for (var in v_kolonnenavne2[1:5]) {
d2[idx, var] = json2[[idx]][var]
}
#metrics
for (var in v_kolonnenavne2[6:7]) {
d2[idx, var] = json2[[idx]][["Metrics"]][[var]]
}
#Chart
for (var in v_kolonnenavne2[8:11]) {
d2[idx, var] = json2[[idx]][["Chart"]][[var]]
}
}
