Valgdata fra EU-valget i 2015 fra DR.dk


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.

valg_dr

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]]
  }
}