Dieses Dokument beschreibt die Vorprozessierung und explorative Analyse des Datensatzes, der Grundlage des auf srf.ch veröffentlichten Artikel Wenn fehlende Parlamentarier den Unterschied machen ist.
SRF Data legt Wert darauf, dass die Datenvorprozessierung und -Analyse nachvollzogen und überprüft werden kann. SRF Data glaubt an das Prinzip offener Daten, aber auch offener und nachvollziehbarer Methoden. Zum anderen soll es Dritten ermöglicht werden, auf dieser Vorarbeit aufzubauen und damit weitere Auswertungen oder Applikationen zu generieren.
Die Endprodukte des vorliegenden Scripts, neben der vorliegenden explorativen Analyse, sind folgende Files:
cases.xls
: Der Datensatz, der alle Fälle aufzeigt, bei denen Fraktionen Abstimmungen verloren, die sie hätten gewinnen können, wenn keine Fraktionsmitglieder gefehlt hätten. In diesem Datensatz kann eine bestimmte Abstimmung mehrfach vorkommen, wenn mehrere Fraktionen die Chance gehabt hätten, den Ausgang einer Abstimmung zu beeinflussen.cases_unique.xls
: Der Datensatz weist jede der betroffenen Abstimmungen auf, unabhängig von und ohne Angabe zur betroffenen Fraktion.Die Vorprozessierung und Analyse wurde im Statistikprogramm R vorgenommen. Das zugrunde liegende Script sowie die prozessierten Daten können unter diesem Link heruntergeladen werden. Durch Ausführen von main.Rmd
kann der hier beschriebene Prozess nachvollzogen und der für den Artikel verwendete Datensatz generiert werden. Dabei werden Daten aus dem Ordner input
eingelesen und Ergebnisse in den Ordner output
geschrieben.
SRF Data verwendet das rddj-template von Timo Grossenbacher als Grundlage für seine R-Scripts. Entstehen bei der Ausführung dieses Scripts Probleme, kann es helfen, die Anleitung von rddj-template zu studieren.
Debug-Informationen: This report was generated on 2018-12-07 10:23:59. R version: 3.4.4 on x86_64-pc-linux-gnu. For this report, CRAN packages as of 2018-01-01 were used.
Der Code für die vorliegende Datenprozessierung ist auf https://github.com/srfdata/2018-02-parlament-absenzen zur freien Verwendung verfügbar.
2018-02-parlament-absenzen von SRF Data ist lizenziert unter einer Creative Commons Namensnennung - Weitergabe unter gleichen Bedingungen 4.0 International Lizenz.
Code & Daten von SRF Data sind unter http://srfdata.github.io verfügbar.
Die veröffentlichten Informationen sind sorgfältig zusammengestellt, erheben aber keinen Anspruch auf Aktualität, Vollständigkeit oder Richtigkeit. Es wird keine Haftung übernommen für Schäden, die durch die Verwendung dieses Scripts oder der daraus gezogenen Informationen entstehen. Dies gilt ebenfalls für Inhalte Dritter, die über dieses Angebot zugänglich sind.
Die Originalquelle ist die Abstimmungsdatenbank des Parlamentsdienstes der Schweiz. Dort veröffentlicht der Parlamentsdienst Namenslisten mit dem Abstimmungsverhalten aller Mitglieder des Nationalrats seit Beginn der 49. Legislaturperiode.
## [1] "package package:rmarkdown detached"
# von https://mran.revolutionanalytics.com/web/packages/checkpoint/vignettes/using-checkpoint-with-knitr.html
# alle Packages, die nicht gebraucht werden,
# können hier entfernt werden (auskommentieren reicht nicht!)
# Wichtig: wenn neues Package installiert werden soll,
# scanForPackages = T setzen im checkpoint() call im nächsten Chunk
# tidyverse: see https://blog.rstudio.org/2016/09/15/tidyverse-1-0-0/
cat(
"
library(rstudioapi) # temporary bugfix, might be removed when renewing date
library(tidyverse) # ggplot2, dplyr, tidyr, readr, purrr, tibble
library(magrittr) # pipes
library(stringr) # string manipulation
library(readxl) # excel
library(WriteXLS) #write excel
library(scales) # scales for ggplot2
library(jsonlite) # json
library(forcats) # easier factor handling,
library(lintr) # code linting, auf keinen Fall entfernen ;-)
library(styler) # code formatting
library(rmarkdown) # muss für automatisches knitting
# in deploy.sh eingebunden werden",
file = "manifest.R"
)
# if checkpoint is not yet installed, install it (for people using this
# system for the first time)
if (!require(checkpoint)) {
if (!require(devtools)) {
install.packages("devtools", repos = "http://cran.us.r-project.org")
require(devtools)
}
devtools::install_github("RevolutionAnalytics/checkpoint",
ref = "v0.3.2", # could be adapted later,
# as of now (beginning of July 2017
# this is the current release on CRAN)
repos = "http://cran.us.r-project.org")
require(checkpoint)
}
## Loading required package: checkpoint
##
## checkpoint: Part of the Reproducible R Toolkit from Microsoft
## https://mran.microsoft.com/documents/rro/reproducibility/
# nolint start
if (!dir.exists("~/.checkpoint")) {
dir.create("~/.checkpoint")
}
# nolint end
# install packages for the specified CRAN snapshot date
checkpoint(snapshotDate = package_date,
project = path_to_wd,
verbose = T,
scanForPackages = T,
use.knitr = F,
R.version = R_version)
## Scanning for packages used in this project
## rmarkdown files found and will not be parsed. Set use.knitr = TRUE
## - Discovered 13 packages
## All detected packages already installed
## checkpoint process complete
## ---
rm(package_date)
source("manifest.R")
## ── Attaching packages ────────────────────────────────── tidyverse 1.2.1 ──
## ✔ ggplot2 2.2.1 ✔ purrr 0.2.4
## ✔ tibble 1.4.1 ✔ dplyr 0.7.4
## ✔ tidyr 0.7.2 ✔ stringr 1.2.0
## ✔ readr 1.1.1 ✔ forcats 0.2.0
## ── Conflicts ───────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
##
## Attaching package: 'magrittr'
## The following object is masked from 'package:purrr':
##
## set_names
## The following object is masked from 'package:tidyr':
##
## extract
##
## Attaching package: 'scales'
## The following object is masked from 'package:purrr':
##
## discard
## The following object is masked from 'package:readr':
##
## col_factor
##
## Attaching package: 'jsonlite'
## The following object is masked from 'package:purrr':
##
## flatten
unlink("manifest.R")
sessionInfo()
## R version 3.4.4 (2018-03-15)
## Platform: x86_64-pc-linux-gnu (64-bit)
## Running under: Ubuntu 18.04.1 LTS
##
## Matrix products: default
## BLAS: /opt/R/R-3.4.4/lib64/R/lib/libRblas.so
## LAPACK: /opt/R/R-3.4.4/lib64/R/lib/libRlapack.so
##
## locale:
## [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
## [3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8
## [5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
## [7] LC_PAPER=en_US.UTF-8 LC_NAME=C
## [9] LC_ADDRESS=C LC_TELEPHONE=C
## [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] rmarkdown_1.8 styler_1.0.0 lintr_1.0.2 jsonlite_1.5
## [5] scales_0.5.0 WriteXLS_4.0.0 readxl_1.0.0 magrittr_1.5
## [9] forcats_0.2.0 stringr_1.2.0 dplyr_0.7.4 purrr_0.2.4
## [13] readr_1.1.1 tidyr_0.7.2 tibble_1.4.1 ggplot2_2.2.1
## [17] tidyverse_1.2.1 rstudioapi_0.7 checkpoint_0.4.0
##
## loaded via a namespace (and not attached):
## [1] reshape2_1.4.3 haven_1.1.0 lattice_0.20-35 colorspace_1.3-2
## [5] htmltools_0.3.6 yaml_2.1.16 rlang_0.1.6 pillar_1.0.1
## [9] foreign_0.8-69 glue_1.2.0 modelr_0.1.1 bindrcpp_0.2
## [13] bindr_0.1 plyr_1.8.4 munsell_0.4.3 gtable_0.2.0
## [17] cellranger_1.1.0 rvest_0.3.2 psych_1.7.8 evaluate_0.10.1
## [21] knitr_1.18 rex_1.1.2 parallel_3.4.4 broom_0.4.3
## [25] Rcpp_0.12.14 backports_1.1.2 mnormt_1.5-5 hms_0.4.0
## [29] digest_0.6.13 stringi_1.1.6 grid_3.4.4 rprojroot_1.3-1
## [33] cli_1.0.0 tools_3.4.4 lazyeval_0.2.1 crayon_1.3.4
## [37] pkgconfig_2.0.1 xml2_1.1.1 lubridate_1.7.1 assertthat_0.2.0
## [41] httr_1.3.1 R6_2.2.2 nlme_3.1-131.1 compiler_3.4.4
# falls Logik auf andere Scripts ausgelagert werden soll (z.B. der Übersichtlichkeit halber), hier einkommentieren
Für jede Abstimmung im Nationalrat liegen Daten zum Abstimmungsverhalten der einzelnen Ratsmitglieder vor. Der Parlamentsdienst stellt die Daten sessionsweise als xlsx-Dateien zur Verfügung. Daraus sollen die oben beschriebenen Datensätze erstellt werden.
# Leere Datensätze erstellen, um mit dem Loop aufzufüllen
cases <- data.frame()
abstimmungen <- data.frame()
parlamentarier <- data.frame()
# Loop, der die einzelnen xlsx-Files jeder Session einliest und verarbeitet
temp <- list.files(
path = "input",
pattern = "*.xlsx"
)
# Beginn des Loops
for (i in temp) {
# Schritt 1: Abstimmung und Abstimmungsverhalten der Parlamentarier einlesen und zu einem Datensatz zusammenfassen
# xlsx-Dateien zu Abstimmungen einlesen und Bereich auswählen
votes_loop <- read_excel(
paste(
"input/",
i,
sep = ""
),
col_names = TRUE,
range = anchored("A9", dim = c(NA, NA))
)
# Zur einfacheren Verarbeitung nur das Datum der Abstimmungen speichern
votes_loop %<>%
mutate(VoteDate = str_sub(VoteDate, 0, 10))
# Liste aller Abstimmungen wird bei jedem Durchgang des Loops ergänzt
abstimmungen %<>%
bind_rows(
select(votes_loop,
VoteDate:VoteSubmissionText,
Decision:Präsident)
)
# Transformieren des Datensatzes, alle Parlamentarier und Abstimmungen einzeln auflisten
votes_loop %<>%
gather(
BioId,
VoteDecision,
13:(ncol(votes_loop) - 7)
)
# Schritt 2: Ein Datensatz aller Parlamentarier erstellen
# xlsx-Dateien zu Parlamentariern einlesen, Bereich auswählen und neu benennen
parl_loop <-
read_excel(
paste(
"input/",
i,
sep = ""
),
col_names = F,
range = anchored("M1", dim = c(8, NA))
)
parl_loop %<>%
t() %>%
as.data.frame() %>%
rename(
Id = V1,
BioId = V2,
CouncillorName = V3,
Rat = V4,
Fraktion = V5,
Kanton = V6,
Geburtsdatum = V7,
Vereidigungsdatum = V8) %>%
mutate(BioId = as.character(BioId),
Id = as.character(Id),
CouncillorName = as.character(CouncillorName),
Geburtsdatum = as.character(Geburtsdatum),
Vereidigungsdatum = as.character(Vereidigungsdatum),
Fraktion = as.character(Fraktion))
# Datensatz aller Parlamentarier wird bei jedem Durchgang des Loops ergänzt
parlamentarier %<>%
bind_rows(
parl_loop)
# Schritt 3: Das Abstimmungsverhalten der Fraktionen zu jeder einzelnen Abstimmung berechnen Datensatz zu Abstimmungen und Parlamentarieren mergen und anpassen
data_merged <-
full_join(
votes_loop,
parl_loop,
by = "BioId"
)
# Datensatz spezifieren, rekodieren und Abstimmungen nach Fraktionen gruppieren
data_merged %<>%
select(
BioId,
Id,
Name = CouncillorName,
Rat = Rat.x,
Fraktion,
Kanton,
Date = VoteDate,
Kommission,
Dept.,
AffairId,
AffairTitle,
VoteId = VoteRegistrationNumber,
VoteMeaningYes,
VoteMeaningNo,
DivisionText,
SubmissionText = VoteSubmissionText,
VoteDecision,
RatJa = Ja,
RatNein = Nein,
RatEnth = `Enth.`,
RatEntsch = `Entschuldigung gem. Art. 57 Abs. 4`,
RatNicht = `Hat nicht teilgenommen`,
RatPres = Präsident) %>%
mutate(Ja = case_when(VoteDecision ==
"Ja" ~ 1, TRUE ~ 0),
Nein = case_when(VoteDecision ==
"Nein" ~ 1, TRUE ~ 0),
Ent = case_when(VoteDecision ==
"Enthaltung" ~ 1, TRUE ~ 0),
Abw = case_when(VoteDecision ==
"Hat nicht teilgenommen" ~ 1, TRUE ~ 0),
AbwEnt = case_when(VoteDecision ==
"Entschuldigt" ~ 1, TRUE ~ 0),
Pres = case_when(VoteDecision ==
"Der Präsident stimmt nicht" ~ 1, TRUE ~ 0)) %>%
group_by(VoteId, Fraktion) %>%
summarise(
Ja = sum(Ja),
Nein = sum(Nein),
Enthaltung = sum(Ent),
Abwesend = sum(Abw),
Entschuldigt = sum(AbwEnt),
Präsident = sum(Pres),
RatJa = mean(RatJa),
RatNein = mean(RatNein),
RatEnthaltung = mean(RatEnth),
RatEntschuldigt = mean(RatEntsch),
RatAbwesend = mean(RatNicht)
)
# Schritt 4: Potenzial berechnen, um die für die Auswertung relevanten Fälle zu finden
# Das Potenzial A ist die Differenz zwischen der Anzahl der fehlenden Personen einer Fraktion und der Stimmendifferenz im Rat. Das Potenzial gibt darüber Auskunft, ob eine Fraktion eine Abstimmung hätte gewinnen können, wenn alle Mitglieder anwesend gewesen wären. In der Regel trifft dies zu für Fraktionen und Abstimmungen mit einem Potenzial A > 0. Allerdings gibt es 2 Ausnahmen, bei denen auch Potenzial A = 0 ausreicht. Aus diesem Grund werden vorerst auch diese Fälle mitberücksichtigt. (Wird später für die Berechnung von Potenzial B und Potenzial C relevant.)
# Berechnen, wie eine Abstimmungen aus Sicht der Fraktionsmehrheit ausging
data_merged %<>%
mutate(RatDifferenz = RatJa - RatNein,
Fehlende = Abwesend, #+ Entschuldigt,
PotentialA = Fehlende - abs(RatDifferenz)) %>%
mutate(Ausgang = ( Ja / ( Ja + Nein ) - 0.5 ) /
( RatJa / ( RatJa + RatNein ) - 0.5 ) ) %>%
mutate(Ausgang = case_when(Ausgang <= 0 ~ "Verloren",
TRUE ~ "Gewonnen")) %>%
filter(PotentialA > -1 &
Ausgang == "Verloren")
# Fälle, in denen das Potenzial A mindestens 0 beträg und die Abstimmung aus Sicht der Fraktionsmehr verloren wurde, an den Datensatz "cases" anhängen
cases %<>%
bind_rows(data_merged)
}
# Nicht weiter benötigte Datensätze löschen
rm(data_merged)
rm(votes_loop)
rm(parl_loop)
# Rekodieren der CVP-Fraktion
cases %<>%
mutate(Fraktion = recode(Fraktion, "CE" = "C"))
# Jeden Parlamentarier nur einmal im Datensatz
parlamentarier %<>%
distinct(BioId, .keep_all = T)
Eine Abstimmungen gilt dann als verschenkt, wenn die Anzahl der Abwesenden einer Fraktion grösser ist als die totale Stimmendifferenz (d.h. “Potenzial A” > 0). Wie bereits erwähnt, gibt es aber zwei Ausnahmen:
Abstimmungen, bei denen der Präsident aufgrund von Stimmengleichheit im Rat den Stichentscheid fällt. Ist die Anzahl der Abwesenden in diesem Fall gleich gross wie die totale Stimmendifferenz (“Potenzial A” = 0), gilt die Abstimmung dennoch als verschenkt. Obwohl die Stimmendifferenz = 1, hätte 1 zusätzliches Fraktionsmitglied schon gereicht, um die Abstimmung zu gewinnen (da der Präsident dann nicht mitgestimmt hätte). Für diese Fälle gilt “Potenzial B” = 1.
# Dazu wird zuerst berechnet, in welchen Abstimmungen der Präsident den Stichentscheid fällte. (Der Präsident kann bei einer Reihe von besonderen Abstimmungen mitstimmen, nicht nur wenn im Rat Stimmenparität herrscht. Weil wir aber nur die Stichentscheide wollen, suchen wir also all jene Entscheide, bei denen der Präsident mitstimmte und die Stimmendifferenz 1 beträgt.)
abstimmungen %<>%
mutate(Differenz = Ja - Nein)
# Subset erstellen für Abstimmungen, die der Präsident per Stichentscheid entschied
abstimmungen_pres <- abstimmungen %>%
select(
Dept.,
AffairId,
VoteRegistrationNumber,
Ja,
Nein,
Differenz,
Präsident
)
abstimmungen_pres %<>%
mutate(Differenz = abs(Differenz))
abstimmungen_pres %<>%
filter(Differenz == 1 &
Präsident == "True") %>%
select(
VoteRegistrationNumber,
PresDec = Präsident
)
# In einer neuen Variable PotentialB wird vermerkt, ob ein Stichentscheid des Präsidenten stattfand
cases %<>%
left_join(
abstimmungen_pres,
by = c("VoteId" = "VoteRegistrationNumber")) %>%
mutate(PotentialB = case_when(PresDec == "True" &
PotentialA == 0 ~ 1,
TRUE ~ 0))
rm(abstimmungen_pres)
Ein weiterer Spezialfall sind Abstimmungen, bei denen die Anzahl der Abwesenden einer Fraktion gleich gross ist wie die totale Stimmendifferenz (d.h. “Potenzial A” = 0) und der NR-Präsident der eigenen Fraktion angehört. Wären in diesem Fall alle Fraktionsteilnehmer anwesend, entschiede der Präsident per Stichentscheid. Da dieser der eigenen Fraktion angehört, wird davon ausgegangen, dass er ebenfalls im Sinne der Fraktionsmehrheit stimmt. In diesem Fall gilt “Potenzial C” = 1.
# Diese Fälle werden in der Variable PotentialC vermerkt.
cases %<>%
mutate(PotentialC = case_when(Präsident == 1 ~ 1,
TRUE ~ 0))
Erst die Variable PotentialTotal beinhaltet alle Spezialfälle. Weist eine Abstimmung für eine Fraktion also eine Gesamtpotenzial von mind. 1 auf, gilt die Abstimmung als verschenkte Chance. Es können also alle Abstimmungen und Fraktionen entfernt werden, bei denen das PotentialTotal 0 oder kleiner ist.
# Variable PotentialTotal berechnen und berücksichtigen
cases %<>%
mutate(PotentialTotal =
PotentialA +
PotentialB +
PotentialC) %>%
filter(PotentialTotal > 0)
# Datensatz zu "verschenkten Abstimmungen" mit Zusatzdaten zu Abstimmungen (Titel, Text, etc.) kombinieren
abstimmungen_t <- abstimmungen %>%
select(
Date = VoteDate,
Kommission,
Dept = `Dept.`,
`AffairId`,
Title = AffairTitle,
VoteMeaningYes,
VoteMeaningNo,
DivisionText,
VoteSubmissionText,
VoteId = VoteRegistrationNumber
)
cases %<>% left_join(
abstimmungen_t,
by = "VoteId"
)
rm(abstimmungen_t)
# Umbrüche entfernen
cases %<>%
mutate(Title = str_replace_all(Title, "[\r\n]", " "),
VoteMeaningYes = str_replace_all(VoteMeaningYes, "[\r\n]", " "),
VoteMeaningNo = str_replace_all(VoteMeaningNo, "[\r\n]", " "),
DivisionText = str_replace_all(DivisionText, "[\r\n]", " "),
VoteSubmissionText = str_replace_all(VoteSubmissionText, "[\r\n]",
" "))
Die Analyse basiert auf der Annahme, dass die abwesenden Parlamentarier gleich stimmen wie die Mehrheit der anwesenden Fraktionsmitglieder. Diese Annahme ist aber nur realistisch, wenn es in der Fraktion klare Mehrheitsverhältnisse gibt. Mit dem Threshold wird festgelegt, wie gross die Mehrheit in Prozent mindestens sein soll, damit der Fall in der Analyse berücksichtigt wird.
# Der Threshold wird bei 75% angelegt.
ts1 <- 75
cases %<>%
mutate(JaAnteil = Ja / (Ja + Nein)) %>%
filter(JaAnteil > (ts1 / 100) |
JaAnteil < (100 - ts1) / 100)
Es gibt auch Fälle, wo sich ein Teil der Fraktion der Stimme enthält. Je grösser der Anteil der anwesenden Fraktionsmitglieder, der sich einer Stimme enthält, desto unwahrscheinlicher wird die Annahme, dass die abwesendenen Mitglieder mit der stimmenden Fraktionsmehrheit gestimmt hätten. Vielmehr hätten wohl auch sie sich ihrer Stimme enthalten. Deshalb wird ein Threshold gesetzt, der bestimmt, wie gross der Anteil der Enthaltungen maximal sein darf, bevor eine Abstimmung nicht mehr berücksichtigt wird.
# Der Threshold wird bei 25% angelegt.
ts2 <- 25
cases %<>%
mutate(EnthAnteil = Enthaltung / (Ja + Nein + Enthaltung)) %>%
filter(EnthAnteil < ( ts2 / 100) )
# Das File "cases.xls" enthält alle Fälle, in denen Fraktionen wegen Schwänzern Abstimmungen verloren, die sie eigentlich hätten gewinnen können (inkl. Link zum offiziellem Abstimmungsprotokoll).
cases %<>%
mutate(legislatur = case_when(VoteId < 12604 ~ 49,
VoteId >= 12604 ~ 50)) %>%
mutate(URL = paste(
"https://www.parlament.ch/poly/Abstimmung/",
legislatur,
"/out/vote_",
legislatur,
"_",
VoteId,
".pdf",
sep = ""))
WriteXLS(
cases,
ExcelFileName = "output/cases.xls"
)
# Das File "cases_unique.xls" enthält alle Abstimmungen, die anders ausgegangen wären, wenn eine der unterlegenen Fraktionen vollständig anwesend gewesen wäre.
cases_unique <-
cases %>%
distinct(VoteId, .keep_all = T)
cases_unique %<>%
select(
Date:VoteSubmissionText,
VoteId,
RatJa:Fehlende)
WriteXLS(
cases_unique,
ExcelFileName = "output/cases_unique.xls"
) # alle betroffenen Abstimmungen
Ein paar einfache Plots als Überblick über die Daten.
plot <- ggplot(cases, aes(Fraktion)) +
geom_histogram(stat = "count") +
labs(
x = "Fraktion",
y = "Anzahl",
title = "Verlorene Abstimmungen wegen abwesenden Fraktionsmitgliedern"
) +
theme_minimal()
## Warning: Ignoring unknown parameters: binwidth, bins, pad
plot
dplot <- filter(cases, Fraktion == "V")
plot <- ggplot(dplot, aes(Dept)) +
geom_histogram(stat = "count") +
labs(
x = "Dept.",
y = "Anzahl",
title = "SVP: Verschenkte Abstimmungen nach Departement"
) +
theme_minimal()
## Warning: Ignoring unknown parameters: binwidth, bins, pad
plot
rm(dplot)
dplot <- filter(cases, Fraktion == "S")
plot <- ggplot(dplot, aes(Dept)) +
geom_histogram(stat = "count") +
labs(
x = "Dept.",
y = "Anzahl",
title = "SP: Verschenkte Abstimmungen nach Departement"
) +
theme_minimal()
## Warning: Ignoring unknown parameters: binwidth, bins, pad
plot
rm(dplot)
dplot <-
cases %>%
distinct(VoteId, .keep_all = T)
dplot %<>%
mutate(differenz = (RatJa - RatNein),
form = case_when(grepl("Motion",
VoteMeaningYes,
ignore.case = T) ~ "Motion",
grepl("Postulat",
VoteMeaningYes,
ignore.case = T) ~ "Postulat",
grepl("Gesamtabstimmung",
DivisionText,
ignore.case = T) ~ "Gesamtabstimmung"))
plot <- ggplot(dplot, aes(form)) +
geom_histogram(stat = "count") +
labs(
x = "Art der Vorlage",
y = "Anzahl",
title = "Verschenkte Abstimmungen nach Art der Vorlage"
) +
theme_minimal()
## Warning: Ignoring unknown parameters: binwidth, bins, pad
plot
rm(dplot)
dplot <-
cases %>%
distinct(VoteId, .keep_all = T)
dplot %<>%
mutate(Date = str_sub(Date, 0, 4))
plot <- ggplot(dplot, aes(Date)) +
geom_histogram(stat = "count") +
labs(
x = "Jahr",
y = "Anzahl",
title = "Verschenkte Abstimmungen nach Jahr"
) +
theme_minimal()
## Warning: Ignoring unknown parameters: binwidth, bins, pad
plot
Der Code in diesem RMarkdown wird mit lintr automatisch auf den Wickham’schen tidyverse style guide überprüft.
lintr::lint(
"main.Rmd", linters =
lintr::with_defaults(
commented_code_linter = NULL,
trailing_whitespace_linter = NULL
)
)
## main.Rmd:221:1: style: lines should not be more than 80 characters.
## # Schritt 1: Abstimmung und Abstimmungsverhalten der Parlamentarier einlesen und zu einem Datensatz zusammenfassen
## ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## main.Rmd:236:31: style: Variable and function names should be all lowercase.
## mutate(VoteDate = str_sub(VoteDate, 0, 10))
## ^~~~~~~~
## main.Rmd:242:14: style: Variable and function names should be all lowercase.
## VoteDate:VoteSubmissionText,
## ^~~~~~~~
## main.Rmd:242:23: style: Variable and function names should be all lowercase.
## VoteDate:VoteSubmissionText,
## ^~~~~~~~~~~~~~~~~~
## main.Rmd:245:1: style: lines should not be more than 80 characters.
## # Transformieren des Datensatzes, alle Parlamentarier und Abstimmungen einzeln auflisten
## ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## main.Rmd:248:7: style: Variable and function names should be all lowercase.
## BioId,
## ^~~~~
## main.Rmd:249:7: style: Variable and function names should be all lowercase.
## VoteDecision,
## ^~~~~~~~~~~~
## main.Rmd:280:35: style: Variable and function names should be all lowercase.
## mutate(BioId = as.character(BioId),
## ^~~~~
## main.Rmd:282:44: style: Variable and function names should be all lowercase.
## CouncillorName = as.character(CouncillorName),
## ^~~~~~~~~~~~~~
## main.Rmd:293:1: style: lines should not be more than 80 characters.
## # Schritt 3: Das Abstimmungsverhalten der Fraktionen zu jeder einzelnen Abstimmung berechnen Datensatz zu Abstimmungen und Parlamentarieren mergen und anpassen
## ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## main.Rmd:301:1: style: lines should not be more than 80 characters.
## # Datensatz spezifieren, rekodieren und Abstimmungen nach Fraktionen gruppieren
## ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## main.Rmd:304:7: style: Variable and function names should be all lowercase.
## BioId,
## ^~~~~
## main.Rmd:306:14: style: Variable and function names should be all lowercase.
## Name = CouncillorName,
## ^~~~~~~~~~~~~~
## main.Rmd:310:14: style: Variable and function names should be all lowercase.
## Date = VoteDate,
## ^~~~~~~~
## main.Rmd:313:7: style: Variable and function names should be all lowercase.
## AffairId,
## ^~~~~~~~
## main.Rmd:314:7: style: Variable and function names should be all lowercase.
## AffairTitle,
## ^~~~~~~~~~~
## main.Rmd:315:16: style: Variable and function names should be all lowercase.
## VoteId = VoteRegistrationNumber,
## ^~~~~~~~~~~~~~~~~~~~~~
## main.Rmd:316:7: style: Variable and function names should be all lowercase.
## VoteMeaningYes,
## ^~~~~~~~~~~~~~
## main.Rmd:317:7: style: Variable and function names should be all lowercase.
## VoteMeaningNo,
## ^~~~~~~~~~~~~
## main.Rmd:318:7: style: Variable and function names should be all lowercase.
## DivisionText,
## ^~~~~~~~~~~~
## main.Rmd:319:24: style: Variable and function names should be all lowercase.
## SubmissionText = VoteSubmissionText,
## ^~~~~~~~~~~~~~~~~~
## main.Rmd:320:7: style: Variable and function names should be all lowercase.
## VoteDecision,
## ^~~~~~~~~~~~
## main.Rmd:324:19: style: Words within variable and function names should be separated by '_' rather than '.'.
## RatEntsch = `Entschuldigung gem. Art. 57 Abs. 4`,
## ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## main.Rmd:324:19: style: Variable and function names should not be longer than 30 characters.
## RatEntsch = `Entschuldigung gem. Art. 57 Abs. 4`,
## ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## main.Rmd:327:27: style: Variable and function names should be all lowercase.
## mutate(Ja = case_when(VoteDecision ==
## ^~~~~~~~~~~~
## main.Rmd:329:29: style: Variable and function names should be all lowercase.
## Nein = case_when(VoteDecision ==
## ^~~~~~~~~~~~
## main.Rmd:331:28: style: Variable and function names should be all lowercase.
## Ent = case_when(VoteDecision ==
## ^~~~~~~~~~~~
## main.Rmd:333:28: style: Variable and function names should be all lowercase.
## Abw = case_when(VoteDecision ==
## ^~~~~~~~~~~~
## main.Rmd:335:31: style: Variable and function names should be all lowercase.
## AbwEnt = case_when(VoteDecision ==
## ^~~~~~~~~~~~
## main.Rmd:337:29: style: Variable and function names should be all lowercase.
## Pres = case_when(VoteDecision ==
## ^~~~~~~~~~~~
## main.Rmd:339:14: style: Variable and function names should be all lowercase.
## group_by(VoteId, Fraktion) %>%
## ^~~~~~
## main.Rmd:345:26: style: Variable and function names should be all lowercase.
## Entschuldigt = sum(AbwEnt),
## ^~~~~~
## main.Rmd:347:20: style: Variable and function names should be all lowercase.
## RatJa = mean(RatJa),
## ^~~~~
## main.Rmd:348:22: style: Variable and function names should be all lowercase.
## RatNein = mean(RatNein),
## ^~~~~~~
## main.Rmd:349:28: style: Variable and function names should be all lowercase.
## RatEnthaltung = mean(RatEnth),
## ^~~~~~~
## main.Rmd:350:30: style: Variable and function names should be all lowercase.
## RatEntschuldigt = mean(RatEntsch),
## ^~~~~~~~~
## main.Rmd:351:26: style: Variable and function names should be all lowercase.
## RatAbwesend = mean(RatNicht)
## ^~~~~~~~
## main.Rmd:355:1: style: lines should not be more than 80 characters.
## # Schritt 4: Potenzial berechnen, um die für die Auswertung relevanten Fälle zu finden
## ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## main.Rmd:357:1: style: lines should not be more than 80 characters.
## # Das Potenzial A ist die Differenz zwischen der Anzahl der fehlenden Personen einer Fraktion und der Stimmendifferenz im Rat. Das Potenzial gibt darüber Auskunft, ob eine Fraktion eine Abstimmung hätte gewinnen können, wenn alle Mitglieder anwesend gewesen wären. In der Regel trifft dies zu für Fraktionen und Abstimmungen mit einem Potenzial A > 0. Allerdings gibt es 2 Ausnahmen, bei denen auch Potenzial A = 0 ausreicht. Aus diesem Grund werden vorerst auch diese Fälle mitberücksichtigt. (Wird später für die Berechnung von Potenzial B und Potenzial C relevant.)
## ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## main.Rmd:361:27: style: Variable and function names should be all lowercase.
## mutate(RatDifferenz = RatJa - RatNein,
## ^~~~~
## main.Rmd:361:35: style: Variable and function names should be all lowercase.
## mutate(RatDifferenz = RatJa - RatNein,
## ^~~~~~~
## main.Rmd:363:40: style: Variable and function names should be all lowercase.
## PotentialA = Fehlende - abs(RatDifferenz)) %>%
## ^~~~~~~~~~~~
## main.Rmd:365:16: style: Variable and function names should be all lowercase.
## ( RatJa / ( RatJa + RatNein ) - 0.5 ) ) %>%
## ^~~~~
## main.Rmd:365:26: style: Variable and function names should be all lowercase.
## ( RatJa / ( RatJa + RatNein ) - 0.5 ) ) %>%
## ^~~~~
## main.Rmd:365:34: style: Variable and function names should be all lowercase.
## ( RatJa / ( RatJa + RatNein ) - 0.5 ) ) %>%
## ^~~~~~~
## main.Rmd:368:12: style: Variable and function names should be all lowercase.
## filter(PotentialA > -1 &
## ^~~~~~~~~~
## main.Rmd:371:1: style: lines should not be more than 80 characters.
## # Fälle, in denen das Potenzial A mindestens 0 beträg und die Abstimmung aus Sicht der Fraktionsmehr verloren wurde, an den Datensatz "cases" anhängen
## ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
## main.Rmd:387:12: style: Variable and function names should be all lowercase.
## distinct(BioId, .keep_all = T)
## ^~~~~
## main.Rmd:412:5: style: Variable and function names should be all lowercase.
## AffairId,
## ^~~~~~~~
## main.Rmd:413:5: style: Variable and function names should be all lowercase.
## VoteRegistrationNumber,
## ^~~~~~~~~~~~~~~~~~~~~~
## main.Rmd:427:5: style: Variable and function names should be all lowercase.
## VoteRegistrationNumber,
## ^~~~~~~~~~~~~~~~~~~~~~
## main.Rmd:436:33: style: Variable and function names should be all lowercase.
## mutate(PotentialB = case_when(PresDec == "True" &
## ^~~~~~~
## main.Rmd:437:32: style: Variable and function names should be all lowercase.
## PotentialA == 0 ~ 1,
## ^~~~~~~~~~
## main.Rmd:461:12: style: Variable and function names should be all lowercase.
## PotentialA +
## ^~~~~~~~~~
## main.Rmd:462:12: style: Variable and function names should be all lowercase.
## PotentialB +
## ^~~~~~~~~~
## main.Rmd:463:12: style: Variable and function names should be all lowercase.
## PotentialC) %>%
## ^~~~~~~~~~
## main.Rmd:464:10: style: Variable and function names should be all lowercase.
## filter(PotentialTotal > 0)
## ^~~~~~~~~~~~~~
## main.Rmd:473:12: style: Variable and function names should be all lowercase.
## Date = VoteDate,
## ^~~~~~~~
## main.Rmd:476:5: style: Variable and function names should be all lowercase.
## `AffairId`,
## ^~~~~~~~~~
## main.Rmd:477:13: style: Variable and function names should be all lowercase.
## Title = AffairTitle,
## ^~~~~~~~~~~
## main.Rmd:478:5: style: Variable and function names should be all lowercase.
## VoteMeaningYes,
## ^~~~~~~~~~~~~~
## main.Rmd:479:5: style: Variable and function names should be all lowercase.
## VoteMeaningNo,
## ^~~~~~~~~~~~~
## main.Rmd:480:5: style: Variable and function names should be all lowercase.
## DivisionText,
## ^~~~~~~~~~~~
## main.Rmd:481:5: style: Variable and function names should be all lowercase.
## VoteSubmissionText,
## ^~~~~~~~~~~~~~~~~~
## main.Rmd:482:14: style: Variable and function names should be all lowercase.
## VoteId = VoteRegistrationNumber
## ^~~~~~~~~~~~~~~~~~~~~~
## main.Rmd:494:43: style: Variable and function names should be all lowercase.
## VoteMeaningYes = str_replace_all(VoteMeaningYes, "[\r\n]", " "),
## ^~~~~~~~~~~~~~
## main.Rmd:495:42: style: Variable and function names should be all lowercase.
## VoteMeaningNo = str_replace_all(VoteMeaningNo, "[\r\n]", " "),
## ^~~~~~~~~~~~~
## main.Rmd:496:41: style: Variable and function names should be all lowercase.
## DivisionText = str_replace_all(DivisionText, "[\r\n]", " "),
## ^~~~~~~~~~~~
## main.Rmd:497:47: style: Variable and function names should be all lowercase.
## VoteSubmissionText = str_replace_all(VoteSubmissionText, "[\r\n]",
## ^~~~~~~~~~~~~~~~~~
## main.Rmd:510:10: style: Variable and function names should be all lowercase.
## filter(JaAnteil > (ts1 / 100) |
## ^~~~~~~~
## main.Rmd:511:12: style: Variable and function names should be all lowercase.
## JaAnteil < (100 - ts1) / 100)
## ^~~~~~~~
## main.Rmd:522:10: style: Variable and function names should be all lowercase.
## filter(EnthAnteil < ( ts2 / 100) )
## ^~~~~~~~~~
## main.Rmd:531:33: style: Variable and function names should be all lowercase.
## mutate(legislatur = case_when(VoteId < 12604 ~ 49,
## ^~~~~~
## main.Rmd:532:33: style: Variable and function names should be all lowercase.
## VoteId >= 12604 ~ 50)) %>%
## ^~~~~~
## main.Rmd:536:6: warning: Do not use absolute paths.
## "/out/vote_",
## ^~~~
## main.Rmd:539:5: style: Variable and function names should be all lowercase.
## VoteId,
## ^~~~~~
## main.Rmd:551:12: style: Variable and function names should be all lowercase.
## distinct(VoteId, .keep_all = T)
## ^~~~~~
## main.Rmd:555:10: style: Variable and function names should be all lowercase.
## Date:VoteSubmissionText,
## ^~~~~~~~~~~~~~~~~~
## main.Rmd:556:5: style: Variable and function names should be all lowercase.
## VoteId,
## ^~~~~~
## main.Rmd:557:5: style: Variable and function names should be all lowercase.
## RatJa:Fehlende)
## ^~~~~
## main.Rmd:621:12: style: Variable and function names should be all lowercase.
## distinct(VoteId, .keep_all = T)
## ^~~~~~
## main.Rmd:624:23: style: Variable and function names should be all lowercase.
## mutate(differenz = (RatJa - RatNein),
## ^~~~~
## main.Rmd:624:31: style: Variable and function names should be all lowercase.
## mutate(differenz = (RatJa - RatNein),
## ^~~~~~~
## main.Rmd:626:33: style: Variable and function names should be all lowercase.
## VoteMeaningYes,
## ^~~~~~~~~~~~~~
## main.Rmd:629:33: style: Variable and function names should be all lowercase.
## VoteMeaningYes,
## ^~~~~~~~~~~~~~
## main.Rmd:632:33: style: Variable and function names should be all lowercase.
## DivisionText,
## ^~~~~~~~~~~~
## main.Rmd:652:12: style: Variable and function names should be all lowercase.
## distinct(VoteId, .keep_all = T)
## ^~~~~~
# lintr::lint("scripts/my_script.R", linters =
# lintr::with_defaults(
# commented_code_linter = NULL,
# trailing_whitespace_linter = NULL
# )
# )