#######################################################
## Open Data Kooperation: univie & Parlament ##########
## Showcase 8: Mehrfachbesetzungen von Ausschüssen ####
## code by Laurenz Ennser-Jedenastik & Daniel Bliem ###
### Kontakt: laurenz.ennser@univie.ac.at ##############
#######################################################
# Leeren der Arbeitsumgebung
rm(list = ls())
# Installieren und Laden der erforderlichen Pakete.
necessary.packages <- c("httr", "jsonlite", "RJSONIO", "RCurl", "httr2", "purrr", "tibble", "rjson", "tidyverse", "gridExtra", "showtext", "stringr")
new.packages <- necessary.packages[!(necessary.packages %in% installed.packages()[,"Package"])]
if(length(new.packages)) install.packages(new.packages)
lapply(necessary.packages, library, character.only = TRUE)
# Definieren des Arbeitsverzeichnisses
setwd("Pfad/zu/Ihrem/Arbeitsverzeichnis")
### Herunterladen des ersten Datensatzes: aktuelle NR-Abgeordnete
# Anmerkung: Durch die Verwendung des Datensatzes für aktuelle NR-Abgeordnete aktualisieren sich die Daten automatisch mit erneutem Benutzen des Codes.
# Die Ergebnisse in den Grafiken werden somit andere sein als die im Showcase dargestellten. Für den Showcase wurde der Stichtag 01.06.2024 gewählt.
# Die Teile des Codes, die bei Wiederverwendung geändert werden müssen, sind mit weiteren Anmerkungen versehen.
# Definieren der URL für die POST-Anfrage
req <- request("https://www.parlament.gv.at/Filter/api/json/post?jsMode=EVAL&FBEZ=WFW_002&listeId=undefined&showAll=true&export=true")
# Senden der POST-Anfrage mit definiertem Body - nur aktuelle GP
t1 <-
req %>%
req_body_raw('{
"STEP": [
"1000"
],
"NRBR": [
"NR"
],
"GP": [
"AKT"
],
"R_WF": [
"FR"
],
"R_PBW": [
"WK"
],
"M": [
"M"
],
"W": [
"W"
]
}
') %>%
req_perform()
# Laden der Antwort in einen Datenframe
df1 <- t1 %>% resp_body_json()
# Benötigte Variablen extrahieren
name_list <- lapply(df1$rows, function(x) x[[9]])
pad_list <- lapply(df1$rows, function(x) x[[8]])
party_list <- lapply(df1$rows, function(x) x[[10]])
# Erstellen eines Datenrahmens aus den extrahierten Informationen
df01 <- data.frame(
Name = unlist(name_list),
pad_id = unlist(pad_list),
fraktion = unlist(party_list)
)
# Umformen der pad_id Variable
df01$pad_id <- as.numeric(str_extract(df01$pad_id, "\\d+"))
# Speichern des Dataframes
save(df01, file = "Ihr_Dateiname.RData")
### Herunterladen des 2. Datensatzes: Ausschussmitgliedschaften
# Liste von allen benötigten Personen-IDs
pad_id_list <- unique(df01$pad_id)
# Festlegen des Speicherorts für die JSON Files
setwd("Pfad/zu/Ihrem/Speicherort")
# Herunterladen der JSON Files für jede Person
fetch_data <- function(pad_intern) {
base_url <- "https://www.parlament.gv.at/Filter/api/filter/data/250?js=eval&showAll=true&export=true"
post_body <- list(PAD_INTERN = list(pad_intern))
response <- POST(url = base_url, body = post_body, encode = "json")
if (status_code(response) == 200) {
# Speichern des Inhalts der Antwort (JSON-Daten) in einer Datei
content <- content(response, as = "text")
write(content, file = paste0(pad_intern, ".json"))
}}
# Iterieren dieser Funktion für jede PAD_INTERN-Nummer
for (pad_intern in pad_id_list) {
fetch_data(pad_intern)
}
# Erstellen des leeren Dataframes
df02 <- data.frame(
pad_id = character(),
GP = character(),
position = character(),
ausschuss = character(),
NR = character(),
start_date = character(),
end_date = character(),
stringsAsFactors = FALSE
)
# Pfad zu den JSON Files festlegen
json_files <- list.files(path = "Pfad/zu/Ihrem/Speicherort", pattern = "\\.json$", full.names = TRUE)
# Daten mit Loop extrahieren und in den Dataframe überspielen
for (file in json_files) {
# Laden der JSON-Daten
json_data <- jsonlite::fromJSON(file)
if (!is.null(json_data$rows) && length(json_data$rows) > 0) {
rows_matrix <- json_data$rows
# Durchlaufen jeder Zeile der Matrix und extrahieren der Werte
for (i in 1:nrow(rows_matrix)) {
row <- rows_matrix[i, ]
pad_id <- row[7]
GP <- row[1]
position <- row[3]
ausschuss <- gsub("\\s*\\([^)]+\\)", "", row[4])
NR <- row[5]
date_info <- row[4]
# Beim Enddatum müssen laufende Ausschüsse berücksichtigt werden
if (grepl("\\s+-\\s+", date_info)) {
start_date <- gsub(".*\\((.*?)\\s*-\\s*.*", "\\1", date_info)
end_date <- gsub(".*-\\s*(.*?)\\)", "\\1", date_info)
} else {
start_date <- gsub(".*\\((.*?)\\).*", "\\1", date_info)
end_date <- format(Sys.Date(), "%d.%m.%Y") # Aktuelles Datum als Enddatum für aktive Ausschussmandate
}
# Hinzufügen der extrahierten Werte als neue Zeile
new_row <- data.frame(pad_id, GP, position, ausschuss, NR, start_date, end_date, stringsAsFactors = FALSE)
df02 <- rbind(df02, new_row)
}
} else {
cat("Keine Daten in 'rows' für Datei:", file, "\n")
}
}
# Filtern der Ausschüsse: Kein U-Ausschuss, Unterausschuss, besonderer Ausschuss, Ausschuss im Bundesrat, ...
df02 <- df02 %>%
filter(NR == "NR") %>%
filter(!grepl("unterausschuss|ständiger|unterausschuß|untersuchungsausschuss|besonderer|enquete", ausschuss, ignore.case = TRUE))
# Filtern der Rollen: Nur Mitglieder (da diese Funktion bestehen bleibt, auch wenn eine weitere (Obfrau, Schriftführer, ...) dazukommt)
df02 <- df02 %>% filter(position == "Mitglied")
# Format der Datumsvariablen ändern
df02$start_date <- as.Date(df02$start_date, format = "%d.%m.%Y")
df02$end_date <- as.Date(df02$end_date, format = "%d.%m.%Y")
# Nur aktuelle GP und laufende Mitgliedschaften berücksichtigen - Anm.: Bei Wiederverwendung des Codes auf die aktuelle GP ändern
df02 <- df02 %>% filter(GP == "XXVII" & end_date == Sys.Date())
# Speichern des Dataframes
save(df02, file = "Ihr_Dateiname2.RData")
# Kombinieren der Datensätze
df03 <- merge(df02, df01, by = "pad_id")
### Erstellung eines benutzerdefinierten Themes für die Grafiken
# Laden der Schriftart Lato (stellen Sie zuerst sicher, dass die Schriftart auf dem PC installiert ist)
font_add("Lato",
regular = "Pfad/zu/Ihrer/Schriftart-Regular.ttf",
bold = "Pfad/zu/Ihrer/Schriftart-Bold.ttf")
showtext_auto()
# Erstellen des Themes
custom_theme <- function() {
theme_minimal() +
theme(
plot.background = element_rect(fill = "white", color = NA),
panel.grid.major = element_line(color = alpha("gray", 0.25)),
panel.grid.minor = element_line(color = "white"),
panel.border = element_blank(),
plot.title = element_text(color = "#132843", size = 55, face = "bold", family = "Lato", hjust = 0),
plot.subtitle = element_text(color = "#132843", size = 38, family = "Lato", margin = margin(b = 20), hjust = 0),
axis.title.x = element_text(face = "bold", family = "Lato", size = 35, margin = margin(t = 15)),
axis.title.y = element_text(face = "bold", family = "Lato", size = 35, margin = margin(r = 15)),
axis.text = element_text(family = "Lato", size = 30),
legend.text = element_text(family = "Lato", face = "bold", size = 35),
plot.margin = margin(1.2, 0.7, 0.7, 0.7, "cm"),
plot.title.position = "plot",
plot.caption.position = "plot",
plot.caption = element_text(size = 27)
)
}
# Festlegen der Reihenfolge der Klubs für die Grafiken - Anm.: Bei Wiederverwendung des Codes auf die aktuell im Nationalrat vertretenen Klubs anpassen
fraktion_order <- c("ÖVP", "SPÖ", "FPÖ", "GRÜNE", "NEOS", "OK")
# Festlegen des Speicherorts für die Grafiken
setwd("Pfad/zu/Ihrem/Speicherort")
### 1. Grafik: Anzahl an Ausschussmitgliedschaften pro Abgeordneter
# Zusammenfassen der Anzahl der AUsschussmitgliedschaften pro NR-Abg.
df03_sum <- df03 %>%
group_by(pad_id, fraktion) %>%
summarise(num_observations = n())
# Ergänzen des Dataframes um Philippa Beck, die in keinem Ausschuss Mitglied ist - Anm.: Bei Wiederverwendung des Codes nicht benutzen, bzw. neue unabhängige Abgeordnete ergänzen.
beck <- data.frame(
pad_id = "44127",
num_observations = 0,
fraktion = "OK"
)
df03_sum <- rbind(df03_sum, beck)
# Gruppieren der Abgeordneten mit der gleichen Anzahl an Ausschussmitgliedschaften
df03_plot1 <- df03_sum %>%
group_by(num_observations) %>%
summarise(num_pad_id = n())
# Berechnen der Gesamtanzahl der Ausschussmandate
gesamt_anzahl_mandate <- sum(df03_plot1$num_observations * df03_plot1$num_pad_id)
# Erstellen der ersten Grafik
grafik01 <- ggplot(df03_plot1, aes(x = num_observations, y = num_pad_id, fill = "#132843")) +
geom_bar(stat = "identity") +
geom_text(aes(label = num_pad_id), vjust = -0.5, size = 12) +
labs(x = "Anzahl an Ausschussmitgliedschaften", y = "Anzahl NR-Abgeordneter",
title = paste("Nationalratsabgeordnete nach der Anzahl ihrer Ausschussmitgliedschaften\nam", format(Sys.Date(), "%d.%m.%Y")),
subtitle = paste("Gesamtanzahl der Ausschussmitgliedschaften:", gesamt_anzahl_mandate),
caption = "Quelle: parlament.gv.at") +
scale_x_continuous(breaks = seq(min(df03_sum$num_observations), max(df03_sum$num_observations), by = 1)) +
scale_fill_identity() +
custom_theme() +
theme(plot.title = element_text(lineheight = 0.4))
# Speichern der Grafik
ggsave("SC08_Grafik01.jpg", grafik01, width = 10, height = 7.5, units = "in", dpi = 300)
### 2. Grafik: Verteilung der Ausschussmitgliedschaften innerhalb der Klubs
# Zusammenfassen der Abgeordneten nach Fraktion und Anzahl an Ausschussmitgliedschaften
df03_plot2 <- df03_sum %>%
group_by(fraktion, num_observations) %>%
summarise(count = n()) %>%
ungroup()
# Zusammenfassen der niedrigen und hohen Ausschusszahlen
df03_plot2$num_observations <- ifelse(df03_plot2$num_observations %in% 0:2,
paste0("1-2"),
ifelse(df03_plot2$num_observations %in% 6:8,
paste0("6-8"),
as.character(df03_plot2$num_observations)))
# Prozentuale Berechnung der Balken pro Fraktion
df03_plot2 <- df03_plot2 %>%
group_by(fraktion, num_observations) %>%
summarize(count = sum(count)) %>%
group_by(fraktion) %>%
mutate(percentage = count / sum(count) * 100) %>%
ungroup()
# Herausfiltern der Abgeordneten ohne Klubzugehörigkeit
df03_plot2 <- df03_plot2 %>% filter(fraktion != "OK")
# Manuelle Anpassung der Prozente für spezifische Fälle (damit die Werte in der Grafik gerundet und zusammengezählt 100% ergeben)
# df03_plot2$percentage <- ifelse(df03_plot2$fraktion_obs == "FPÖ4", df03_plot2$percentage + 0.5, df03_plot2$percentage)
# df03_plot2$percentage <- ifelse(df03_plot2$fraktion_obs == "GRÜNE2", df03_plot2$percentage + 0.5, df03_plot2$percentage)
# Neue Variable Fraktion_1 bis 5
df03_plot2 <- df03_plot2 %>%
mutate(
fraktion_obs = paste0(fraktion, case_when(
num_observations == "1-2" ~ "1",
num_observations == "3" ~ "2",
num_observations == "4" ~ "3",
num_observations == "5" ~ "4",
num_observations == "6-8" ~ "5"
))
)
# Reihenfolge der Klubs ändern
fraktion_order <- c("ÖVP", "SPÖ", "FPÖ", "GRÜNE", "NEOS")
df03_plot2$fraktion <- factor(df03_plot2$fraktion, levels = fraktion_order)
# Farbskalen für jede Partei definieren und zuweisen - Anm.: Bei Wiederverwendung des Codes an die aktuell im Nationalrat vertretenen Parteien anpassen
# Anm.: Wenn ein Klub nicht in jeder Kategorie von "num_observations" vertreten ist, kann die Farbe und Farbenzuweisung bei bar_colors entfernt werden
# - Bsp. Anfangs der XXVIII. GP hat niemand aus der SPÖ über 5 Ausschussmitgliedschaften --> num_observations "6-8" ist 0, also fällt weg --> dunkelsten Rot-Ton bei colors_SPOE und bar_colors entfernen
colors_OEVP <- rev(c("#0b707e", "#34a1af", "#62c3d0", "#9ddae2", "#c6f0f6"))
colors_SPOE <- rev(c("#7b0100", "#bc0001", "#fe0000", "#ff6666", "#ff9e9e"))
colors_FPÖ <- rev(c("#002164", "#0136a6", "#0053fb", "#5a8efc", "#8fb3ff"))
colors_Grüne <- rev(c("#35620d", "#4c8d17", "#6ab12f", "#96cc6c", "#bfe7a1"))
colors_NEOS <- rev(c("#8a003e", "#b10b57", "#e3257b", "#fa6eab", "#ff99c8"))
# Reihenfolge der Balkenabschnitte festlegen
# df03_plot2$num_observations=rep(c("1-2", "3", "4", "5", "6-8"),5)
num_obs_order <- c("1-2", "3", "4", "5", "6-8")
df03_plot2$num_observations <- factor(df03_plot2$num_observations, levels = num_obs_order)
# Farben für die Balken und Legende festlegen - Anm.: Bei Wiederverwendung des Codes an die aktuell im Nationalrat vertretenen Parteien anpassen
bar_colors <- c("SPÖ1" = colors_SPOE[1], "SPÖ2" = colors_SPOE[2], "SPÖ3" = colors_SPOE[3], "SPÖ4" = colors_SPOE[4], "SPÖ5" = colors_SPOE[5],
"ÖVP1" = colors_OEVP[1], "ÖVP2" = colors_OEVP[2], "ÖVP3" = colors_OEVP[3], "ÖVP4" = colors_OEVP[4], "ÖVP5" = colors_OEVP[5],
"FPÖ1" = colors_FPÖ[1], "FPÖ2" = colors_FPÖ[2], "FPÖ3" = colors_FPÖ[3], "FPÖ4" = colors_FPÖ[4], "FPÖ5" = colors_FPÖ[5],
"GRÜNE1" = colors_Grüne[1], "GRÜNE2" = colors_Grüne[2], "GRÜNE3" = colors_Grüne[3], "GRÜNE4" = colors_Grüne[4], "GRÜNE5" = colors_Grüne[5],
"NEOS1" = colors_NEOS[1], "NEOS2" = colors_NEOS[2], "NEOS3" = colors_NEOS[3], "NEOS4" = colors_NEOS[4], "NEOS5" = colors_NEOS[5])
legend_colors <- rev(c("#dedede", "#c0c0c0", "#999999", "#727272", "#454545"))
# Erstellen der Grafik
plot2 <- ggplot(df03_plot2, aes(x = factor(fraktion, levels = rev(fraktion_order)), y = percentage, fill = fraktion_obs)) +
geom_bar(stat = "identity", color = "black") +
geom_text(aes(label = ifelse(percentage > 3, paste0(round(percentage), "%"), "")),
position = position_stack(vjust = 0.5),
size = 12,
color = ifelse(df03_plot2$num_observations %in% c("5", "6-8") | df03_plot2$num_observations == "4" & df03_plot2$fraktion == "FPÖ", "white", "black")) +
labs(x = "", y = "",
title = "Verteilung der Anzahl an Ausschussmitgliedschaften\npro Abgeordneten nach Klub",
subtitle = paste("Stand:", format(Sys.Date(), "%d.%m.%Y")),
caption = "Quelle: parlament.gv.at",
fill = "Anzahl der Ausschussmitgliedschaften") +
coord_flip() +
scale_y_continuous(labels = scales::percent_format(scale = 1)) +
scale_fill_manual(values = bar_colors, breaks = c("GRÜNE1", "GRÜNE2", "GRÜNE3", "GRÜNE4", "GRÜNE5"), labels = rev(c("1-2", "3", "4", "5", "6-8"))) +
custom_theme() +
theme(
plot.title = element_text(lineheight = 0.4),
legend.position = "bottom",
legend.title = element_text(face = "bold", size = 35))
# Legendenfarben hinzufügen
grafik02 <- plot2 + guides(fill = guide_legend(override.aes = list(fill = legend_colors)))
# Speichern der Grafik
ggsave("SC08_Grafik02.jpg", grafik02, width = 10, height = 7.5, units = "in", dpi = 300)
### 3. Grafik: Kombinationen von bestimmten Ausschussmitgliedschaften
# Filtern von Personen mit mehr als einem Ausschuss
df03_filtered <- df03 %>%
group_by(pad_id) %>%
filter(n_distinct(ausschuss) > 1)
# Zusammenfassen aller Ausschusskombinationen
df03_combinations <- df03_filtered %>%
group_by(pad_id) %>%
summarise(ausschuss_combinations = list(combn(unique(ausschuss), 2, simplify = FALSE))) %>%
unnest(ausschuss_combinations) %>%
mutate(ausschuss_combinations = map(ausschuss_combinations, ~ sort(.x))) %>%
mutate(ausschuss_combinations = map_chr(ausschuss_combinations, ~ paste(.x, collapse = " &\n")))
# Zählen der Anzahl jeder Kombination
df03_plot3 <- df03_combinations %>%
group_by(ausschuss_combinations) %>%
summarise(count = n()) %>%
arrange(desc(count))
# Filtern auf die Ausschusskombinationen, die häufiger als siebenmal vorkommen
top_combinations <- df03_plot3 %>% filter(count >= 8)
# Erstellen der Grafik
grafik03 <- ggplot(top_combinations, aes(x = reorder(ausschuss_combinations, count), y = count)) +
geom_bar(stat = "identity", fill = "#132843") +
geom_text(aes(label = count), hjust = ifelse(top_combinations$count >= 10, 1.5, 2), size = 12, color = "white") +
labs(x = "", y = "Anzahl der Kombinationen",
title = "Die häufigsten Ausschusskombinationen unter Nationalratsabgeordneten",
subtitle = paste("Stand:", format(Sys.Date(), "%d.%m.%Y")),
caption = "Quelle: parlament.gv.at") +
custom_theme() +
coord_flip() +
theme(axis.text.y = element_text(lineheight = 0.35))
# Speichern der Grafik
ggsave("SC08_Grafik03.jpg", grafik03, width = 10, height = 7.5, units = "in", dpi = 300)