4 Graphische Analyse mit ggplot2
Wir arbeiten in diesem Kapitel mit den in Kapitel 3 transformierten Daten weiter. Dazu müssten Sie entweder das Script aus der Vorwoche nochmals durchführen, den unten stehenden code Block, welcher alle Veränderungen an den Daten in kompakter Form enthält ausführen, oder sie laden die Daten – vorausgesetzt Sie haben sie gespeichert. Vor dem Laden der Daten müssen wir erneut das tidyverse laden.
library(tidyverse)
load("stammdaten_17_19.RData")
<- stammdaten_17_19 %>%
stammdaten_19 filter(wp == 19) %>%
rename(titel = Titel) %>%
mutate(titel_dummy = if_else(!is.na(titel), TRUE, FALSE),
fraktion = factor(fraktion),
fraktion = fct_infreq(fraktion),
geschlecht = factor(geschlecht)) %>%
select(-c(geb, titel))
4.1 ggplot2 syntax
Die graphische Datenanalyse mit dem core tidyverse package ggplot2 folgt einer intuitiven Logik. Jede Grafik beginnt mit dem Initieren eines leeren plots. Diese leere “Leinwand” füllen wir dann in weiteren Schritten mit den darzustellenden graphischen Elementen.
Zum Initieren des plots nutzen wir die Funktion ggplot()
– auch wenn der Name
des packages ggplot2 lautet, trägt der Funktionsname keine “2”. Der Funktion
geben wir das Datenobjekt welches geplottet werden soll als Argument.
ggplot(data = stammdaten_19)
Die neu erstellte Grafik öffnet sich im “Plots” Tab von RStudio und erstrahlt in blendender Leere, da wir noch keine graphischen Elemente hinzugefügt haben.
4.1.1 geoms & aesthetics
Diese graphischen Element werden geoms genannt. Wir fügen Sie einem plot hinzu
indem wir nach ggplot()
ein +
schreiben und den Befehl für das geom in der
nächsten Zeile eingeben. Weitere geoms können wir auf die selbe Art und Weise
hinzufügen. Die grundsätzliche Syntax – dies ist kein ausführbarer Code –
sieht damit wie folgt aus:
ggplot(data = ...) +
geom_1() +
geom_2() +
...
Die geom Funktionen beginnen immer mit geom_
und enden mit einem Wort das die
Art des graphischen Objekts beschreibt. Beispielsweise geom_point()
für
scatterplots, geom_line()
für lineplots oder geom_bar()
für barplots.
Die aesthetics eines geoms dienen zur Zuordnung der x und y Variablen die in das Koordinatensytem geplottet werden sollen. Darüber hinaus können aesthetics auch genutzt werden um die graphische Darstellung der geplottet Elemente anhand der Werte einer weiteren Variable zu manipulieren – beispielsweise die Farbe oder Größe geplotteter Punkte oder die Dicke von Linien. Dies klingt noch sehr abstrakt, wird aber in späteren Beispielen deutlich werden.
Betrachten wir zunächst, wie die Zuordnung von x und y Variablen syntaktisch
funktioniert. Diese müssen festgelegt werden. Alle weiteren aesthetics sind
optional. Zur Definition der aesthetics nutzen wir die Funktion aes()
als ein
Argument der jeweiligen geom Funktion. Innerhalb von aes()
weisen wir x
und
y
die Variablen die auf der x-Achse beziehungsweise der y-Achse abgetragen
werden sollen zu. Die Syntax sieht wie folgt aus:
ggplot(data = ...) +
geom_1(aes(x = x_variable, y = y_variable)) +
geom_2(aes(x = x_variable, y = y_variable)) +
...
Nutzen wir die selben x und y Variablen für alle geoms, können wir die
Zuordnung auch direkt in der Funktion ggplot()
vornehmen.
ggplot(data = ..., aes(x = x_variable, y = y_variable)) +
geom_1() +
geom_2() +
...
Dies ist die grundsätzliche Syntax von ggplot2. Im Folgenden nutzen wir das package zur graphischen Analyse unserer Beispieldaten. Dabei betrachten wir nur einen Teil der verfügbaren geoms und der Möglichkeiten die Darstellung über die aesthetics und weitere Optionen zu manipluieren. Als Übersicht über alle verfügbaren geoms empfehle ich dringend das cheatsheet für ggplot2: https://raw.githubusercontent.com/rstudio/cheatsheets/master/data-visualization.pdf Eine ausführlichere Einführung gibt das Kapitel “Data visualisation” in “R for Data Science”: https://r4ds.had.co.nz/data-visualisation.html
4.2 Graphische Analyse der Stammdaten
Variablen sind kontinuierlich, wenn sie jeden Wert – möglicherweise im Minimum und Maximum begrenzt – annehmen können. Sie sind auch immer numerisch. Ein in den Sozialwissenschaften häufig anzutreffendes Beispiel für eine kontinuierliche Variable wäre das Einkommen beziehungsweise monetäre Werte im Allgemeinen, vorausgesetzt sie werden als exakter Geldwert gemessen. In unserem Beispielsdatensatz ist das Alter der MdBs eine kontinuierliche Variable.
Variablen sind kategorial, wenn Sie als Werte nur eine begrenzte Anzahl vordefinierter Kategorien annehmen können. Wird das Einkommen statt als exakter Wert als Mitgliedschaft in breiten Einkommensgruppen gemessen, ist dies eine kategoriale Variable. In den Beispieldaten sind die Fraktionsmitgliedschaft, das Geschlecht sowie die Dummyvariable zum akademischen Titel kategoriale Variablen.
Geoms können danach unterschieden werden, für welche Typen von x und y Variablen sie anwendbar sind. Dieser Logik folgt auch das oben verlinkte cheatsheet.
4.2.1 kontinuierliches x & y
Das Alter ist die einzige kontinuierliche Variable in unserem Beispielsdatensatz. Damit eignet sich der Beispieldatensatz nicht zum Plotten zweier kontinuierlicher Variablen. Stattdessen, generieren wir im folgenden Zufallssaten für Mietpreise und Quadratmeter fiktiver Wohnungen in einer Stadt.
Bevor wir nun Zufallswerte generieren, müssen wir uns über eines bewusst sein:
Zufallswerte sind Zufallswerte. Bei jeder wiederholten Ziehung der
Zufallswerte, werden wir andere Werte erhalten. Meist sind wir aber daran
interessiert, auch zufällig gezogene Werte reproduzieren zu können. Also bei
jeder wiederholten Ziehung, beispielsweise wenn wir am nächsten Tag an einem
Projekt weiterarbeiten, dieselben Zufallswerte zu erhalten. Dies können wir
ermöglichen, in dem wir vor dem Ziehen der Zahlen einen sogenannten Seed
setzen. Dieser Seed legt den Startpunkt des Random Number Generators (RNG)
fest. Dieser Startpunkt bestimmt, welche Zahlen in welcher Reihenfolge zufällig
generiert werden und sicher die Reproduzierbarkeit unserer Arbeit. Die Funktion
set.seed()
, mit einer beliebigen Zahl zwischen den Klammern – hier das Datum
der Seminarsitzung – setzt den Seed.
Der folgende Codeblock generiert unsere Zufallsdaten als eine Tibble. Die Spalte
“size” enthält 1000 Zufallswerte aus einer Normalverteilung mit einem Mittelwert
von 70 und einer Standardabweichung von 15. Dies sind die Quadratmeterzahlen
unser fiktiver Wohnungen. Für die Spalte “premium” werden 1000 Werte aus der
Binomialverteilung gezogen. Mit einer Wahrscheinlichkeit von 20% ist der Wert
TRUE
, mit 80% FALSE
. Die Variable soll einige Wohnungen zufällig als
besonders teuer kennzeichnen – möglicherweise aufgrund ihrer exklusiven Lage.
Auf Basis der Werte von “size” und “premium”, berechnet sich der Mitpreis in
“price” wie folgt: Ausgehend von einer fiktiven Quadratmetermiete von 10€, wird
zunächst etwas “Rauschen” hinzugefügt (Addition/Subtraktion von Werten aus einer
Normalverteilung mit einem Mittelwert von 0 und einer Standardabweichung von 3).
Handelt es sich um eine “Premiumwohnung”, werden auf diesen Preis nochmals 10€
aufgeschlagen. Nun wird der Quadratmeterpreis mit der Größe der Wohnung
multipliziert um den finalen Mietpreis zu berechnen.
set.seed(170522)
<- tibble(
rent size = rnorm(1000, mean = 70, sd = 15),
premium = as.logical(rbinom(n = 1000, size = 1, prob = 0.2)),
price = size * (10 + rnorm(1000, mean = 0, sd = 3) + (10 * premium))
)
%>%
rent head(n = 5)
## # A tibble: 5 × 3
## size premium price
## <dbl> <lgl> <dbl>
## 1 77.2 TRUE 1473.
## 2 66.1 FALSE 574.
## 3 56.4 FALSE 801.
## 4 90.7 TRUE 2290.
## 5 59.8 TRUE 1197.
Nun können wir unsere Zufallsdaten plotten. Typischerweise wird die erklärende
unabhängige Variable, hier size
, auf der x-Achse und die zu erklärende
abhängige Variable, price
, auf der y-Achse abgetragen. Mit geom_point()
können wir
einen scatterplot erstellen um die Kombinationen der Werte für x- und y-Variablen
als Punkte in einem Koordinatensystem darzustellen.
ggplot(data = rent, aes(x = size, y = price)) +
geom_point()
Da wir die Daten selbst generiert haben, wissen wir bereits, dass x- und
y-Variable positiv miteinander korreliert sind. Auch ohne dieses Wissen, würde
uns ein erster Blick auf die Punktewolke vermutlich einen positiven linearen
Zusammenhang vermuten lassen. Um diese Vermutung zu überprüfen, könnten wir eine
lineare Regressionsgerade in den Plot legen. Diese visualisiert den Zusammenhang
zwischen zwei Variablen und wird so über die Daten gelegt, dass Sie deren
Zusammenhang bestmöglichst beschreibt, also die Abweichung von den
tatsächlichen Daten minimiert. Eine Regressionsgerade erhalten wir, indem wir
dem Plot das geom_smooth()
hinzufügen und dabei das Argument method = "lm"
setzen. “lm” steht dabei für “linear model”, also eine lineare Regression. Das
weitere Argument se = FALSE
sorgt dafür, dass kein Konfidenzinterval – ein
Maß für die Unsicherheit des geschätzten Zusammenhangs – um die Gerade
angezeigt wird.
ggplot(data = rent, aes(x = size, y = price)) +
geom_point() +
geom_smooth(method = 'lm', se = FALSE)
## `geom_smooth()` using formula 'y ~ x'
Der Winkel in dem die Regressionsgerade verläuft – die slope – zeigt uns den Zusammenhang zwischen beiden Variablen an, welcher hier klar positiv ist.
Wir haben die Zufallsdaten so konstruiert, dass es eine Klasse von Wohnungen
gibt, welche besonders teuer sind. Die Korrelation zwischen Größe und Preis
unterscheidet sich also zwischen diesen Gruppen. Dies können wir in unserem Plot
visualisieren in dem wir die Variable premium
nutzen um die Daten zu gruppieren
und sowohl Punkte als auch Regressionsgeraden getrennt nach dem Wert der dritten
Variable abzutragen. Zur Gruppierung legen wir eine weitere aesthetic fest.
Dazu könnten wir das Argument group = premium
setzen. Um Punkte und Geraden
auch farblich abzugrenzen, bietet sich aber colour = premium
an.
ggplot(data = rent, aes(x = size, y = price, colour = premium)) +
geom_point() +
geom_smooth(method = 'lm', se = FALSE)
## `geom_smooth()` using formula 'y ~ x'
Wir sehen klar, dass sich die Slope beider Geraden unterscheidet. Die Korrelation zwischen Größe und Preis ist für Premiumwohnungen stärker.
Sidenote: In diesem Fall haben wir die Daten selbst konstruiert und waren uns über die Zusammenhänge der Variablen im Vorfeld bewusst. Die Zusammenhänge in echten Daten kennen wir nicht, wir können aber basiert auf theoretischen Überlegungen Annahmen zu Zusammenhängen treffen und diese, unter anderem, mit vergleichbaren graphischen Analysen überprüfen.
4.2.2 kategoriales x, kontinuierliches y
In Kapitel 3 haben wir mit summarise()
und group_by()
die Anzahl
von Beobachtungen pro Fraktion berechnet. Diese könnten wir auch in einer Graphik
darstellen. Die Variable zur Fraktionsmitgliedschaft ist dabei eine kategoriale
Variable, die Anzahl der Abgeordneten ist kontinuierlich, liegt aber nicht als
Variable vor. Dies benötigen wir aber auch nicht, da geom_bar()
– für
barplots – die Anzahl von Beobachtungen pro Kategorie der x Variable
automatisch berechnet. So müssen wir in den aesthetics auch nur die x Variable
zuordnen.
%>%
stammdaten_19 ggplot(aes(x = fraktion)) +
geom_bar()
So schnell und einfach kommen wir zu einem barplot der Fraktionsmitgliedschaft. Die
Darstellung ist dabei aber nicht sonderlich hübsch. Ein erster Schritt wäre es,
die Achsen sowie die Graphik selbst sinnvoll zu beschriften. die Funktion
labs()
erlaubt die Benennung der zentralen Graphikbestandteile,
beispielsweise:
%>%
stammdaten_19 ggplot(aes(x = fraktion)) +
geom_bar() +
labs(x = "Fraktion",
y = "Mandate",
title = "Anzahl Mandate im 19. Bundestag nach Fraktionszugehörigkeit",
caption = "Daten: https://www.bundestag.de/services/opendata")
Soweit, so gut. Aber die Balken sind doch noch sehr eintönig grau. In der
aes()
Funktion innerhalb von geom_bar()
oder auch ggplot()
, können wir
über das fill =
Argument festlegen, dass die Balken nach dem Wert einer
Variable eingefärbt werden sollen. Setzen wir dieses gleich der Variable
“fraktion”, bekommt jeder Balken eine eigene Farbe zugewiesen. Die automatisch
erstellte Farblegende, verstecken wir mit einem weiteren Argument.
%>%
stammdaten_19 ggplot(aes(x = fraktion)) +
geom_bar(aes(fill = fraktion), show.legend = FALSE) +
labs(x = "Fraktion",
y = "Mandate",
title = "Anzahl Mandate im 19. Bundestag nach Fraktionszugehörigkeit",
caption = "Daten: https://www.bundestag.de/services/opendata")
Noch schöner wäre es, wenn die Balkenfarben mit den tatsächlichen Parteifarben
übereinstimmen würden. Dazu können wir die Farben der Balken per Hand festlegen
statt sie automatisch zuweisen zu lassen. Hier erstellen wir einen Vektor mit
Farbnamen den wir dann für das fill =
Argument nutzen. Beachten Sie dabei,
dass fill =
diesmal nicht innerhalb von aes()
steht. Dies liegt daran, dass
wir die Farben nicht anhand einer Variable festlegen sondern konstant zuweisen,
was außerhalb von aes()
erfolgt.
<- c("black", "red", "deepskyblue", "yellow2", "limegreen", "violetred", "grey")
parteifarben
%>%
stammdaten_19 ggplot(aes(x = fraktion)) +
geom_bar(fill = parteifarben) +
labs(x = "Fraktion",
y = "Mandate",
title = "Anzahl Mandate im 19. Bundestag nach Fraktionszugehörigkeit",
caption = "Daten: https://www.bundestag.de/services/opendata")
Eine Übersicht über alle verfügbaren Farben, finden Sie unter: http://www.stat.columbia.edu/~tzheng/files/Rcolor.pdf
Mich persönlich stört an dieser Stelle noch der graue Hintergrund des plots.
Dieser ist Teil des standard themes von ggplot2, theme_gray()
. Wir
können aber auch andere themes auswählen. Eine Übersicht finden sie hier:
https://ggplot2.tidyverse.org/reference/ggtheme.html
%>%
stammdaten_19 ggplot(aes(x = fraktion)) +
geom_bar(fill = parteifarben) +
labs(x = "Fraktion",
y = "Mandate",
title = "Anzahl Mandate im 19. Bundestag nach Fraktionszugehörigkeit",
caption = "Daten: https://www.bundestag.de/services/opendata") +
theme_minimal()
Nutzen wir für die fill
aesthetic eine zweite Variable, beispielsweise die
Informationen zu akademischen Titeln, erhalten wir einen gestapelten barplot.
Hier macht es wiederum Sinn, die automatisch erstellte Farblegende nicht
auszublenden.
%>%
stammdaten_19 ggplot(aes(x = fraktion)) +
geom_bar(aes(fill = titel_dummy)) +
labs(x = "Fraktion",
y = "Mandate",
title = "Anzahl Mandate mit/ohne Titel im 19. Bundestag nach Fraktionszugehörigkeit",
caption = "Daten: https://www.bundestag.de/services/opendata") +
theme_minimal()
Möchten wir die Balken nicht stapeln sondern nebeneinander darstellen, können
wir dies über das Argument position = "dodge"
festlegen. Um die Darstellung
weiter aufzuhübschen können wir außerdem den Titel der Farblegende in labs()
anpassen.
%>%
stammdaten_19 ggplot(aes(x = fraktion)) +
geom_bar(aes(fill = titel_dummy), position = "dodge") +
labs(x = "Fraktion",
y = "Mandate",
title = "Anzahl Mandate mit/ohne Titel im 19. Bundestag nach Fraktionszugehörigkeit",
caption = "Daten: https://www.bundestag.de/services/opendata",
fill = "Akadem. Titel") +
theme_minimal()
4.2.3 kontinuierliches x
In Kapitel 3 haben wir deskriptive Statistiken zur Altersverteilung
berechnet. Auch diese können wir graphisch darstellen. Dazu bietet sich unter
anderem geom_histogram()
an. Ein Histogramm unterteilt eine kontinuierliche
Variable in eine festlegbare Anzahl von Abschnitten – bins – und stellt
die Anzahl von Beobachtungen die in jedes bin fallen als Balken dar. Als
Standard unterteilt ggplot2 eine Variable in 30 bins, dies können wir aber
über das bins =
Argument beeinflussen.
%>%
stammdaten_19 ggplot(aes(x = alter)) +
geom_histogram() +
labs(x = "Alter",
y = "Anzahl",
title = "Altersverteilung im 19. Bundestag",
caption = "Daten: https://www.bundestag.de/services/opendata") +
theme_minimal()
## `stat_bin()` using `bins = 30`. Pick better value with `binwidth`.
Um die Grafik besser interpretierbar zu machen, könnten wir eine vertikale Linie
hinzufügen die den Mittelwert der x Variable markiert. Dazu nutzen wir
geom_vline()
und legen für xintercept =
den x Wert fest, an dem die Linie
eingezeichnet werden soll. Außerdem scheint es angebracht, die Anzahl der bins
zu reduzieren. Mit 30 bins, deckt jeder Balken knapp 2 Jahre ab. So werden
zufällige Fluktuationen in der Altersverteilung überbetont.
%>%
stammdaten_19 ggplot(aes(x = alter)) +
geom_histogram(bins = 15) +
geom_vline(aes(xintercept = mean(alter)), colour = "red") +
labs(x = "Alter",
y = "Anzahl",
title = "Altersverteilung im 19. Bundestag",
caption = "Daten: https://www.bundestag.de/services/opendata") +
theme_minimal()
Wir sehen, dass die Alterstruktur annäherend um den Mittelwert normalverteilt ist, die Verteilung aber leicht links-schief ist. Das bedeutet, dass die Verteilung auf der linken Seite etwas langsamer ansteigt als die auf der rechten abnimmt. Dies ist hier vor allem mit dem starken Abfall von Mandatsträgern beim Erreichen des Rentenalters erklärbar.
Durch das Verringern der bins auf 15 – jeder bin deckt so 3-4 Jahre ab –, erscheint die Altersverteilung deutlich näher an einer Normalverteilung, da Fluktuationen in der Altersverteilung so weniger betont werden. Wenn es unser Ziel ist, die generelle Altersverteilung im Bundestag zu bewerten, macht dieser Ansatz aus meiner Sicht auch durchaus Sinn. Wir sollten aber davon absehen, solange an der “bins-Schraube” zu drehen, bis wir ein Bild bekommen, dass uns gefällt. Vielmehr sollten wir vor dem plotten darüber nachdenken, was das Ziel der graphischen Darstellung ist und die bins entsprechend festlegen.
Möchten wir die Histogramme für alle Fraktionen vergleichen, können wir facets
nutzen. Dabei werden in einem plot mehrere einzelne plots neben- und
untereinander dargestellt. In der Funktion facet_wrap()
schreiben wir dazu
den Namen der Variable nachdem die Kacheln gebildet werden sollen und setzen
davor eine Tilde ~
.
%>%
stammdaten_19 ggplot(aes(x = alter)) +
geom_histogram(bins = 15) +
facet_wrap(~ fraktion) +
labs(x = "Alter",
y = "Anzahl",
title = "Altersverteilung im 19. Bundestag nach Fraktion",
caption = "Daten: https://www.bundestag.de/services/opendata") +
theme_minimal()
Um dies besser interpretierbar zu machen, könnten wir die Mittelwerte des Alters
für jede Fraktion einzeichnen. Diese müssen wir dazu zunächst pro Fraktion berechen.
Dazu nutzen wir wiederum die dplyr Funktionen und hängen ggplot()
am Ende der
Pipe an. In diesem Zuge, können wir auch die Fraktionslosen herausfiltern, da ihre
Anzahl für eine inhaltliche Interpretation deutlich zu klein ist.
%>%
stammdaten_19 filter(fraktion != "Flos") %>%
group_by(fraktion) %>%
mutate(arith_mittel = mean(alter)) %>%
ungroup() %>%
ggplot(aes(x = alter)) +
geom_histogram(bins = 15) +
geom_vline(aes(xintercept = arith_mittel), colour = "red") +
facet_wrap(~ fraktion) +
labs(x = "Alter",
y = "Anzahl",
title = "Altersverteilung im 19. Bundestag nach Fraktion",
caption = "Daten: https://www.bundestag.de/services/opendata") +
theme_minimal()
Die Befunde aus Kapitel 3 lassen sich zunächst bestätigen. Der relativ hohe Mittelwert der AfD wird durch viele besonders alte Mandatsträger:innen etwas nach oben verschoben. Keine andere Fraktion hat so “viele” – es geht hier eigentlich um eine geringe Anzahl von Personen – Abgeordnete über 70. FDP und Grüne als die im Mittelwert jüngsten Fraktionen unterscheiden sich in Ihrer Altersspannweite. Die FDP hat viele sehr junge aber auch sehr alte MdBs, während die Spannweite bei den Grünen deutlich enger ist. Wir erkennen nun auch, dass die Altersverteilung in der Union relativ nahe an der generellen Altersverteilung des 19. Bundestags liegt. Interessant sind die Verteilungen von SPD und von DIE LINKE. Anders als die alleinige Betrachtung des Mittelwerts suggeriert, liegt der Schwerpunkt der Altersverteilung in beiden Fraktionen bei den über 50-jährigen. Es gilt zu erinnern, dass die Histogramme für die kleineren Fraktionen auf wenig Fällen basieren. Die Fluktuationen zwischen den bins sollten deshalb nicht überinterpretiert werden.
Eine Alternative zu Histogrammen sind density plots. Diese können wir als geglätte Version eines Histogramms verstehen. Statt abgesteckter bins, für welche jeweils die Anzahl Beobachtungen die in dieses Interval der x Variable fallen exakt gezählt werden, wird bei einem density plot die “Dichte” der Daten über alle x Werte hinweg geschätzt. Diese Dichte wird auf der y-Achse abgetragen und summiert sich zu 1 auf. Dabei werden Fluktuationen in der Verteilung weniger detailliert abgebildet, aber wie bekommen dafür ein klareres Bild der generellen Verteilung einer kontinuierlichen Variable. Zwei weitere Vorteile sind, dass wir für density plots keine Entscheidungen zur Größe beziehungsweise Anzahl der bins treffen müssen und diese sich besser zum übereinanderlegen eignen als Histogramme.
So könnten wir beispielsweise die in Kapitel 3 bereits angesprochene
Altersverteilung für Träger akademischer Titel und Personen ohne einen Titel in
zwei übereinandergelegten density plots gleichzeitig betrachten und vergleichen.
Dazu plotten wir mit geom_density()
und nutzen entweder die fill
oder
colour
aesthetic. Bei fill
wird die Fläche unter der Kurve gefüllt, bei
colour
werden nur die Kurven farblich gezeichnet.
%>%
stammdaten_19 ggplot(aes(x = alter, colour = titel_dummy)) +
geom_density() +
labs(x = "Alter",
y = "Density",
title = "Altersverteilung im 19. Bundestag",
caption = "Daten: https://www.bundestag.de/services/opendata",
colour = "Akadem. Titel") +
theme_minimal()
Beide Verteilungen sind sich relativ ähnlich, bei den Titelträgern gibt es aber einen höheren Anteil besonders alter MdBs. Wir haben auch bereits gesehen, dass es möglicherweise Unterschiede zwischen den Fraktionen gibt. Diese können wir erneut mit einem facet vergleichen. Dazu filtern wir zunächst die Fraktionslosen heraus, da durch ihre geringe Anzahl nicht genug Daten zur Verfügung stehen um belastbare Ergebnisse zur Verteilung zu berechnen.
%>%
stammdaten_19 filter(fraktion != "Flos") %>%
ggplot(aes(x = alter, colour = titel_dummy)) +
geom_density() +
facet_wrap(~ fraktion) +
labs(x = "Alter",
y = "Density",
title = "Altersverteilung im 19. Bundestag",
caption = "Daten: https://www.bundestag.de/services/opendata",
colour = "Akadem. Titel") +
theme_minimal()
Die plots bestätigen die Ergebnisse aus Kapitel 3 weitestgehend. Union und SPD Mandatsträger mit und ohne Titel sind in der Altersverteilung sehr ähnlich. In AfD und LINKE sind Träger akademischer Titel klar älter. Bei den GRÜNEN klar jünger. Bei der FDP ist das Bild etwas differenzierter. Während Mandatsträger ohne Titel vornehmlich jüngeren bis mittleren Alters sind, ist die Alterverteilung bei Titelträgern relativ gleich über alle Alter hinweg.
4.3 Graphiken exportieren
Nachdem wir nun einige schöne Graphiken erstellt haben, folgt die Frage, wie
wie diese in unsere Papers und Hausarbeiten einbinden können. Arbeiten wir in
R Markdown, können wir direkt den ggplot2 Output nutzen, arbeiten wir aber
in externer Software – z. B. Word oder LaTeX – müssen wir die Graphiken
exportieren. Ein einfacher Weg ist die Funktion ggsave()
.
Um die letzte erstelle Graphik abzuspeichern, müssen wir ggsave()
nur einen
Dateinamen beziehungsweise Pfad als Argument mitgeben. Das Format der Graphik
legen wir dabei einfach über die Dateiendung fest. Ich empfehle generell eine
Vektorgraphik zu nutzen – beispielsweise “.eps” oder “.svg”. Der Vorteil ist,
dass diese stufenlos skalierbar sind. Wir können die Größe der Graphik beim
Import also in beide Richtungen anpassen, ohne dass die Darstellungsqualität
leidet. Pixelbasierte Formate wie “.jpeg” oder “.png” sind bereits komprimiert
und verlieren dadruch an Qualität. Möchten wir diese vergrößern, wird die
Darstellung zunehmend verschwommen. Das Verkleinern funktioniert eventuell
besser, kann aber auch graphische Artefakte erzeugen.
Hier speichern wir die letzte erstellte Graphik – die density plots nach Fraktionen – als “.eps”.
ggsave("age_density_by_party.eps")
## Saving 7 x 5 in image
Flexibler einsetzen lässt sich sich ggsave()
wenn wir plots zunächst einem
Objekt zuweisen. So ist es nicht mehr notwendig direkt nach der Erstellung einer
Graphik den Export vorzunehmen. Hier erstellen wir zwei Graphiken und weisen
diese zunächst Objekten zu, um sie später abzuspeichern. Durch die
Objektzuweisung bekommen wir dabei keinen Output. Ich würde empfehlen zunächst
die Graphik zu gestalten bis das Endergebnis erreicht ist und die Objektzuweisung
erst dann hinzuzufügen. Die erstellten Graphiken exportieren wir am Ende des
Blocks. Dabei handelt es sich um den barplot der Abgeordneten nach Fraktionen.
Einmal wie oben als Version mit den Parteifarben, einmal als greyscale Variante,
welche sich besser zum Druck eignet. Dazu fügen wir scale_fill_grey()
hinzu.
<- stammdaten_19 %>%
mdb_partei_colour ggplot(aes(x = fraktion)) +
geom_bar(fill = parteifarben) +
labs(x = "Fraktion",
y = "Mandate",
title = "Anzahl Mandate im 19. Bundestag nach Fraktionszugehörigkeit",
caption = "Daten: https://www.bundestag.de/services/opendata") +
theme_minimal()
<- stammdaten_19 %>%
mdb_partei_grey ggplot(aes(x = fraktion)) +
geom_bar(aes(fill = fraktion)) +
labs(x = "Fraktion",
y = "Mandate",
title = "Anzahl Mandate im 19. Bundestag nach Fraktionszugehörigkeit",
caption = "Daten: https://www.bundestag.de/services/opendata") +
scale_fill_grey()
ggsave("mdb_party_colour.eps", plot = mdb_partei_colour)
## Saving 7 x 5 in image
ggsave("mdb_party_grey.eps", plot = mdb_partei_grey)
## Saving 7 x 5 in image
Wir können für ggsave()
noch weitere Argumente festlegen. Zum Beispiel um die
Größe und Auflösung der Graphik einzustellen. Diese sind vor allem interessant,
wenn wir uns für das Speichern in einem pixelbasierten Format entscheiden. Für
mehr Informationen betrachten Sie bitte ?ggsave()
.