7 Graphiken mit ggplot2


Artwork by Allison Horst

7.1 Exkurs: Warum viridis?

Das viridis Paket in R stellt eine Reihe an Colormaps bereit, die folgenden Anspruch an sich stellen:

  • gute Lesbarkeit und Unterscheidbarkeit in Graphiken
  • auch bei Farbenblindheit oder Farbsehschwäche
  • bleibt bei Grauskala(-druck) erhalten

Praktisch bedeutet das, die Farbkarten sind:

  • farbenfroh: Sie umspannen weite Teile der Farbpalette, damit Unterschiede einfach zu erkennen sind
  • einheitlich: Nah beieinander liegende Punkte haben ähnliche Farben und weit auseinander liegende Punkte haben stark unterschiedliche Farben – und das möglichst konsistent über den gesamten Farbraum hinweg
    \(\rightarrow\) ein fester Abstand wird also an verschiedenen Stellen im Farbraum als perzeptuell gleich wahrgenommen, d.h. keine mal schnellen mal langsamen Farbton- oder Helligkeitsänderungen

Gerade die Einheitlichkeit ist wichtig, sie sorgt dafür, dass keine Gebiete überbetont werden, während Kontrast an anderen Strellen nicht gegeben ist. Hier die viridis Farbskala oben und jet (langjährig die Standardfarben in Matlab) unten:

Bei jet stechen besonders Gelb und Türkis heraus – in einer Graphik gibt das Artefakte durch die Darstellung, weil unauffällige Daten durch die Farbwahl auf einmal außergewöhnlich wirken. Außerdem werden an anderen Stellen Unterschiede in den Daten dadurch unterschlagen, dass in weiten Teilen des roten und blauen Spektrums in jet fast keine Farbstufen enthalten sind. viridis versucht dieses Problem zu beheben und wirkt homogen – ohne “Spitzen und Täler”.

Zusätzlich muss berücksichtigt werden, dass Graphiken auch bei Grauskaladruck noch interpretierbar bleiben. Das macht eine Grauskala aus viridis und jet:

Bei der oberen viridis Skala vermindert sich die Interpretierbarkeit nur minimal, während man bei der unteren Skala nicht mehr zwischen hohen und niedrigen Werten unterscheiden kann. Tatsächlich wirkt es so, als ob die mittleren Bereiche besonders auffällig wären – Bereiche die meistens um die 0 herum liegen!

Im viridis Paket gibt es 8 Colormaps, aus denen man wählen kann und die alle diese Kriterien erfüllen:

7.2 ggplot2 – Einführung

ggplot2 ist ein Paket zur graphischen Darstellung in R, das auf dem Buch “The Grammar of Graphics” von Leland Wilkinson basiert. Wie bei dplyr ist die Codestruktur an Grammatik orientiert und somit einfach nachzuvollziehen. Ablauf der Graphikerstellung in ggplot2 lässt sich wie folgend zusammenfassen:

  • Daten bereitstellen

  • Wie werden Variablen in der Graphik in Ästhetik (aesthetic mappings) umgewandelt? – aesthetics()

    • Was ist die x-Achse, was die y-Achse?
    • Wonach wird farbkodiert?
  • Welche graphische Darstellung?

    • Scatterplot – geom_point()
    • Histogram – geom_histogram()
    • Linienplot – geom_line()
  • Ggf. weitere Details definieren, wie z.B. die Achsenlabel

Um eine Graphik zu “bauen” kann man also dieser Struktur folgen:


ggplot(data = DATA, aes(MAPPINGS)) +

GEOM_FUNCTION (mapping = aes(MAPPINGS), position = POSITION) +

LABEL_FUNCTION +

THEME_FUNCTION +

COORDINATE_FUNCTION +

SCALE_FUNCTION +

FACET_FUNCTION


Dabei sind DATA, MAPPINGS und GEOM_FUNCTION notwendig, während der Rest nicht notwendig ist, da es gute Standardeinstellungen gibt.


Vorsicht: In ggplot2 sind Lagen mit + verknüpft und nicht mit %>%!

7.3 Vor der Visualisierung: Die Daten

Das Kapitel arbeitet mit einem Datensatz, der die Superhelden von Marvel und DC miteinander vergleicht. Die Daten finden sich auf GitHub (“https://github.com/cosmoduende/r-marvel-vs-dc”), sind aber auf zwei Files aufgeteilt, die erst einzeln geladen und dann zusammengeführt werden müssen.

Erst werden die zwei Files von GitHub heruntergeladen und den Variablen MarvelCharacters und MarvelStats zugewiesen. Dabei werden fehlende Werte als NA kodiert:

# Lade Daten aus zwei unterschiedlichen Files
MarvelCharacters <- read_csv("https://raw.github.com/cosmoduende/r-marvel-vs-dc/main/dataset_shdb/heroesInformation.csv", 
                             na = c("-", "-99.0"))
## Warning: One or more parsing issues, call `problems()` on your data
## frame for details, e.g.:
##   dat <- vroom(...)
##   problems(dat)
MarvelStats <- read_csv("https://raw.github.com/cosmoduende/r-marvel-vs-dc/main/dataset_shdb/charactersStats.csv")

Dann werden nur die Charaktere aus Marvel und DC ausgewählt und die MarvelCharacters-Daten werden mit dplyr vorbearbeitet:

# Preprocessing der Daten `MarvelCharacters`
marvelDcInfo <- MarvelCharacters %>%
  rename(Name = name) %>%                  # `name` -> `Name`
  filter(Publisher == "Marvel Comics" |    # nur Marvel oder... 
           Publisher == "DC Comics")  %>%  # ... DC
  filter(!duplicated(Name)) %>%            # Duplikate löschen
  # nur bestimmte Spalten (es gibt z.B. auch Augenfarbe)
  select(Name, Gender, Race, Publisher, Weight, Height) 

Dann werden die beiden Datensätze zusammengefügt:

# Zusammenführen der beiden Datensätze
MarvelDC <- inner_join(marvelDcInfo, MarvelStats, by = "Name")

# einige Zeilen sind falsch kodiert und enthalten eine andere Skala,
# deswegen werden alle Zeilen mit Intelligence = 1 ausgeschlossen. 
MarvelDC <- MarvelDC %>% 
  filter(Intelligence > 1) 

Damit ist der Datensatz MarvelDC entstanden, mit dem wir weiterarbeiten können!

Um ggplot Daten zu geben, kann man sie entweder in den Klammern definieren:

ggplot(data = MarvelDC)   # "data = " kann auch weggelassen werden

Oder man gibt sie via Pipeing an ggplot weiter – beides ist äquivalent:

MarvelDC %>%
  ggplot()

Dieser Code funktioniert allerdings noch nicht, da wir bisher nur die Daten definiert haben, aber noch keine MAPPINGS und auch keine GEOM_FUNCTION – die beiden anderen erforderlichen Angaben.

7.4 Ästhetische Mapping

Das ästhetische Mapping (aesthetics) kann entweder direkt in ggplot definiert werden, dann gilt es für alle weiteren Schritte, oder es kann in der jeweiligen graphischen Funktion definiert werden, dann gilt es nur für diese geom_* Funktion.

aesthetics Bedeutung
x Welche Variable soll auf die x-Achse?
y Welche Variable soll auf die y-Achse?
shape Nach den Werten welcher Variable soll die Form vergeben werden?
color Nach den Werten welcher Variable soll die Farbe vergeben werden?
fill Nach den Werten welcher Variable soll die Füllfarbe vergeben werden?


aesthetics in ggplot() werden an alle geom_* weitergegeben. aesthetics in geom_* sind spezifisch für diese graphische Funktion (und können geerbte Werte überschreiben).


Hier ein Beispiel, das sich wie folgend liest: “Nehme MarvelDC als Daten. Die x-Achse soll Publisher sein und die y-Achse Combat. Stelle das in einem Boxplot dar.”

ggplot(data = MarvelDC, aes(x = Publisher, y = Combat)) +
  geom_boxplot()    

Um eine farbliche Trennung nach Geschlecht zu haben, kann das Beispiel erweitert werden: “Nehme MarvelDC als Daten. Die x-Achse soll Publisher sein und die y-Achse Combat. Stelle das in einem Boxplot dar. Wähle unterschiedliche Farben für Gender und fülle die Plots damit.”

ggplot(data = MarvelDC, aes(x = Publisher, y = Combat)) +
  geom_boxplot(aes(fill = Gender))    

7.5 Graphischen Funktionen

Mit den graphischen Funktionen (geom_*) gibt man an, welche Art der graphischen Darstellung man will. Beispiele sind:

aesthetics Anzahl Variablen: x ist dabei: y ist dabei:
geom_bar() 1 diskret -
geom_histogram() 1 kontinuierlich -
geom_qq() 1 kontinuierlich -
geom_boxplot() 2 diskret kontinuierlich
geom_violin() 2 diskret kontinuierlich
geom_point() 2 kontinuierlich kontinuierlich
geom_smooth() 2 kontinuierlich kontinuierlich

7.5.1 Säulen- und Balkendiagramm

geom_bar ist eine graphische Funktion, um Häufigkeiten einer diskreten Variable in einem Säulen- oder Balkendiagramm zu visualisieren.

ggplot(data = MarvelDC,        # Nehme Daten MarcelDC
       aes(x = Publisher)) +   # auf der x-Achse soll Publisher sein
  geom_bar()                   # stelle in einem Barplot dar

Marvel hat doppelt soviele Superhelden wie DC! Will man wissen, wie viele es genau sind, kann man mithilfe eines Graphik-Labels die Zählung hinzufügen:

ggplot(data = MarvelDC, 
       aes(x = Publisher)) +
  geom_bar() +
  # man kann Label mithilfe der graphischen Funktion
  # geom_label und der Statistik "zählen" hinzufügen
  geom_label(stat = "count",  
             aes(label = ..count..)) 

Indem man eine Farbkodierung vergibt, kann man in diesem Säulendiagramm das Geschlechterverhältnis beurteilen. Da hier mit Farben gefüllt wird, ist das Argument fill.

ggplot(data = MarvelDC,      
       aes(x = Publisher,    
           fill = Gender)) +    # vergebe Füllfarbe nach Geschlecht
  geom_bar()                 

In der Graphik oben wurde der default-Parameter für Position verwendet, weil nichts anderes definiert wurde. Das ist stack. Bei stack werden die Teile übereinander “gestapelt” dargestellt. Da weit mehr Charaktere aus Marvel stammen, kann die Position fill dafür sorgen, dass man das Geschlechterverhältnis besser beurteilen kann. fill erstellt Balken gleicher Länge, sodass eine Beurteilung der relativen Anteile leichter fällt. Erst sollten allerdings die NA Fälle herausgenommen werden, damit es bei Marvel und DC je nur zwei Kategorien gibt.

MarvelDC %>%                  
  filter(!is.na(Gender)) %>%    # Schließe Gender=NA aus
  ggplot(aes(x = Publisher,    
             fill = Gender)) + 
  geom_bar(position = "fill")   # mache alle Balken gleich lang

Die x oder y Angabe entscheidet darüber, ob ein Säulen- oder Balkendiagramm entsteht. Oben wurden die Daten als x an die Funktion gegeben und ein Säulendiagramm ist entstanden. Werden die Daten als y angegeben, so entsteht ein Balkendiagramm:

MarvelDC %>%               
  filter(!is.na(Gender)) %>%
  ggplot(aes(y = Publisher,     # auf der y-Achse soll Publisher sein 
             fill = Gender)) +
  geom_bar(position = "fill")

Dieselbe Information kann auch in Kreisform dargestellt werden, in sogenannten Polarkoordinaten:

MarvelDC %>%
  filter(!is.na(Gender)) %>%
  ggplot(aes(y = Publisher, 
             fill = Gender)) +
  geom_bar(position = "fill") +
  coord_polar()                 # stelle das in Polarkoordinaten dar

Die Information für Marvel DC wird auf dem äußeren Kreis abgebildet und die für DC Comics auf dem inneren Kreis abgebildet. Hier sieht man, dass bei DC Comics nur weniger als ein Viertel aller Helden weiblich sind, während es bei Marvel etwas mehr als ein Viertel sind.

7.5.2 Histogramm

geom_histogram ist eine graphische Funktion um Häufigkeiten einer kontinuierlichen Variable zu visualisieren. Beispielsweise kann man schauen, wie schnell die Superhelden unterwegs sind:

ggplot(MarvelDC,                
       aes(x = Speed)) +        # auf der x-Achse soll Speed sein  
  geom_histogram(               # stelle das in einem Histogramm dar
    bins = 10)                  # Anzahl der Kategorien soll 10 sein

Unterscheidet sich die Geschwindigkeit der Helden zwischen Marvel und DC?

ggplot(MarvelDC, 
       aes(x = Speed, 
           fill = Publisher)) + 
  geom_histogram(bins = 10,             
                 alpha = 0.7,         # "Durchsichtigkeit" bei 70%
                 position = "dodge")  # Position Balken: nebeneinander

Offensichtlich nicht, die Verteilungen sind sich relativ ähnlich.

Bei Speed fällt allerdings direkt auf, dass es nicht sehr normalverteilt aussieht. Ein Histogramm lässt hier einen ersten Eindruck zu, aber eine visuelle Prüfung der Normalverteilung sollte lieber über einen qq-Plot vorgenommen werden.

7.5.3 QQ-Plot

Bei einem qq-Plot kann und muss man Punkte und Vergleichslinie getrennt definieren:

ggplot(MarvelDC, 
       aes(sample = Speed)) +  # erstelle Quantile von: Speed
  geom_qq() +                  # erstelle QQ-Plot Punkte
  geom_qq_line()               # erstelle QQ-Plot Vergleichslinie

Bei Speed zeigen sich deutliche Abweichungen von einer Normalverteilung. Das gilt auch für alle anderen Eigenschaften (hier nicht gezeigt). Nur der Summenscore, Total, zeigt im qq-Plot eine Verteilung nahe der Normalverteilung:

ggplot(MarvelDC, 
       aes(sample = Total)) +   # erstelle Quantile von: Total
  geom_qq() + 
  geom_qq_line()

7.5.4 Boxplot

geom_boxplotist eine graphische Funktion, um kontinuierliche Verteilungen getrennt nach einer diskreten Gruppierung darzustellen. Hat Marvel oder DC die stärkeren Superhelden? – Dafür betrachten wir den Total Wert jedes Helden.

ggplot(MarvelDC, 
       aes(x = Publisher, y = Total)) + 
  geom_boxplot()

Auf den ersten Blick mithilfe eines Boxplots gibt es keine Unterschiede zwischen Marvel Comics und DC Comics.

ggplot(MarvelDC, 
       aes(x = Publisher, y = Total, 
           fill= Gender)) + 
  geom_boxplot()

Betrachtet man Total aufgespalten nach Geschlecht, so scheint Marvel etwas stärkere Männer und schwächere Frauen zu haben – allerdings sind die Unterschiede so gering, dass es sich wahrscheinlich um zufällige Schwankungen und nicht um belastbare Effekte handelt! Keins der Universen scheint also dem anderen überlegen zu sein.

7.5.5 Violinen-Plot

geom_violin ist ebenfalls eine graphische Funktion um kontinuierliche Verteilungen getrennt nach einer diskreten Gruppierung darzustellen – und lässt etwas mehr Aufschluss auf die Daten zu (z.B. wie die grobe Verteilung der Werte ist).

ggplot(MarvelDC, 
       aes(x = Publisher, y = Total, 
           fill= Gender)) + 
  geom_violin(            # stelle in einem Violinenplot dar
    trim=FALSE)           # schneide Spitzen nicht ab

7.5.6 Beeswarm Plot mit dem Paket ggbeeswarm

Das package ggbeeswarm bietet eine ähnliche Darstellung durch die graphische Funktion geom_quasirandom:

library(ggbeeswarm)
MarvelDC %>%
  filter(!is.na(Gender)) %>%
  ggplot(aes(y = Total, x = Publisher,
             color = Gender)) +
  
  geom_quasirandom(dodge.width = 1)   # stelle als beeswarm dar

Weder Violinen-Plot noch Beeswarm-Plot deuten darauf hin, dass Marvels Superhelden stärker und cooler sind, als die von DC. Ohne gegenteilige Hinweise bleibt es also bei der Annahme, dass beide Universen gleich gut sind.

7.5.7 Scatterplot

Ein Scatterplot mit geom_point stellt die Daten als Punkte im Raum zweier kontinuierlicher Variablen dar. Beispielsweise kann man Power und Durability aller Helden gegeneinander darstellen:

ggplot(data = MarvelDC, 
       aes(x = Power, y = Durability)) + 
  geom_point()                          # stelle als Scatterplot dar

Auch diese Graphik kann einfach nach Publisherfarblich kodiert werden. Hier sollen die Punkte Farbe haben, aber es wird nichts mit Farbe gefüllt, deswegen ist das Argument hier color:

ggplot(data = MarvelDC, 
       aes(x = Power, y = Durability, 
           color = Publisher)) +   # getrennte Farben für Publisher
  geom_point()    

Die Daten beider Publisher sind weit verteilt, es ist also keineswegs so, dass DCs Superhelden weniger Power haben, als die von Marvel.

Will man zusätzlich nach Geschlecht unterscheiden, so geht das beispielsweise über die Form der Punkte mithilfe des Arguments shape:

ggplot(data = MarvelDC, 
       aes(x = Power, y = Durability, 
           color = Publisher, 
           shape = Gender)) +     # getrennte Formen für Gender
  geom_point()    

7.5.8 (Linearer) Fit

Die Power und Durability Daten können mit einer Funktion gefittet werden. So kann man visuell prüfen, ob es bei Marvel und DC jeweils einen anderen Zusammenhang zwischen Power und Durability gibt. Dafür wird die graphische Funktion geom_smooth verwendet. Um ein lineares Modell zu erhalten, muss das Argument method = "lm" für “linear model” gesetzt werden. Um y durch x vorherzusagen, braucht es die Formel y ~ x:

ggplot(data = MarvelDC, 
       aes(x = Power, y = Durability, 
           color = Publisher, 
           shape = Gender)) +
  geom_point()    + 
  geom_smooth(method = "lm",      # lineares Modell
              formula = 'y ~ x',  # y durch x vorhersagen
              se = FALSE)         # keine Fehlerbalken

Das sind aber 5 Fits – je für Geschlecht und Publisher. Nicht nur für die beiden Publisher wie geplant.

Das liegt daran, dass sowohl Farbe als auch Form innerhalb von ggplot bei den allgemeinen aesthetics definiert sind. Um nur einen linearen Fit für jeden Publisher zu erhalten, nicht aber nach Geschlecht aufgespalten, muss man die Form-Kennung für Geschlecht nur an geom_point geben. Auf diese Weise kann sie nicht mehr an geom_smooth weitergegeben werden. Gibt man die Farb-Kennung für Publisher nur an die Linien, also nur an geom_smooth, so erhält man nur eine farbliche Trennung bei den Fit-Linien, nicht aber bei den zugrunde liegenden Punkten. Mit se=TRUE werden die Fehlerintervalle um die linearen Fit-Funktionen herum dargestellt. Der folgende Code liefert einen linearen Fit der Power und Durability der Superhelden farblich getrennt nach Marvel und DC:

ggplot(data = MarvelDC, 
       aes(x = Power, y = Durability)) +
  geom_point(aes(shape = Gender)) +     # Form gilt nur für Punkte
  geom_smooth(aes(color = Publisher),   # Farbe gilt nur für Linien
              method = "lm",      
              formula = 'y ~ x',  
              se = TRUE)         

Auch hier zeigen sich weiterhin keine Unterschiede zwischen den Publishern. Es muss wohl endgültig davon ausgegangen werden, dass Marvel nicht das alleinige Recht auf coole Superhelden hat. Unsere Daten geben keine Hinweise auf die Überlegenheit des einen oder anderen Superhelden-Universums.

7.5.9 Linienplot

Linienplots lassen sich am besten an einer überschaubaren Anzahl von Punkten veranschaulichen, z.B. eignet sich eine Auswahl der X-Men. Die Datenpunkte werden farblich nach Geschlecht getrennt – dann werden alle Punkte durch eine Linie verbunden:

# Erstelle Vektor der X-Men Charaktere: 
XMen <- c("Wolverine", "Jean Grey", "Storm", "Beast", 
          "Cyclops", "Professor X", "Raven")

MarvelDC %>%
  filter(Name %in% XMen) %>%  # Verwende nur X-Men
  ggplot(aes(x = Power,            
             y = Durability)) +
  geom_point(                 # stelle in Scatterplot dar
    aes(color = Gender),      # Farbe nach Gender (Punkte)
             size = 3) +      # Punkte sollen Größe 3 haben
  geom_line()                 # verbinde Punkte mit Linie

Da Farbe innerhalb von geom_point definiert ist, enthalten die allgemeinen aesthetics keine Gruppierung. Deswegen verbindet die Linie einfach alle Datenpunkte. Informativer ist es natürlich, getrennte Linien für die Geschlechter zu haben. Dazu muss die Farbdefinition in den allgemeinen aesthetics erfolgen und nicht innerhalb von geom_point:

XMen <- c("Wolverine", "Jean Grey", "Storm", "Beast", 
          "Cyclops", "Professor X", "Raven")

MarvelDC %>%
  filter(Name %in% XMen) %>%
  ggplot(aes(x = Power, 
             y = Durability, 
             color = Gender)) +     # Farbe nach Gender (Punkte & Linie)
  geom_point(size = 3) +          
                 
  geom_line(aes(linetype = Gender)) # zusätzlich Linentyp nach Gender

Will man wissen, welcher Charakter welche Werte aufweist, fügt geom_label Textlabel zu dem Plot hinzu. Außerdem können die Achsen so skaliert werden, dass der absolute Nullpunkt enthalten ist und beide Achsen symmetrisch laufen:

XMen <- c("Wolverine", "Jean Grey", "Storm", "Beast", 
          "Cyclops", "Professor X", "Raven")

MarvelDC %>%
  filter(Name %in% XMen) %>%
  ggplot(aes(x = Power, 
             y = Durability,
             color = Gender)) +
  geom_point(size = 3) + 
  geom_line(aes(linetype = Gender)) +
  geom_label(aes(label = Name,      # Füge Label hinzu mit: "Name"
                 color = Gender)) + # färbe Labels nach Geschlecht
  xlim(c(0, 110))+                  # x-Achse soll laufen von 0-110
  ylim(c(0, 110))                   # y-Achse soll laufen von 0-110

7.6 Sonstige Funktionalität

7.6.1 Labels

Label sind die wahrscheinlich wichtigste zusätzliche Funktionalität, die fast immer benötigt wird, um einen Plot allgemein verständlich zu machen. Mithilfe von labs() können Titel, Untertitel, Achsenbeschriftungen und eine Caption zu einem Plot hinzugefügt werden. Z.B. für den Plot der X-Men:

XMen <- c("Wolverine", "Jean Grey", "Storm", "Beast", 
          "Cyclops", "Professor X", "Raven")

MarvelDC %>%
  filter(Name %in% XMen) %>%
  ggplot(aes(x = Power, 
             y = Durability, 
             color = Gender)) +
  geom_point(size = 3) + 
  geom_line(aes(linetype = Gender)) +
  geom_label(aes(label = Name, 
                 color = Gender)) +
  xlim(c(0, 110)) +
  ylim(c(0, 110)) +

  # Füge Beschriftungen hinzu: Titel, x- & y-Achsen, Caption
  labs(title = "Power and durability of the X-Men",
         x = "Power", 
         y = "Durability",
         caption = "dataset source: https://github.com/cosmoduende/r-marvel-vs-dc" )

Ein weiteres Beispiel:

ggplot(MarvelDC, 
       aes(x = Publisher, y = Total, 
           fill= Gender)) + 
  geom_boxplot() +

  labs(title = "Total skills of Marvel and DC superheros",
         subtitle = "Separate for their gender", 
         x = "Publisher", 
         y = "Total skills",
         caption = "dataset source: https://github.com/cosmoduende/r-marvel-vs-dc" )

7.6.2 Thema

Es gibt verschiedene themes die das grundlegende Graphiklayout bestimmen.

  • theme_bw() – weißer Hintergrund mit grid Linien

  • theme_gray() – grauer Hintergrund mit hellen grid Linien (default)

  • theme_dark() – dunkler Hintergrund mit grid Linien

  • theme_minimal() – minimalistisches theme

  • theme_void() – leeres theme

Minimalistisches Thema:

ggplot(MarvelDC, 
       aes(x = Publisher, y = Total, 
           fill= Gender)) + 
  geom_boxplot() +
  
  theme_minimal()         # verwende Thema: Minimal

Dunkles Thema:

ggplot(MarvelDC, aes(x = Publisher, y = Total, fill= Gender)) + 
  geom_boxplot() +
  
  theme_dark()            # verwende Thema: Dunkel

7.6.3 Position

Mit position kann die Positionierung graphischer Elemente zueinander eingestellt werden. Positionsarten sind z.B.:

  • identity – Werte sollen an ihrer wahren Position (d.h. so wie sie in der Funktion eingegeben wurden) angezeigt werden. Tipp: Bei dieser Einstellung kann man die angezeigten Werte machmal nicht so gut erkennen durch (z.B. weil sie aufeineander liegen). Manchmal kann es hilfreich sein, den alpha Parameter zusätzlich zu verwenden, um die angezeigten Punkten (oder Balken, etc.) etwas zu entzerren.

  • stack – Elemente aufeinander schichten (default)

  • dodge – Elemente nebeneinander zeigen

  • jitter – Zufälliges Rauschen auf die (x,y) Position jedes Elements addieren, um den Plot zu entzerren

dodge = nebeneinander:

MarvelDC %>%
  filter(!is.na(Alignment),            # verwende nur Alignments...
         Alignment != "neutral") %>%   # ... `good` und `bad`
  ggplot(aes(x = Intelligence, 
             fill = Alignment)) +
  geom_histogram(bins = 15,
                 alpha = 0.6,
                 
                 position = "dodge")   # Position: nebeneinander

stack = aufeinander:

MarvelDC %>%
  filter(!is.na(Alignment), 
         Alignment != "neutral") %>%
  ggplot(aes(x = Intelligence, 
             fill = Alignment)) +
  geom_histogram(bins = 15,
                 alpha = 0.6,
                 
                 position = "stack")   # Position: aufeinander

identity = hintereinander:

MarvelDC %>%
  filter(!is.na(Alignment), 
         Alignment != "neutral") %>%
  ggplot(aes(x = Intelligence, 
             fill = Alignment)) +
  geom_histogram(bins = 15,
                 alpha = 0.6,
                 
                 position = "identity")  # Position: hintereinander

7.6.4 Legenden

Die Legende wird von ggplot automatisch erstellt und kann einfach an die Positionen bottom, right, left und top gelegt werden:

ggplot(MarvelDC, aes(x = Publisher, y = Total, 
                     fill= Gender)) + 
  geom_boxplot() +
  theme_minimal() + 
  labs(title = "Total skills of Marvel and DC superheros",
         subtitle = "Separate for their gender", 
         x = "Publisher", 
         y = "Total skills",
         caption = "dataset source: https://github.com/cosmoduende/r-marvel-vs-dc" ) +
  
  theme(legend.position="top")   # positioniere Legende oben

7.6.5 Koordinatensysteme

Das wichtigste Koordinatensystem ist zweifellos das kartesische. In R kann man aber z.B. auch Polarkoordinaten verwenden, oder das kartesische System “drehen”:

  • coord_flipdreht ein kartesisches Koordinatensystem um (x wird zu y und umgekehrt) - empfohlen ist allerdings, das über die Definition von x und y direkt zu lösen.

  • coord_polarPolarkoordinaten

Polarkoordinaten wurden bereits beim Balkendiagramm gezeigt.

7.6.6 Farbskalen

scale bestimmt, auf welche Farbskala die Daten abgebildet werden. Am Beispiel von viridis:

  • scale_color_viridis_d() – diskretes viridis Spektrum für das Argument color

  • scale_color_viridis_c() – kontinuierliches viridis Spektrum für das Argument color

  • scale_fill_viridis_d() – diskretes viridis Spektrum für das Argument fill

Über option kann im Paket viridis auf eine andere der enthaltenen Skalen zugegriffen werden:

  • scale_fill_viridis_d(option=inferno) – diskretes inferno Spektrum für das Argument fill

Neben dem viridis Package gibt es auch den ColorBrewer in R, der unter anderem folgende Farbkarten kennt (am Beispiel von fill Skalen):

  • scale_fill_brewer(palette="Set1") andere mögliche Einstellungen für palette: "Set2", "Set3", "Accent", "Dark2", "Pastel1", "Pastel2"

Wenn man allerdings schon ein Farbspektrum selbst definiert, ist es empfehlenswert ein colorblind friendly Schema wie alle Skalen aus dem viridis Package zu benutzen.

Im folgenden Beispiel werden verschiedene Einstellungen zusammengeführt, um eine ansprechende und informative Graphik zu erhalten. Erst wird eine Liste der besten Superhelden der X-Men, der Avengers und der Guardians of the Galaxy erstellt. Dann veranschaulicht ein Balkendiagramm welcher Art sie angehören. Also ob es Menschen sind oder Mutanten oder Androiden… Dann wird die Graphik informativ beschriftet, so dass sie auch ohne den zugehörigen Code verständlich ist, und als letztes wird ein diskretes viridis Spektrum als die Farbskala bestimmt, die R verwenden soll:

# Charaktere der X-Men, der Guardians of the Galaxy und der Avengers
XMen <- c("Wolverine", "Jean Grey", "Storm", "Beast", 
          "Cyclops", "Professor X", "Raven")
GoG <- c("Groot", "Quill", "Rocket Raccoon")
Avengers <- c("Iron Man", "Captain America", "Black Widow", 
              "Hulk", "Hawkeye", "Thor", "Spiderman", "Vision")

# ein Vektor mit den coolsten Superhelden
BestHeros <- c(XMen, GoG, Avengers)

MarvelDC %>%
  filter(Name %in% BestHeros) %>%     # Nur Charaktere aus 'BestHeros'
  ggplot(aes(y = Race,                # y soll 'Race' sein
             fill= Race)) +           # vergebe Füllfarbe nach 'Race'
  geom_bar() +                        # stelle als Balken dar
  theme_bw() +                        # in scharz-weißem Thema
  
  # Beschrifte
  labs(title = "Races of superheros",
       subtitle = "X-Men, Avengers and Guardians of the Galaxy",
         x = "Count", 
         y = "",
         caption = "dataset source: https://github.com/cosmoduende/r-marvel-vs-dc" ) +
  
  scale_fill_viridis_d()              # verwende Farben aus viridis

7.6.7 Variablenskalen

Mit ggplot2 können Variablen einfach auf unterschiedliche Skalen übertragen werden. Diese Funktionalität kann mit der x-Achse oder mit der y-Achse verwendet werden, z.B.:

  • scale_x_log10() ()

  • scale_x_sqrt() ()

  • scale_x_reverse() ()

Beispielsweise können Sie in der folgenden Abbildung den Zusammenhang zweier Variablen betrachten. Dabei wird ein logarithmischer Zusammenhang dargestellt.

ggplot(data = data.frame(x = seq(1:100), y = 10 + 3 * log(seq(1:100))),
       aes(x = x, y = y)) +
  geom_point()

Wenn Sie die x-Achse mittels scale_x_log10() umwandeln, könnnen Sie sehen, dass der dargestellte Zusammenhang linear aussieht (d.H. der Zusammen ist linear in der Logarithmus-Skala).

ggplot(data = data.frame(x = seq(1:100), y = 10 + 3 * log(seq(1:100))),
       aes(x = x, y = y)) +
  geom_point()

  scale_x_log10()
## <ScaleContinuousPosition>
##  Range:  
##  Limits:    0 --    1

7.7 Facetten

Facettierung bedeutet, dass ein Plot in mehrere Plots aufgespalten wird, abhängig von den Werten einer oder mehrerer diskreter Variablen. Der einfachste Weg geht über facet_wrap(). Beispielsweise kann man das Balkendiagramm von oben, welches die Art der Superhelden zeigt, um die größten Gegner dieser Helden erweitern. Erst definiert man in einem Vektor, wer die größten Helden und Bösewichte sind. Dann facettiert man das Balkendiagramm nach Alignment, es werden also unterschiedliche Grids für die Guten und die Bösen erstellt:

# Gegner der X-Men, der Guardians of the Galaxy und der Avengers
VXMen <- c("Magneto", "Gambit", "Apocalypse", "Mystique")
VGoG <- c("Ronin", "Thanos")
VAvengers <- c("Loki", "Ultron", "Doctor Doom", "Galactus")

# ein Vektor mit den coolsten Superhelden und ihren größten Gegnern
HerosVillains <- c(BestHeros, VXMen, VGoG, VAvengers)

MarvelDC %>%
  filter(Name %in% HerosVillains) %>%  # Nur wenn in 'HerosVillains'
  ggplot(aes(y = Race,                 # y soll 'Race' sein
             fill = Race)) +           # vergebe Füllfarbe nach 'Race'
  geom_bar() +                         # stelle als Balken dar
  theme_bw() +                         # in scharz-weißem Thema
  
  # Beschrifte
  labs(title = "Races of superheros and their villains",
       subtitle = "X-Men, Avengers and Guardians of the Galaxy",
         x = "Count", 
         y = "",
         caption = "dataset source: https://github.com/cosmoduende/r-marvel-vs-dc" ) +
  scale_fill_viridis_d() +             # verwende Farben aus viridis
  
  facet_wrap(~ Alignment)              # trenne Grids nach 'Alignment'

Dieser Plot enthält viele der sonstigen Funktionalitäten von ggplot2. Auch wenn es anfangs wie unnötige Arbeit erscheint: gerade die richtige Beschriftung eines Plots ist unerlässlich! Farbskala und Thema hingegen sind nett zu haben, aber nicht unbedingt ab der ersten Version eines Plots erforderlich.