Dieser Foliensatz vermittelt elementare Grundlagen zu folgenden Szenarien:
Schwieriger wird es, wenn Web-Seiten dynamisch aus Datenbanken generiert werden. Dann ist meist eine Fernsteuerung eines Browsers erforderlich, z.B. mit dem Selenium WebDriver (vgl. R-Paket RSelenium). Diese fortgeschrittene Technik wird in diesem Foliensatz nicht behandelt.
Durch die Entwicklung hin zu Open Governmemt bzw. Open Data werden immer mehr Datensätze online zur Verfügung gestellt. Zum Teil sind dies Datenformate, die an eine bestimmte Software gebunden sind (z.B. Excel). Die Regel sind jedoch Datenaustauschformate wie csv und json.
Beispiel 1: Die Stadt Duisburg stellt über ein Open Data-Portal etliche interessante Datensätze zur Verfügung. Wir interessieren uns für eine Tabelle zu "Menschen mit Migrationshintergrund", welche die entsprechende Anteile nach Ortsteilen aufschlüsselt.
Etliche R-Funktionen erkennen, wenn bei einem Dateinamen eine URL angegeben wird und laden die Datei direkt "aus dem Netz". Mit read.csv()
kann man die Datei direkt laden.
df <- read.csv( file = "https://opendata-duisburg.de/sites/default/files/MHGo2018_2.csv", sep = ";" )
btw17_url <- "https://www.bundeswahlleiter.de/dam/jcr/72f186bb-aa56-47d3-b24c-6a46f5de22d0/btw17_kerg.csv" btw17_local <- tempfile() download.file(url = btw17_url, destfile = btw17_local) btw17_aux <- scan(file = btw17_local, what = character(), sep = "\n") df <- read.csv(file = btw17_local, sep = ";", skip = 5)
für die html-spezifische Datenextraktion wird das rvest-Paket verwendet.
direktes Einlesen von Tabellen
Beispiel: Extraktion einer Tabelle zu MdBs aus Wikipedia-Seite
library(rvest) library(xml2) wikipedia_url <- "https://de.wikipedia.org/wiki/Liste_der_Mitglieder_des_Deutschen_Bundestages_%2816._Wahlperiode%29" page <- xml2::read_html(wikipedia_url) tables <- rvest::html_nodes(page, "table") tab <- rvest::html_table(tables[[2]])
head(tab[,1:3])
Wir können beispielsweise das Durchschnittsalter beim Zusammentritt des Bundestags berechnen ...
mean(2005 - as.integer(tab[,2])) # NOT WORKING
Um Text aus html-Dokumenten zu extrahieren, wird die hierarchische Baumstruktur des html-Dokuments mit Xpath-Ausdrücken abgefragt.
Ein typisches Szenario ist die Extraktion von Text aus einem Archiv von Pressemitteilungen (z.B. des Bundespresse- und Informationsamts)
pm <- "http://www.bundesregierung.de/Content/DE/Pressemitteilungen/BPA/2015/07/2015-07-09-bkm-kulturelle-bildung.html" page <- xml2::read_html(pm)
paragraph_nodes <- rvest::html_nodes(page, xpath = "//p") # Identifikation aller Absätze paragraphs <- sapply(paragraph_nodes, html_text) # Extraktion des Texts aus den Absätzeen paragaphs <- paragraphs[nchar(paragraphs) > 0L] # Absätze ohne Text fallen lassen paragaphs[1]
url_ltw <- "https://www.bundeswahlleiter.de/dam/jcr/a333e523-0717-42ad-a772-d5ad7e7e97cc/ltw_erg_gesamt.pdf" ltw_local <- tempfile() pdf_local <- download.file(url = url_ltw, destfile = ltw_local)
library(tabulizer) tabulizer::extract_tables(file = ltw_local, pages = 74)
Unser altes Beispiel: Wahlkreisergebnisse
urlWahlkreisergebnisse <- "http://www.bundeswahlleiter.de/de/bundestagswahlen/BTW_BUND_13/veroeffentlichungen/ergebnisse/kerg.csv" wkTab <- read.table( urlWahlkreisergebnisse, header=T, skip=2, fileEncoding="ISO-8859-1", sep=";" ) wkTab <- wkTab[c(3:nrow(wkTab)),]
Daten von www.govdata.de
... wenn man nach NRW sucht, findet man ...
wahlenKoelnUrl <- "http://offenedaten-koeln.de/sites/default/files/ergebnisse_der_kommunalwahlen_in_koeln_seit_1946_prozent.csv" koelnTab <- read.table(wahlenKoelnUrl, header=T, sep=",")
Daten von Eurostat
library("eurostat") eurostatId <- "tps00189" # asylum and new asylum applicants asylum <- get_eurostat(eurostatId) is(asylum) dim(asylum) View(asylum)
Aha! Wir bekommen die Daten in extensiver Form. Kennen wir von ggplot ...
btArchive <- "http://dipbt.bundestag.de/doc/btp/" lp <- 18 lpArchive <- paste(btArchive, as.character(lp), sep="") maxDoc <- 116 downloadDir <- "/Users/blaette/Lab/tmp/btDownload" for (docNo in c(1:maxDoc)){ docNoFormatted <- sprintf("%03d", docNo) print(docNoFormatted) pdfFilename <- paste(lp, docNoFormatted, ".pdf", sep="") download.file( url=paste(lpArchive, "/", lp, docNoFormatted, ".pdf", sep=""), destfile=file.path(downloadDir, pdfFilename) ) }
library(RCurl) library(XML) wikipediaUrl <- "https://de.wikipedia.org/wiki/Liste_der_Mitglieder_des_Deutschen_Bundestages_%2818._Wahlperiode%29" wikipediaHtml <- RCurl::getURL(wikipediaUrl) wikipediaXml <- htmlTreeParse(wikipediaHtml, useInternalNodes=TRUE) tableXml <- getNodeSet(wikipediaXml, '//table[@class="wikitable"]')[[1]] tableXml <- getNodeSet(wikipediaXml, '//table')[[2]] table <- readHTMLTable(tableXml)
library(rvest) wikipediaUrl <- "https://de.wikipedia.org/wiki/Liste_der_Mitglieder_des_Deutschen_Bundestages_%2816._Wahlperiode%29" page <- html(wikipediaUrl) tables <- html_nodes(page, "table") tab <- html_table(tables[[1]])
pm <- "http://www.bundesregierung.de/Content/DE/Pressemitteilungen/BPA/2015/07/2015-07-09-bkm-kulturelle-bildung.html" page <- html(pm) dateNode <- html_nodes(page, xpath='//div[@class="abstract"]') pClass <- dateNode <- html_nodes(page, css="LMFuss") html_text(pClass) abstractText <- html_text(dateNode[[1]])
faz <- "http://www.faz.net/aktuell/politik/inland/die-steuer-die-spaltet-13692526.html" fazPage <- html(faz) linkedComments <- html_nodes(fazPage, "LMFuss")
if (!"twitteR" %in% rownames(installed.packages())){ install.packages("twitteR") } library(twitteR)
setwd("~/Lab/analysen/twitter") api_key <- scan(file = "api_key.txt", what = character()) api_secret <- scan(file = "api_secret.txt", what = character()) access_token <- scan(file = "access_token.txt", what = character()) access_token_secret <- scan(file = "access_token_secret.txt", what = character())
setup_twitter_oauth( consumer_key = api_key, consumer_secret = api_secret, access_token = access_token, access_secret = access_token_secret )
tweet_list <- list() dates <- seq(from = as.Date("2017-06-01"), to = as.Date("2017-07-14"), by = "day") for (i in 2:length(dates)){ print(dates[i]) twitter_raw <- searchTwitter( searchString = "#pulseofeurope+#PulseOfEurope", # n = 1000, since = as.character(dates[i-1]), until = as.character(dates[i]) ) tweet_list[[as.character(dates[i])]] <- data.frame( text = sapply(twitter_raw, function(x) x$getText()), created = sapply(twitter_raw, function(x) as.character(as.Date(x$getCreated()))), screen_name = sapply(twitter_raw, function(x) x$getScreenName()), retweet = sapply(twitter_raw, function(x) x$getRetweeted()), date = rep(as.character(dates[i]), times = length(twitter_raw)) ) } tweets_df <- do.call(rbind, tweet_list) # tweets_df[["date"]] <- gsub("^(\\d{4}-\\d{2}-\\d{2}).*$", "\\1", # rownames(tweets_df))
unique(tweets_df[, "created"]) unique(tweets_df[, "date"])
dt <- as.data.table(tweets_df) dt_n <- dt[, .N, by = c("screen_name", "date")] for_gg <- as.data.frame(dt_n[1:10]) d <- ggplot(data = for_gg, aes(x = screen_name, y = N)) d <- d + geom_bar(stat = "identity", position = "dodge") d <- d + xlab("Urheber") d <- d + ylab("Zahl der tweets") d dt_cross <- dcast( data = dt_n, formula = date ~ screen_name, value.var = "N" ) colSums(dt_cross[,2:ncol(dt_cross)]) Z <- zoo(dt_cross[,2:ncol(dt_cross)], order.by = as.Date(dt_n[["date"]])) plot(as.xts(Z[, "schwar_ron"]))
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.