2016-07-08 9 views
0

Ich bin neu zu R, und ich bin auf ein Problem gestoßen, das ich nicht lösen kann. Ich würde gerne schwedische Wahldaten auf der Ebene der Wahlkreise abstreifen. Sie sind wie hier gefunden werden kann http://www.val.se/val/val2014/slutresultat/K/valdistrikt/25/82/0134/personroster.htmlR - Html-Adressen von Datenrahmen zu rvest

ich die Daten Ich möchte erhalten, indem Sie diesen Code verwenden:

library(rvest) 
district.data <- read_html("http://www.val.se/val/val2014/slutresultat/K/kommun/25/82/0134/personroster.html") 
prost <- district.data %>% 
html_nodes("table") %>% 
.[[2]] %>% 
html_table() 

Aber das ist nur für ein Viertel von 6227 Bezirken. Die Bezirke sind durch die html-Adresse gekennzeichnet. Auf der oben genannten Website ist sie mit "25/82/0134" gekennzeichnet. Ich kann die Identitäten aller Bezirke finden hier http://www.val.se/val/val2014/statistik/2014_riksdagsval_per_valdistrikt.skv

Und ich las das Semikolon mithilfe dieser Code-Datei in R getrennt:

valres <-read_csv2("http://www.val.se/val/val2014/statistik/2014_riksdagsval_per_valdistrikt.skv")

(als Randnotiz, wie kann ich ändern die Kodierung, damit die schwedischen Buchstaben (zB å, ä, ö) korrekt importiert werden? Das gelingt mir mit read.csv und Angabe encoding='utf-8' aber nicht mit read_csv)

In diesem Datenrahmen sind die Spalten LAN, KOM und VALDIST geben die Identitäten des Bezirks s (beachte, dass VALDIST manchmal nur 2 Zeichen haben). Daher haben die Adressen die folgende Struktur http://www.val.se/val/val2014/slutresultat/K/kommun/LAN/KOM/VALDIST /personroster.html

Also, ich würde in jeder Zeile die Kombination zu verwenden, wie die Identität des Bezirkes zu bekommen, kratzt die Informationen in R, fügen Sie eine Spalte mit der Bezirksidentität hinzu (dh LAN, KOM und VALDIST in einer Zeichenfolge), und zwar über alle 6.227 Bezirke und fügen Sie die Informationen aus jedem dieser Bezirke in einem einzigen Datenrahmen an. Ich nehme an, ich muss eine Art von Schleife oder einige dieser Funktionen verwenden, um über den Datenrahmen zu iterieren, aber ich habe nicht herausgefunden, wie.

UPDATE: Nach der Hilfe erhielt ich (! Danke) in der Antwort unten, jetzt ist der Code wie folgt. Mein verbleibendes Problem ist, dass ich die Bezirksidentität (d. H. paste0(LAN, KOM, VALDIST)) für jede Website hinzufügen möchte, die in einer Spalte im endgültigen Datenrahmen verschrottet wird. Kann mir jemand bei diesem letzten Schritt helfen?

# Read the indentities of the districts (w Swedish letters) 
districts_url <- "http://www.val.se/val/val2014/statistik/2014_riksdagsval_per_valdistrikt.skv" 
valres <- read_csv2(districts_url, locale=locale("sv",encoding="ISO-8859-1", asciify=FALSE)) 

# Add a variabel to separate the two types of electoral districts 
valres$typ <- "valdistrikt" 
valres$typ [nchar(small_valres$VALDIST) == 2] <- "onsdagsdistrikt" 

# Create a vector w all the web addresses to the district data 
base_url <- "http://www.val.se/val/val2014/slutresultat/K/%s/%s/%s/%s/personroster.html" 
urls <- with(small_valres, sprintf(base_url, typ, LAN, KOM, VALDIST)) 

# Scrape the data 
pb <- progress_estimated(length(urls)) 
map_df(urls, function(x) { 

    pb$tick()$print() 
    # Maybe add Sys.sleep(1) 
    read_html(x) %>% 
     html_nodes("table") %>% 
     .[[2]] %>% 
     html_table() 
}) -> df 

Jede Hilfe würde sehr geschätzt werden!

Alles Gute, Richard

Antwort

1

Sie können sprintf() verwenden Positions Substitution zu tun und dann purrr::map_df() verwenden, um einen Vektor von URLs iterieren und einen Datenrahmen erzeugen:

library(rvest) 
library(readr) 
library(purrr) 
library(dplyr) 

districts_url <- "http://www.val.se/val/val2014/statistik/2014_riksdagsval_per_valdistrikt.skv" 
valres <- read_csv2(districts_url, locale=locale("sv",encoding="UTF-8", asciify=FALSE)) 

base_url <- "http://www.val.se/val/val2014/slutresultat/K/valdistrikt/%s/%s/%s/personroster.html" 

urls <- with(valres, sprintf(base_url, LAN, KOM, VALDIST)) 

pb <- progress_estimated(length(urls)) 
map_df(urls, function(x) { 

    pb$tick()$print() 

    read_html(x) %>% 
    html_nodes("table") %>% 
    .[[2]] %>% 
    html_table() 

}) -> df 

Sie sollten jedoch Fügen Sie eine randomisierte Verzögerung hinzu, um zu vermeiden, als Bot blockiert zu werden, und sollten sich die read_html() mit purrr::safely()purrr::safely() ansehen, da nicht alle diese LAN/KOM/VALDIST Kombinationen gültige URLs sind (zumindest in meinen Tests).

Dieser Code bietet auch einen Fortschrittsbalken, da es eine Weile dauern wird (prleby eine Stunde auf einer mäßig anständigen Verbindung).

+0

Vielen Dank für Ihre Antwort!Nur ein paar Nachfragen: 1) Wie füge ich eine zufällige Verzögerung hinzu? und 2) Ich merke, dass selbst mit der Codierung "UTF-8" die Zeichen nicht korrekt importiert werden, kann ich einen ISO-Code in der Codierung angeben? Sorry über alle Fragen, R ist sehr neu für mich. – user2245655

+0

Ich nehme an, dass die Fehlermeldung, die ich erhalte, "Fehler in open.connection (x," rb "): HTTP-Fehler 404.", ist wegen dieser fehlenden Verzögerung. Entschuldigung, eine zusätzliche Frage - Wie kann ich die Identität des Bezirks (d. H. LAN, KOM und VALDIST kombiniert zu einer String-Variablen) als zusätzliche Spalte in dem Datenrahmen hinzufügen, der erstellt wird? – user2245655

+0

Sorry wieder, die Fehlermeldung scheint aufgrund der Tatsache, dass einige HTML-Adressen nicht gültig sind, wie Sie erwähnt haben. Wo VALDIST nur zwei Zeichen hat, ist die Adresse anders. Ich habe es geschafft, das zu lösen, indem ich 'valres $ typ <-" valdistrikt "' 'valres $ typ [nchar (klein_valves $ VALDIST) == 2] <-" onsdagsdistrikt "' hinzufüge. 'base_url <-" http://www.val.se/val/val2014/slutresultat/K/%s/%s/%s/%s/personroster.html "' 'URLs <- mit (valres, sprintf (base_url, Typ, LAN, KOM, VALDIST)) '. Aber ich weiß immer noch nicht, wie man eine Spalte mit der Bezirks-ID, d. H. LAN, KOM und VALDIST, hinzufügt. – user2245655