########################################################
### Open Data Kooperation: univie & Parlament ##########
### Showcase 1: Wiederwahl von NR-Abgeordneten #########
### Code: Laurenz Ennser-Jedenastik & Isabel Kiani #####
### August 2024 ########################################
########################################################
# empty environment
rm(list = ls())
# Installieren und Laden der erforderlichen Pakete.
necessary.packages <- c("httr",
"jsonlite",
"RJSONIO",
"RCurl",
"httr2",
"purrr",
"tidyr",
"dplyr",
"tibble",
"rjson",
"askpass",
"stringr",
"progress")
new.packages <- necessary.packages[!(necessary.packages %in% installed.packages()[,"Package"])]
if(length(new.packages)) install.packages(new.packages)
# load packages
lapply(necessary.packages, library, character.only = TRUE)
# Arbeitsumgebung für das Script und Speicherung von Ergebnissen des API-Calls
setwd("Pfad/zu/Ihrem/Arbeitsverzeichnis")
#Definition von API-URI und Body des API-Calls
req_sc1 <- request("https://www.parlament.gv.at/Filter/api/json/post?jsMode=EVAL&FBEZ=WFW_008&listeId=10008&pageNumber=-1")
t1 <- req_sc1 %>%
req_body_json(list(NRBR="NR", R_WF="FR", M="M", W="W", GP="ALLE"), auto_unbox = FALSE) %>% # Body API Call
req_perform()
df1 <- t1 %>% resp_body_json()
# Loop zur Umwandlung von relativen Links aus den Ergebnislisten des API-Calls (Filter) zu absoluten Links
nrows1 <- length(df1$rows)
vorne <- "https://www.parlament.gv.at"
hinten <- "?json=true"
all.urls <- rep("", nrows1)
all.pads <- rep(NA, nrows1)
# Ladebalken erstellen
pb <- progress_bar$new(
format = " Downloading [:bar] :percent :elapsed",
total = nrows1, clear = FALSE, width = 60
)
for (i in 1:nrows1) {
all.urls[i] <- paste0(vorne, df1[["rows"]][[i]][[9]], hinten)
all.pads[i] <- df1[["rows"]][[i]][[1]]
suppressMessages( # Ausgabe während dem Download unterdrücken
download.file(all.urls[i], destfile = paste0("person_", all.pads[i], ".json"), quiet = TRUE)
)
pb$tick() # Fortschrittsbalken aktualisieren
}
#############################
# END OF DATA COLLECTION #
#############################
#-------------------------------------
#############################
# START OF DATA ANALYSIS #
#############################
# Environment leeren
rm(list = ls())
# Liste aller Files im Arbeitsverzeichnis erstellen
files.in.dir <- list.files(getwd())
# Dataframe df01 erstellen (1 Zeile pro Person)
df01 <- as.data.frame(rep(NA, length(files.in.dir)))
# Loop zum Zählen der Mandate pro Person (1 Mandat = 1 Periode in einem öffentlichen Amt zB. Abgeordnete:r, Minister:in ...)
names(df01)[1] <- "nofm"
for (i in 1:length(files.in.dir)) {
getfile <- fromJSON(file = files.in.dir[i]) # JSON-File einlesen
df01$nofm[i] <- length(getfile$content$biografie$mandatefunktionen$mandate) # Anzahl der Mandate anhand der Länge der Mandatsvariable einlesen
}
# Loop zum Erstellen von IDs & Namen pro Zeile
df01$id <- NA
df01$name <- NA
for (i in which(df01$nofm >= 1)) {
getfile <- fromJSON(file = files.in.dir[i])
df01$id[i] <- getfile$content$personInfo$pad_intern # ID von Nationalratsabgeordnetem/r
df01$name[i] <- getfile$meta$title # Name von Nationalratsabgeordnetem/r
}
# Weitere Dataframes erstellen
dfs <- replicate(14, df01, simplify = FALSE)
list2env(setNames(dfs, paste0("df", sprintf("%02d", 2:15))), envir = .GlobalEnv)
# Liste von Dataframes erstellen
dflist <- list(df01, df02, df03, df04, df05, df06, df07, df08, df09, df10, df11, df12, df13, df14)
### Doppelter Loop: über Dataframes (j) & Zeilen in den Dataframes (i)
# zur Ermittlung von Mandaten, Zeitspannen, Startdatum, Enddatum, Klubzugehörigkeit
for (j in 1:length(dflist)) {
dflist[[j]]$mandate <- NA # leere Mandatsvariable erstellen
dflist[[j]]$zeitspanne <- NA # leere Zeitspannenvariable erstellen
for (i in which(dflist[[j]]$nofm >= j)) {
getfile <- fromJSON(file = files.in.dir[i])
dflist[[j]]$mandate[i] <- getfile$content$biografie$mandatefunktionen$mandate[[j]]$bez # Mandatsvariable befüllen
dflist[[j]]$zeitspanne[i] <- getfile$content$biografie$mandatefunktionen$mandate[[j]]$zeitraum # Zeitspannenvariable befüllen
}
dflist[[j]]$start <- as.Date(substr(dflist[[j]]$zeitspanne, 1, 10), "%d.%m.%Y") # Startdatum
dflist[[j]]$ende <- as.Date(substr(dflist[[j]]$zeitspanne, 12, 21), "%d.%m.%Y") # Enddatum
dflist[[j]]$comma.pos <- regexpr(",", dflist[[j]]$mandate) # Ermittlung der Kommastelle zur Identifikation der Fraktionsbezeichnung
dflist[[j]]$klub <- substr(dflist[[j]]$mandate, dflist[[j]]$comma.pos+2, nchar(dflist[[j]]$mandate)) # Klubzugehörigkeit durch Einspielen der Fraktionsbezeichnung aus dem vorhergehenden Schritt
dflist[[j]] <- dflist[[j]][, -which(names(dflist[[j]])=="comma.pos")] # Hilfsvariable für Kommastellenermittlung aus finalem Dataframe wieder entfernen
}
# Dataframes aus dflist in einen übergreifenden Dataframe zusammenfassen
df.all <- rbind(dflist[[1]], dflist[[2]], dflist[[3]], dflist[[4]], dflist[[5]], dflist[[6]], dflist[[7]],
dflist[[8]], dflist[[9]], dflist[[10]], dflist[[11]], dflist[[12]], dflist[[13]], dflist[[14]])
# check:
head(df.all, 10)
# Alle Zeilen in df.all ohne Mandatsinformation entfernen
df.all <- df.all[!is.na(df.all$mandate), ]
nrow(df.all)
# Alle Zeilen in df.all entfernen, in denen das Mandat kein Nationalratsmandat ist (d.h. Bundesminister:innen, StSek, Bundesrät:innen, ...)
df.all$is.nrabg <- ifelse(regexpr("Abgeordnet", df.all$mandate)==-1, 0, 1) # Wenn der String "Abgeordner" nicht in der Mandatsvariable enthalten ist, dann mit 0 kodieren, wenn schon dann mit 1
df.all <- df.all[df.all$is.nrabg==1, ] # Nur Personen, die im vorhergehenden Schritt mit 1 kodiert werden (= NR-Abg.) im Dataframe inkludieren
df.all <- df.all[, -which(names(df.all)=="is.nrabg")] # Hilfsvariable für Ermittlung der Nationalratsabgeordneten aus finalem Datatframe wieder entfernen
# Alle Zeilen in df.all mit Startdatum vor dem 19.12.1945 entfernen (= Start der V. Legislaturperiode)
df.all <- df.all[df.all$start >= as.Date("19.12.1945", "%d.%m.%Y"), ]
# NA im Enddatum von derzeit aktiven Mitgliedern durch heutiges Datum ersetzen
df.all$ende[is.na(df.all$ende)] <- format(Sys.Date(), "%Y-%m-%d")
# Abgeordnete, die nur einen Tag im Amt sind, eliminieren
df.all$eintag <- 1
df.all$eintag[grep("-", df.all$zeitspanne)] <- 0 # Beobachtungen ohne "-" in der Zeitspannen-Variable finden (i.e. Abgeordnete für nur 1 Tag)
df.all <- df.all[df.all$eintag==0, ] # nur Abgeordnete, die mehr als nur einen Tag im Amt waren, im Dataframe inkludieren (?)
# Manuelle Korrektur: Mandatsperiode für 2 FP-Abgeordnete (IDs: 1803, 2866) um 1 Tag verkürzen (sind analog wie im vorherigen Schritt zu behandeln):
df.all$ende[df.all$id==1803 & substr(df.all$ende, 1, 4)=="1996"] <- df.all$ende[df.all$id==1803 & substr(df.all$ende, 1, 4)=="1996"] - 1
df.all$ende[df.all$id==2866 & substr(df.all$ende, 1, 4)=="1996"] <- df.all$ende[df.all$id==2866 & substr(df.all$ende, 1, 4)=="1996"] - 1
# Zweifach gezählte Abgeordnete eliminieren (KP-Abg. die ebenso mit "LB" als Klubzugehörigkeit gelistet werden)
df.all <- df.all[df.all$klub!="LB", ]
# df.all nach ID und Mandatnummer sortieren
df.all <- df.all[order(df.all$id, df.all$start), ]
# Klub-Varable aggregieren
klub_mapping <- c(
"SPÖ" = "SP",
"ÖVP" = "VP",
"GRÜNE" = "GR",
"BZÖ" = "FP",
"F" = "FP",
"F-BZÖ" = "FP",
"FPÖ" = "FP",
"WdU" = "FP",
"VO" = "KP",
"LB" = "KP",
"KuL" = "KP",
"KPÖ" = "KP",
"NEOS-LIF" = "NEOS",
"NEOS" = "NEOS",
"JETZT" = "PILZ",
"PILZ" = "PILZ",
"STRONACH" = "STRONACH",
"L" = "LF",
"ohne Klubzugehörigkeit" = "ohne"
)
df.all$klub.agg <- klub_mapping[df.all$klub]
# Referenzdaten für Start und Ende der Legislaturperioden definieren
stichtag_start <- as.Date(c("09.11.1949", "19.03.1953", "09.06.1956", "10.06.1959", "15.12.1962", "31.03.1966", # Vektor mit allen Startdaten erstellen:
"01.04.1970", "05.11.1971", "05.11.1975", "05.06.1979", "19.05.1983", "17.12.1986",
"05.11.1990", "07.11.1994", "15.01.1996", "29.10.1999", "20.12.2002", "30.10.2006",
"28.10.2008", "29.10.2013", "09.11.2017", "23.10.2019"), "%d.%m.%Y")
stichtag_ende <- as.Date(c("07.11.1949", "17.03.1953", "07.06.1956", "08.06.1959", "13.12.1962", "29.03.1966", # Vektor mit allen Enddaten erstellen
"30.03.1970", "03.11.1971", "03.11.1975", "03.06.1979", "18.05.1983", "16.12.1986",
"04.11.1990", "06.11.1994", "14.01.1996", "28.10.1999", "19.12.2002", "29.10.2006",
"27.10.2008", "28.10.2013", "08.11.2017", "22.10.2019"), "%d.%m.%Y")
# Namen der Legislaturperioden in einem Vektor zusammenfassen
GPs <- c("GP05", "GP06", "GP07", "GP08", "GP09", "GP10", "GP11", "GP12", "GP13", "GP14","GP15", "GP16", "GP17",
"GP18", "GP19", "GP20", "GP21", "GP22", "GP23", "GP24", "GP25", "GP26", "GP27")
### startGPxx & endeGPxx Variablen generieren, um Abgeordnete zu identifizieren, die zu Stichtagen am Start/Ende der Legislaturperiode anwesend waren
# Ende der Legislaturperiode:
for (i in 1:(length(GPs)-1)) {
df.all$newvar <- NA # leere Variable erstellen
names(df.all)[which(names(df.all)=="newvar")] <- paste("ende", GPs[i], sep="") # Bezeichnung der neuen Variable aus "ende" und zugehöriger Gesetzgebungsperiodennummer zusammensetzen
df.all[, which(names(df.all)==paste("ende", GPs[i], sep=""))] <- ifelse(df.all$ende < stichtag_ende[i] | df.all$start > stichtag_ende[i], 0, 1) # Wenn Abgeordnete:r vor dem Endstichtag aufgehört hat oder erst nach dem Endstichtag begonnen hat, dann mit 0 kennzeichnen sonst mit 1 -> zeigt, welche Abgeordneten am Ende der jeweiligen Gesetzgebungsperiode im Amt waren
}
# Start der Legislaturperiode:
for (i in 2:length(GPs)) {
df.all$newvar <- NA # leere Variable erstellen
names(df.all)[which(names(df.all)=="newvar")] <- paste("start", GPs[i], sep="") # Bezeichnung der neuen Variable aus "start" und zugehöriger Gesetzgebungsperiodennummer zusammensetzen
df.all[, which(names(df.all)==paste("start", GPs[i], sep=""))] <- ifelse(df.all$ende < stichtag_start[i-1] | df.all$start > stichtag_start[i-1], 0, 1) # Wenn Abgeordnete:r vor dem Startstichtag der vorhergehenden Gesetzgebungsperiode aufgehört hat oder nach dem Startstichtag der vorhergehenden Gesetzegbungsgperiode begonnen hat, dann mit 0 kennzeichnen sonst mit 1 -> zeigt, welche Abgeordneten zu Beginn der jeweiligen Gesetzgebungperiode im Amt waren
}
# Dataframe mit wiedergewählten & neuen Abgeordneten für jedes Startjahr einer Legislaturperiode erstellen
jahre <- as.numeric(substr(stichtag_start, 1, 4)) # Jahreszahl aus dem stichtag_start Vektor isolieren (?)
df.jahre <- data.frame(jahre) # Dataframe mit den Jahren erstellen
df.jahre$gp <- 6:27 # jeweilige Gesetzgebungsperiode Nummer zwischen GP06 und GP27 zuordnen
df.jahre$gp.roman <- as.roman(df.jahre$gp) # Nummer der Gesetzgebungsperode in römischen Zahlen darstellen
df.jahre$wiedergew <- 0 # leere Variable für wiedergewählte Abgeordnete erstellen
df.jahre$neu <- 0 # leere Variable für neue Abgeodnete erstellen
# Dataframe mit Anzahl an wiedergewählten und neugewählten Abgeordneten befüllen
for (i in 1:nrow(df.jahre)) {
df.jahre[i, c(which(names(df.jahre)=="wiedergew"), which(names(df.jahre)=="neu"))] <- table(df.all[[paste("ende", GPs[i], sep="")]], df.all[[paste("start", GPs[i+1], sep="")]])[4:3]
# Aus der Kreuztabelle zwischen Abgeordneten am Ende und Start aufeinanderfolgender Gesetzgebungsperioden Ergebnis an vierter Stelle (= anwesend in beiden Gesetzgebungsperioden daher wiedergewählt) und Ergebnis an dritter Stelle (anwesend in nachfolgender Gesetzegbungsperiode aber nicht in vorhergehender, daher neu) in Dataframe einlesen
}
# Gesamtanzahl an Abgeordneten als check berechnen (sollten 165 bis 1970, 183 bis 1971 sein)
df.jahre$checksum <- df.jahre$wiedergew + df.jahre$neu
#####################
### AUSWERTUNGEN: ###
#####################
# Definiere WorkingDirectory für das Abspeichern von Grafiken [OPTIONAL]
# setwd("")
# GRAFIK: wiedergewählte und neu gewählte Abgeordnete zu Beginn jeder GP seit 1945
jpeg("SC1_grafik1.jpg", height = 10, width = 18, units = "cm", res=600)
par(mar=c(4, 10, 4, 2))
b1 <- barplot(c(121, 62), las=1, xlab="Abgeordnete",
col = c("indianred1", "darkseagreen3"), border = "white", font.main=1, beside = FALSE, horiz = TRUE,
main="Wiedergewählte (rot) und neu gewählte (grün) Abgeordnete\nzu Beginn jeder Gesetzgebungsperiode",
names.arg = c("Wiedergewählte Abg.", "Neue Abg."))
text(df.jahre$wiedergew[22] / 2, b1[1], df.jahre$wiedergew[22], cex=0.8)
text(df.jahre$neu[22] / 2, b1[2], df.jahre$neu[22], cex=0.8)
dev.off()
# GRAFIK: wiedergewählte und neu gewählte Abgeordnete zu Beginn jeder GP seit 1945
jpeg("SC1_grafik2.jpg", height = 14, width = 18, units = "cm", res=600)
b1 <- barplot(as.matrix(t(df.jahre[, c(4, 5)])), names.arg = df.jahre$jahre, las=2, ylim=c(0, 200), ylab="Abgeordnete",
col = c("indianred1", "darkseagreen3"), border = "white", font.main=1,
main="Wiedergewählte (rot) und neu gewählte (grün) Abgeordnete\nzu Beginn jeder Gesetzgebungsperiode")
text(b1, df.jahre$wiedergew / 2, df.jahre$wiedergew, cex=0.8)
text(b1, df.jahre$wiedergew + df.jahre$neu / 2, df.jahre$neu, cex=0.8)
mtext("NB: 1971 erfolgte eine Erhöhung der Mandatszahl von 165 auf 183.", 1, 4, cex=0.75)
dev.off()
# TABELLE exportieren:
write.table(df.jahre, "export_showcase1.csv", sep=";")
### Auswahl von 6 Fällen:
# Drei höchste Mandatsgewinne seit 1945: ÖVP 2002 (+ 27), ÖVP 2017 (+15), FPÖ 1990 (+15)
# Drei höchste Mandatsverluste seit 1945: ÖVP 1990 (-17), FPÖ 2019 (-20), FPÖ 2002 (-27)
# 1990 = Wechsel von GP17 auf GP18
# 2002 = Wechsel von GP21 auf GP22
# 2017 = Wechsel von GP25 auf GP26
# 2019 = Wechsel von GP26 auf GP27
# dataframe für alle 6 Fälle kreieren:
df.6cases <- data.frame(case = c("ÖVP 2002", "ÖVP 2017", "FPÖ 1990", "ÖVP 1990", "FPÖ 2019", "FPÖ 2002"))
df.6cases$mandatsplusminus <- c("+27 Mandate", "+15 Mandate", "+15 Mandate", "-17 Mandate", "-20 Mandate", "-27 Mandate")
df.6cases$wiedergew <- NA
df.6cases$neu <- NA
# wiedergewählte Abgeordnete ermitteln:
df.6cases$wiedergew[1] <- table(df.all$endeGP21[df.all$klub.agg=="VP"], df.all$startGP22[df.all$klub.agg=="VP"])[2, 2]
df.6cases$wiedergew[2] <- table(df.all$endeGP25[df.all$klub.agg=="VP"], df.all$startGP26[df.all$klub.agg=="VP"])[2, 2]
df.6cases$wiedergew[3] <- table(df.all$endeGP17[df.all$klub.agg=="FP"], df.all$startGP18[df.all$klub.agg=="FP"])[2, 2]
df.6cases$wiedergew[4] <- table(df.all$endeGP17[df.all$klub.agg=="VP"], df.all$startGP18[df.all$klub.agg=="VP"])[2, 2]
df.6cases$wiedergew[5] <- table(df.all$endeGP26[df.all$klub.agg=="FP"], df.all$startGP27[df.all$klub.agg=="FP"])[2, 2]
df.6cases$wiedergew[6] <- table(df.all$endeGP21[df.all$klub.agg=="FP"], df.all$startGP22[df.all$klub.agg=="FP"])[2, 2]
# neu gewählte Abgeordnete ermitteln:
df.6cases$neu[1] <- table(df.all$endeGP21[df.all$klub.agg=="VP"], df.all$startGP22[df.all$klub.agg=="VP"])[1, 2]
df.6cases$neu[2] <- table(df.all$endeGP25[df.all$klub.agg=="VP"], df.all$startGP26[df.all$klub.agg=="VP"])[1, 2]
df.6cases$neu[3] <- table(df.all$endeGP17[df.all$klub.agg=="FP"], df.all$startGP18[df.all$klub.agg=="FP"])[1, 2]
df.6cases$neu[4] <- table(df.all$endeGP17[df.all$klub.agg=="VP"], df.all$startGP18[df.all$klub.agg=="VP"])[1, 2]
df.6cases$neu[5] <- table(df.all$endeGP26[df.all$klub.agg=="FP"], df.all$startGP27[df.all$klub.agg=="FP"])[1, 2]
df.6cases$neu[6] <- table(df.all$endeGP21[df.all$klub.agg=="FP"], df.all$startGP22[df.all$klub.agg=="FP"])[1, 2]
# GRAFIK: wiedergewählte und neu gewählte Abgeordnete in 6 Fällen mit hohen Mandatsgewinnen bzw. -verlusten
jpeg("SC1_grafik3.jpg", height = 12, width = 20, units = "cm", res=600)
b2 <- barplot(t(as.matrix(df.6cases[, 3:4])), space = c(0, 0, 1, 0, 1, 0, 3, 0, 1, 0, 1, 0), beside = T, col = c("indianred1", "darkseagreen3"), border="white",
main="Wiedergewählte (rot) und neu gewählte (grün) Abgeordnete\nin 6 Fällen mit starken Mandatsgewinnen bzw. -verlusten",
names.arg = df.6cases$case, las=1)
text(b2[1, ], df.6cases$wiedergew / 2, df.6cases$wiedergew)
text(b2[2, ], df.6cases$neu / 2, df.6cases$neu)
axis(1, at=colMeans(b2), labels = df.6cases$mandatsplusminus, lwd=0, line = 1, cex.axis=0.8)
dev.off()
# Tabelle zur Grafik exportieren:
write.table(df.6cases, "export_showcase1_6faelle.csv", sep=";")