18  Daten visualisieren

In R erstellen wir Plots mit Hilfe der ggplot2-Funktionen. Anders als in Excel werden mit diesen Funktionen Plots schrittweise aufgebaut und können auf diese Weise einheitlich reproduziert werden.

Als Erstes laden wir wie immer die tidyverse-Bibliothek, damit wir die ggplot-Funktionen und die Funktionsverkettung verwenden können.

library(tidyverse)
── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
✔ dplyr     1.1.3     ✔ readr     2.1.4
✔ forcats   1.0.0     ✔ stringr   1.5.0
✔ ggplot2   3.4.3     ✔ tibble    3.2.1
✔ lubridate 1.9.2     ✔ tidyr     1.3.0
✔ purrr     1.0.2     
── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors

Wir erzeugen eine Datenvisualisierung immer mit den folgenden Funktionsaufrufen:

  1. Wir initiieren einen Plot mit der Angabe der darzustellenden Vektoren.
  2. Anschliessend wählen wir die Darstellung der Datenpunkte mit einer Geometriefunktion aus.
Achtung

ggplot2 verwendet zur Funktionsverkettung den +-Operator und nicht wie der Rest der modernen R-Funktionen den Verkettungsoperator |>. Wir können also leicht erkennen, dass ein Code-Fragment einen Plot erzeugt, wenn Funktionen mit + verkettet sind.

Mit den folgenden Funktionsaufrufen erzeugen wir ein einfaches Punktdiagramm. Als Beispielstichprobe verwenden wir hier die iris-Daten, die mit R mitgeliefert werden.

iris |>
   ggplot(aes(x = Sepal.Length, y = Petal.Length)) + 
       geom_point()

18.1 Technischer Aufbau von Visualisierungen

In der ersten Zeile legen wir fest, welche Daten visualisiert werden sollen. Die Grundlage für jede Datenvisualisierung ist immer ein Transformationsergebnis.

In der zweiten Zeile signalisieren wir R mit der Funktion ggplot(), dass wir einen Plot erzeugen wollen. Wir übergeben als Parameter das Ergebnis der aes()-Funktion.

Hinweis

Die Funktion aes() legt die ästhetischen Voraussetzungen für einen Plot fest. Damit legen wir fest, welche Daten für unsere Datenpunkte verwendet werden sollen.

In diesem Beispiel legen wir den Vektor Sepal.Length für die Koordinaten auf der x-Achse und Petal.Length für die Koordinaten auf der y-Achse fest. Die Datenpunkte werden also durch die beiden gemeinsam auftretenden Werte in diesen Vektoren festgelegt.

Mit der dritten Zeile legen wir die Geometrie der Datenpunkte fest. Alle ggplot2-Funktionsnamen zur Darstellung von Datenpunkten beginnen mit geom_ (für Geometrie). In diesem Beispiel wollen wir unsere Datenpunkte mit Punkten (engl. Points) darstellen. Deshalb verwenden wir die Funktion geom_point().

Diese drei Schritte zeigen die grundsätzliche Logik zum Erstellen von Plots mit R.

18.2 Mathematische Funktionen visualisieren

In der Mathematik werden regelmässig Funktionen besprochen. Diese Funktionen können wir mit R leicht visualisieren.

Dabei nutzen wir aus, dass wir in R neue Funktionen mit dem Schlüsselwort function definieren können. Im folgenden Beispiel verwenden wir die beiden Funktionen.

f1(x) \to x^2 - 3x

und

f2(x) \to 4x + 2

Im nächsten Schritt erstellen wir unsere beiden mathematischen Funktionen. Dabei beachten wir, dass wir den Namen der jeweiligen Funktion als eine Variable zuweisen müssen. Die rechte Seite der Zuweisung zeigt R an, dass wir eine neue Funktion mit dem Parameter x erstellen möchten. Nach dieser Funktionsdefinition folgt der sog. Funktionskörper in geschweiften Klammern. Hier schreiben wir die Formel unserer Funktion in der ausführlichen Operatorenschreibweise. Anders als bei der mathematischen Schreibweise dürfen wir keine Operatoren weglassen.

f1 = function (x) {
    x ^ 2 - 3 * x
}

f2 = function (x) {
    4 * x + 2
}

Damit ggplot “weiss”, welches Intervall für x wir darstellen möchten, erzeugen wir eine Stichprobe mit einem Vektor x, der genau zwei Werte hat. Diesen Vektor weisen wir der Variable Darstellungsbereich zu. Wenn wir die Werte symmetrisch angeben, dann landet die 0 auf der x-Achse in der Mitte unseres Diagramms.

Darstellungsbereich = tibble(x = c(-9, 9)) 

Jetzt können wir unsere Funktion visualisieren. Wir übergeben die Stichprobe im der Variablen Darstellungsbereich an die ggplot()-Funktion und legen mit dem Aufruf der aes()-Funktion mit dem Vektor x die Grenzen für die x-Achse fest. Anschliessend rufen wir die Funktion geom_line() auf, um einen Graphen zu erzeugen. Weil wir keine Werte für die y-Achse haben, legen wir fest, dass wir die y-Werte aus einer Funktion berechnen wollen. Das erreichen wir mit dem Parameter stat = "function". Sobald wir diesen Parameter angeben, erwartet die geom_line() Funktion eine Funktion zur Berechnung der y-Werte. Diese Funktion übergeben wir mit dem Parameter fun = f1, wobei f1 eine unserer vorab definierten Funktionen ist.

Darstellungsbereich |>
    ggplot(aes(x)) + 
        geom_line(stat = "function", fun = f1)

Diesen Schritt können wir für die Funktion f2 wiederholen.

Darstellungsbereich |>
    ggplot(aes(x)) + 
        geom_line(stat = "function", fun = f2)

Weil wir mit ggplot Darstellungen überlagern können, dürfen wir die beiden Funktionen selbstverständlich auch in einem Diagramm darstellen.

Darstellungsbereich |>
    ggplot(aes(x)) + 
        geom_line(stat = "function", fun = f1) + 
        geom_line(stat = "function", fun = f2)

Wir wollen die beiden Graphen noch visuell hervorheben, damit wir wissen, welcher Graph zu welcher Funktion gehört. Dabei überlassen wir die Auswahl der Farben ggplot, womit wir sicherstellen, dass die Farben nicht zu ähnlich sind. Dazu verwenden wir den Trick, dass wir jeder Geometrie-Funktion ergänzende ästhetische Parameter übergeben dürfen.

Darstellungsbereich |>
    ggplot(aes(x)) + 
        geom_line(stat = "function", fun = f1, 
                  aes(colour = "f1(x) = x ^ 2 - 3 * x")) + 
        geom_line(stat = "function", fun = f2, 
                  aes(colour = "f2(x) = 4 * x + 2"))

Die Legende für unser Diagramm hat keine schöne Überschrift. Das passen wir noch schnell mit der labs()-Funktion(für labels bzw. Beschriftungen) an. Dort geben wir für den ästhetischen Parameter die richtige Beschriftung an. In unserem Fall ist das colour.

Darstellungsbereich |>
    ggplot(aes(x)) + 
        geom_line(stat = "function", fun = f1, 
                  aes(colour = "f1(x) = x ^ 2 - 3 * x")) + 
        geom_line(stat = "function", fun = f2, 
                  aes(colour = "f2(x) = 4 * x + 2")) +
        labs(colour = "Funktion")

18.3 Berechnete Visualisierungen

Wir haben im Abschnitt zu einfachen Visualisieren in R die Funktion ggplot() kennengelernt, um zwei Vektoren zu visualisieren.

Sehr häufig wir einen Vektor und wollen sehen, wie die Werte in diesem Vektor verteilt sind. Wir sollen also die Werte in dem Vektor für die Visualisierung aggregieren. Hierbei handelt es sich um eine so häufige Aufgabe, dass uns ggplot() diese Aufgabe abnimmt.

Für verschiedene Visualisierungen hat ggplot() vordefinierte Funktionen, mit denen Werte für die Visualisierung aufbereitet werden, wenn die Werte für eine Achse fehlen. Diese Funktionen müssen wir im Detail nicht kennen, denn ggplot() wählt diese automatisch für uns aus.

Wir lernen heute zwei wichtige berechnete Visualisierungen kennen.

  1. Das Histogramm
  2. Den Box-Plot

18.3.1 Histogramm

Definition 18.1 Als Histogramm werden Balkendiagramme bezeichnet, die die Häufigkeiten von gemessenen Werte darstellen.

Das übliche Balkendiagramm erzeugen wir mit der Funktion geom_bar(). Diese Funktion verwenden wir immer, wenn unsere gemessenen Werte nur auf bestimmte Werte fallen (können). Die geom_bar()-Funktion zählt für jeden gemessenen Wert die Anzahl der Datensätze, in denen dieser Wert vorkommt.

Gelegentlich sind unserer Werte so verteilt, dass nur selten zwei oder mehr Datensätze gleiche Werte haben. In solchen Fällen verwenden wir die Funktion geom_histogram(). Diese Funktion teilt den gesamten Wertebereich in gleichmässige Intervalle und zählt die Anzahl der Datensätze im jeweiligen Intervall.

Das folgende Beispiel veranschaulicht die Situation.

Wir verwenden die Stichprobe digitales_umfeld1.csv. In dieser Stichprobe gibt es den Vektor tage, der das Alter der beantwortenden Person in Tagen festhält. Dabei handelt es sich rein formell um diskrete Werte. Wenn wir die Verteilung dieser Werte in einem Histogramm für diskrete Werte darstellen würden, dann erhalten wir das folgende Histogramm:

digitales_umfeld = read_csv("befragung_digitales_umfeld/digitales_umfeld1.csv")
Rows: 135 Columns: 5
── Column specification ────────────────────────────────────────────────────────
Delimiter: ","
chr (1): mobilgeraet
dbl (4): alter, tage, monate, digitalisiert

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
digitales_umfeld |> 
    ggplot(aes(x = tage)) +
        geom_bar()
Abbildung 18.1: Tage-Histogram Diskrete Werte

Auf diesem Histogramm kann man keine Verteilung erkennen. Es scheint, als ob alle Werte genau einmal vorkommen. Der Wertebereich der y-Achse deutet aber darauf hin, dass einzelne Werte bis zu drei Mal vorkommen. Diese Balken sind jedoch so dünn, dass sie nicht im Diagramm dargestellt werden können.

Die Werte in diesem Vektore verhalten sich also wie kontinuierliche Werte. Deshalb verwenden wir die Funktion geom_histogram(), um die Daten darzustellen.

digitales_umfeld |> 
    ggplot(aes(x = tage)) +
        geom_histogram()
Abbildung 18.2: Tage-Histogram

Aus diesem Histogramm können wir wesentlich besser die Verteilung des Alters in Tagen ablesen, weil der Wertebereich in grössere Segmente gegliedert wurde und die Datensätze in diesen Segmenten gezählt wurden.

Merke

Histogramme für kontinuierliche Werte erzeugen wir mit der Funktion geom_histogram(). Histogramme für diskrete Werte erzeugen wir mit der geom_bar()-Funktion.

18.3.1.1 Histogramme selbst berechnen

Gelegentlich haben uns bereits die Häufigkeiten für ein Histogramm als Teil unserer Stichproben. In solchen Fällen verwenden wir die Funktion geom_col(), um die Daten als Histogramm darzustellen. In diesem Fall müssen wir neben der x-Achse auch den Vektor mit den berechneten Werten für die y-Achse an ggplot()’s aes()-Funktion übergeben.

18.3.2 Box-Plot

Definition 18.2 Ein Box-Plot stellt die Verteilung eines Stichprobenvektors mit Hilfe von Quartilen dar.

Box-Plots werden mit der geom_boxplot() Funktion dargestellt.

Beim Box-Plot wird der Median als dicke Linie dargestellt. Der Interquartilsabstand wird als Rechteck (Box) um den Median visualisiert (2. und 3. Quartil). Dabei liegt die Hälfte der aller gemessenen Werte innerhalb der dargestelltn Box. Der gesamte Umfang wird durch Linien links (1. Quartil) und rechts (4. Quartil) vom Interquartilsabstand dargestellt. Manchmal werden Punkte an den äusseren Rändern dargestellt. Diese Punkte stellen sog. Ausreisser dar.

Wiederholen wir die Visualisierung für unsere Alterstage mit einem Boxplot, dann erhalten wir folgendes Ergebnis:

digitales_umfeld |> 
    ggplot(aes(x = tage)) +
        geom_boxplot()
Abbildung 18.3: Tage-Boxplot

Wir erkennen jetzt leicht, dass der Grossteil der Gruppe unter 10000 Tagen alt ist und dass es sechs Ausreisser gibt, die deutlich älter als der Grossteil der Gruppe sind.

18.3.3 Punkt- und Jitter-Diagramme

Die dritte wichtige visuelle Analysetechnik sind Punktwolken. Bei Punktwolken stellen wir die Werte von zwei Vektoren ähnlich einer Kreuztabelle gegenüber und überprüfen das gemeinsame Auftreten von Werten in den Vektoren unserer Messungen.

Für Punktwolken stehen zwei Funktionen zur Verfügung:

  1. geom_point() für kontinuierliche Werte.
  2. geom_jitter() für diskrete Werte.

Mit Punktdiagrammen werden zwei Merkmale mit kontinuierlichen Daten gegenübergestellt. Punktdiagramme bilden Beziehungen zwischen Merkmalen ab.

iris |>
    ggplot(aes(x = Sepal.Length, y = Sepal.Width)) +
        geom_point()
Abbildung 18.4: Punktdiagramm der iris-Daten
daten = read_csv("befragung_digitales_umfeld/befragung.csv");

daten |>
    filter(q18_6 > 0 & 
           q18_7  > 0 ) |>
    ggplot(aes(x = q18_6 , 
               y = q18_7)) + 
        geom_point()
Abbildung 18.5: Beispiel eines Punktdiagramms mit diskreten Daten

In diesem Beispiel sehen wir, dass alle Werte genau an den gleichen Punkten im Koordinatensystem liegen. Ein solcher Plot ist ein gutes Beispiel für diskrete Werte. Bei diskreten Werten fallen alle Messungen genau auf bestimmte Punkte im Wertebereich. Kontinuierliche Werte weichen oft ein wenig voneinander ab, sodass wir eine Wolke sehen würden.

Um Punktwolken für diskrete Werte zu erzeugen, verwenden wir die geom_jitter()-Funktion. Diese Funktion erzeugt einen kleinen Bereich um den diskreten (echten) Messwert und verteilt die einzelnen Datensätze mit einem zufälligen Abstand vom echten Messwert. Dadurch wird das gemeinsame Auftreten von Werten deutlich sichtbar, sofern es Gemeinsamkeiten gibt.

daten |>
    filter(q18_6 > 0 & 
           q18_7  > 0 ) |>
    ggplot(aes(x = q18_6 , 
               y = q18_7)) + 
        geom_jitter()
Abbildung 18.6: Beispiel eines Jitter-Diagramms

Durch den leichten Versatz sind nun gehäufte Wertepaare leichter zu erkennen. Bei Jitter-Plots dürfen wir aber nie vergessen, dass die Punkte zwar Messungen repräsentieren, aber leicht vom echten Messpunkt versetzt dargestellt wurden.

18.3.4 Ausgleichsgeraden

Im vorigen Abschnitt können wir eine Häufung entlang der nach rechts aufsteigenden Diagonalen erkennen. Solche Häufungen in Punktwolken deuten auf Korrelationen hin.

Definition 18.3 Eine Korrelation bezeichnet das wiederholte Auftreten von Wertepaaren in Stichproben. Korrelationen deuten auf Zusammenhänge zwischen zwei Vektoren hin.

Ähnlich wie beim Vergleichen mit Histogrammen ist es bei Punktwolken hilfreich, für die Wolke eine Referenz zur Orientierung zu haben. Das erreichen wir mit der geom_smooth()-Funktion. Die Methode lm steht für “lineares Modell”. In diesem Modell versteckt sich das Wort Linie und deshalb erzeugt ein lineares Modell immer eine Ausgleichsgerade. Der graue Bereich zeigt uns die Spanne des Fehlerbereichs für diese Gerade. Bei einer linearen Korrelation sollte diese Gerade den Häufungen in unserem Plot ungefähr folgen.

daten |>
    filter(q18_6 > 0 & 
           q18_7  > 0 ) |>
    ggplot(aes(x = q18_6 , 
               y = q18_7)) + 
        geom_jitter() +
        geom_smooth(method=lm)
Abbildung 18.7: Beispiel eines Jitter-Diagramms mit Ausgleichsgerade

Das folgende Beispiel zeigt eine Punktwolke, bei der die Wertepaare zufällig über den gesamten Wertebereich gestreut sind. In diesem Fall ist eine Korrelation kaum wahrscheinlich.

daten |>
    filter(q18_3 > 0 & 
           q18_29  > 0 ) |>
    ggplot(aes(x = q18_3 , 
               y = q18_29)) + 
        geom_jitter() +
        geom_smooth(method="lm")
Abbildung 18.8: Beispiel eines Jitter-Diagramms mit flacher Ausgleichsgerade

Im Beispiel ist die Ausgleichsgerade fast waagerecht. Wenn eine Ausgleichsgerade fast waagerecht ist, dann liegt in der Regel auch keine Korrelation vor.

Es gibt auch nicht-lineare Korrelationen. In diesem Fall sehen wir Häufungen in bestimmten Teilen unserer Punktwolken oder unsere Punkte folgen einer Kurve. Solche Korrelationen müssten einer entsprechenden “Ausgleichskurve” folgen. Eine solche Ausgleichskurve erzeugen wir mit loess als Ausgleichsmethode.

Wenn eine Ausgleichskurve fast gerade ist, dann sollten wir eine lineare Korrelation annehmen. Ein Beispiel für eine fast gerade Ausgleichskurve zeigt uns der nächste Plot.

daten |>
    filter(q18_3 > 0 & 
           q18_29  > 0 ) |>
    ggplot(aes(x = q18_3 , 
               y = q18_29)) + 
        geom_jitter() +
        geom_smooth(method = "loess")
Abbildung 18.9: Beispiel eines Jitter-Diagramms mit nicht linearer Ausgleichslinie

18.4 Mehrdimensionale Plots mit aes

18.4.1 Farbkodierung

Mit der Farbkodierung können zusätzliche Merkmale in einer Visualisierung kodiert werden. ggplot unterscheidet für die Farbkodierung zwischen diskreten und kontinuierlichen Daten. Bei diskreten Daten verwendet R Farben, die sich gut voneinander unterscheiden lassen. Bei kontinuierlichen Daten werden Farbverläufe zwischen mehreren Farben verwendet. Ausserdem hängt die Färbung von der Art der Visualisierung ab. Flächige Darstellungselemente, wie die Balken von Balkendiagrammen, wird eine Füllfarbe gesetzt. Die Füllfarbe wird über die Ästhetik fill kontrolliert. Darstellungselemente wie Linien oder Punkte wird eine Linienfarbe gesetzt. Die Linienfarbe wird über die Ästhetik colour festgelegt.

Merke

Die Färbung von Punkten wird über die Linienfarbe gesteuert.

iris |>
    ggplot(aes( x = Sepal.Length, 
                y = Sepal.Width, 
1                colour = Species)) +
        geom_point()
1
Farbliche Hervorhebung
Abbildung 18.10: Punktdiagramm der iris-Daten mit farblich hervorgehobenen Spezieswerten

Balkendiagramme und Histogramme benötigen eine Flächenfärbung.

iris |>
    ggplot(aes( x = Sepal.Length, 
1                fill = Species)) +
        geom_histogram()
1
Farbliche Hervorhebung
Abbildung 18.11: Histogramm der iris-Daten mit farblich hervorgehobenen Spezieswerten
Praxis

Wenn Histogramme oder Balkendiagramme eine zusätzliche farbliche Kodierung erhalten, verbirgt eine gestapelte Balkendarstellung die Verteilungen. Mit dem Parameter position lässt sich die Positionierung der Balken steuern. Dies wird beispielsweise durch die Funktion position_dodge() vereinfacht.

iris |>
    ggplot(aes( x = Sepal.Length, 
1                fill = Species)) +
2        geom_histogram(position = position_dodge())
1
Farbliche Hervorhebung
2
Positionierung der hervorgehobenen Balken
Abbildung 18.12: Histogramm der iris-Daten mit farblich hervorgehobenen Spezieswerten

Die Ästhetik kann auch in den Geometriefunktionen angepasst werden. Wird hier für die Farbästhetik jeweils ein einzelner Wert angegeben, erzeugt ggplot() einen Vektor mit diskreten Werten und weist die Farben dynamisch zu.

Darstellungsbereich |>
    ggplot(aes(x)) + 
        geom_line(stat = "function", 
                  fun = f1, 
1                  aes(colour = "f1(x) = x ^ 2 - 3 * x")) +
        geom_line(stat = "function", 
                  fun = f2, 
2                  aes(colour = "f2(x) = 4 * x + 2")) +
        labs(colour = "Funktion")
1
Farbliche Hervorhebung der ersten Funktion
2
Farbliche Hervorhebung der zweiten Funktion
Abbildung 18.13: Angepasste Ästhetik mit Einzelwerten in Geometriefunktionen
Warnung

ggplot unterstützt Farbcodes zur Konfiguration von Füll- und Linienfarben ausserhalb der normalen Ästhetikparameter. Mit diesen Farbcodes wird die normale Füll- oder Linienfarbe auf eine andere Farbe geändert. Diese Methode zur Anpassung von Farbe sollte vermieden werden, weil für solche Farben keine Legende erzeugt wird.

18.4.2 Grössenkodierung

Merke

Die Grössenkodierung eignet sich am Besten für kontinuierliche Daten.

Merke

Die Grössenkodierung lässt sich auf Linien oder Punkte anwenden. Flächen lassen sich nicht zusätzlich grössenkodieren, weil sie bereits Werte über die Grösse kodieren.

Die Grössenkodierung von Punkten erfolgt über die Ästhetik size. Auf diese Weise werden Bubble-Charts (Blasendiagramme) erstellt.

read_csv("geschlechter_schweizer_staedte.csv") -> 
    geschlechteranteile_ch

geschlechteranteile_ch |>
    ggplot(aes(x = S, y = N, size = Gesamt)) + 
        geom_point() +
        xlab("Männeranteil der ständigen Wohnbevölkerung") +
        ylab("Manneranteil der nicht-ständigen Wohnbevölkerung")
Abbildung 18.14: Grössenkodierung am Beispiel des Männeranteils in Schweizer Städten

Die Grössenkodierung von Linien erfolgt über die Ästhetik linewidth. Die Linienbreite funktioniert analog zur Punktgrösse im Punktdiagramm.

Merke

Die Ästhetik size wird in Kombination mit geom_point(), geom_text() oder geom_label() verwendet.

Die Ästhetik linewidth wird in Kombination mit geom_line() verwendet.

18.4.3 Formkodierung

Die Formkodierung kodiert die Werte einer Variable über die Form (engl. shape).

Merke

Die Formkodierung eignet sich nur für diskrete Daten!

Merke

Die Formkodierung kann nur ein Punkt- oder Jitter-Diagramm ergänzen.

Die Formkodierung erfolgt über die Ästhetik shape.

mtcars |> 
    mutate(am = am |> factor()) |>
    ggplot(aes(
        x = mpg, 
        y = hp, 
1        shape = am
    )) + 
    geom_point()
1
Formkodierung über das Merkmal am.
Abbildung 18.15: Anwendung von facet_wrap()

Eine Variante der Formkodierung ist die Linienart. Die Kodierung der Linienart erfolgt äber die Ästhetik linetype. Diese Formatierung prinzipiell mit allen Diagrammentypen verwendet werden, die Linien darstellen. Für Boxplots oder Balkendiagramme sollte eine Kodierung über die Linienart vermieden werden.

iris |>
    ggplot(aes(x = Sepal.Length, 
               y = Sepal.Width, 
               linetype = Species)) +
        geom_point() +
        geom_smooth(method = "lm")
`geom_smooth()` using formula = 'y ~ x'
Abbildung 18.16: Kodierung über Linienarten

Eine weitere Variante der Formkodierung sind Textmarkierungen. Textmarkierungen werden über die Ästhetik label zugewiesen. Für eine Textmarkierung wird der Wert des gewählten Merkmals im Diagramm angezeigt.

geschlechteranteile_ch |>
    ggplot(aes(x = S, y = N, label = Ort)) +
        geom_text() +
        xlab("Männeranteil der ständigen Wohnbevölkerung") +
        ylab("Manneranteil der nicht-ständigen Wohnbevölkerung")
Abbildung 18.17: Textmarkierungen über den Männeranteil an der ständigen und nicht-ständigen Wohnbevölkerung Schweizer Städte

18.4.4 Facetted Plots

Ein Facetted Plot gliedern die Darstellung von Werten in mehrere Teildiagramme. Diese Teildiagramme enthalten in der Regel nur die Werte

Merke

Facetten können nur mit diskreten Daten erstellt werden!

Facetten sind keine Ästhetik, sondern eine Steuerung.

mtcars |> 
    ggplot(aes(mpg, hp)) + 
    geom_point() +
1    facet_wrap(~ gear)
1
Facetten folgen den Werten des Merkmals gear.
Abbildung 18.18: Anwendung von facet_wrap()

Eine Variante von facet_wrap() ist facet_grid(). Diese Funktion erstellt eine visuelle Matrix entlang der Werte zweier diskreter Merkmale.

mtcars |> 
    ggplot(aes(mpg, hp)) + 
    geom_point() +
1    facet_grid(carb ~ gear)
1
Facetten über die Werte der Merkmale gear (horizontal) und carb (vertikal).
Abbildung 18.19: Anwendung von facet_grid()

18.5 Spezielle Visualisierungen

18.5.1 Donut-Diagramme

Wichtig

Tortendiagramme und Donut-Diagramme werden oft falsch interpretiert, weil Kreisflächen schwerer verglichen werden können als die Höhen von Balken. Sie sollten nur zur Illustration, aber nie zur Argumentation verwendet werden.

R kann auch Plots erstellen, die nur einen Datenvektor umfassen. In diesem Fall wird der zweite Vektor für die y-Achse aus den Werten des Vektors berechnet. Diese Möglichkeit haben wir schon bei der Erstellung von Histogrammen kennengelernt.

Nehmen wir das folgende Beispiel: Wir erstellen ein Stichprobenobjekt mit einem Vektor q00_demo_gen, der die Werte 1 : Keine Angabe, 2 : Weiblich und 3 : Männlich enthält.

daten2 = tibble(
    q00_demo_gen = c("2 : Weiblich", "2 : Weiblich", "3 : Männlich", 
"2 : Weiblich", "2 : Weiblich", "2 : Weiblich", "2 : Weiblich", 
"2 : Weiblich", "2 : Weiblich", "3 : Männlich", "3 : Männlich", 
"3 : Männlich", "3 : Männlich", "2 : Weiblich", "2 : Weiblich", 
"3 : Männlich", "3 : Männlich", "2 : Weiblich", "3 : Männlich", 
"2 : Weiblich", "2 : Weiblich", "2 : Weiblich", "2 : Weiblich", 
"3 : Männlich", "2 : Weiblich", "3 : Männlich", "2 : Weiblich", 
"3 : Männlich", "3 : Männlich", "2 : Weiblich", "2 : Weiblich", 
"3 : Männlich", "2 : Weiblich", "3 : Männlich", "2 : Weiblich", 
"3 : Männlich", "2 : Weiblich", "2 : Weiblich", "3 : Männlich", 
"2 : Weiblich", "2 : Weiblich", "2 : Weiblich", "2 : Weiblich", 
"3 : Männlich", "3 : Männlich", "2 : Weiblich", "2 : Weiblich", 
"3 : Männlich", "3 : Männlich", "2 : Weiblich", "3 : Männlich", 
"3 : Männlich", "2 : Weiblich", "2 : Weiblich", "2 : Weiblich", 
"3 : Männlich", "2 : Weiblich", "3 : Männlich", "3 : Männlich", 
"3 : Männlich", "2 : Weiblich", "3 : Männlich", "3 : Männlich", 
"2 : Weiblich", "2 : Weiblich", "3 : Männlich", "2 : Weiblich", 
"2 : Weiblich", "2 : Weiblich", "2 : Weiblich", "3 : Männlich", 
"3 : Männlich", "3 : Männlich", "2 : Weiblich", "3 : Männlich", 
"3 : Männlich", "3 : Männlich", "3 : Männlich", "3 : Männlich", 
"3 : Männlich", "3 : Männlich", "3 : Männlich", "2 : Weiblich", 
"3 : Männlich", "2 : Weiblich", "2 : Weiblich", "2 : Weiblich", 
"2 : Weiblich", "3 : Männlich", "3 : Männlich", "3 : Männlich", 
"3 : Männlich", "3 : Männlich", "3 : Männlich", "2 : Weiblich", 
"2 : Weiblich", "3 : Männlich", "3 : Männlich", "2 : Weiblich", 
"3 : Männlich", "3 : Männlich", "2 : Weiblich", "2 : Weiblich", 
"2 : Weiblich", "3 : Männlich", "3 : Männlich", "2 : Weiblich", 
"2 : Weiblich", "2 : Weiblich", "2 : Weiblich", "2 : Weiblich", 
"2 : Weiblich", "2 : Weiblich", "2 : Weiblich", "3 : Männlich", 
"3 : Männlich", "2 : Weiblich", "3 : Männlich", "2 : Weiblich", 
"3 : Männlich", "3 : Männlich", "3 : Männlich", "3 : Männlich", 
"3 : Männlich", "3 : Männlich", "3 : Männlich", "3 : Männlich", 
"2 : Weiblich", "3 : Männlich", "3 : Männlich", "2 : Weiblich", 
"3 : Männlich", "3 : Männlich", "2 : Weiblich", "3 : Männlich", 
"2 : Weiblich", "3 : Männlich", "2 : Weiblich", "2 : Weiblich", 
"3 : Männlich", "2 : Weiblich", "3 : Männlich", "3 : Männlich", 
"2 : Weiblich", "3 : Männlich", "3 : Männlich", "3 : Männlich", 
"3 : Männlich", "2 : Weiblich", "3 : Männlich", "2 : Weiblich", 
"2 : Weiblich", "3 : Männlich", "2 : Weiblich", "2 : Weiblich", 
"3 : Männlich", "2 : Weiblich", "3 : Männlich", "3 : Männlich", 
"3 : Männlich", "2 : Weiblich", "3 : Männlich", "2 : Weiblich", 
"2 : Weiblich", "3 : Männlich", "2 : Weiblich", "2 : Weiblich", 
"3 : Männlich", "2 : Weiblich", "3 : Männlich", "3 : Männlich", 
"2 : Weiblich", "3 : Männlich", "3 : Männlich", "3 : Männlich", 
"3 : Männlich", "2 : Weiblich", "2 : Weiblich", "2 : Weiblich", 
"2 : Weiblich", "1 : Keine Angabe", "3 : Männlich", "3 : Männlich", 
"2 : Weiblich", "2 : Weiblich", "2 : Weiblich", "2 : Weiblich", 
"3 : Männlich", "3 : Männlich", "3 : Männlich", "3 : Männlich", 
"3 : Männlich", "3 : Männlich", "3 : Männlich", "3 : Männlich", 
"2 : Weiblich", "3 : Männlich", "2 : Weiblich", "3 : Männlich", 
"2 : Weiblich")
)

Uns interessiert nun: Wie oft kommen die drei möglichen Werte in unserer Stichprobe vor?

Wir können die Werte mit count() selbst berechnen oder ggplot die Arbeit überlassen. Anstelle der geom_col()-Funktion verwenden wir nun die geom_bar()-Funktion. geom_bar() erwartet einen Vektor für die x-Achse und berechnet für die y-Achse das Auftreten der Werte, so wie wir es mit der count()-Funktion auch bestimmen würden.

daten2 |>
    count(q00_demo_gen)
# A tibble: 3 × 2
  q00_demo_gen         n
  <chr>            <int>
1 1 : Keine Angabe     1
2 2 : Weiblich        95
3 3 : Männlich       104
daten2 |>
    ggplot(aes(x = q00_demo_gen)) +
        geom_bar()

Mit diesem Plot können wir die Unterschiede in unserer Werteverteilung leichter erkennen.

Für Präsentationen ist so ein Plot aber nicht wahnsinnig attraktiv. Färben wir den Plot also ein. Das machen wir, indem wir den Vektornamen auch für die Füllung der Balken verwenden. ggplot wählt nun für jeden Wert in diesem Vektor eine eigene Farbe aus. Dadurch färben sich unsere Balken ein.

daten2 |>
    ggplot(aes(x=q00_demo_gen, fill = q00_demo_gen)) +
        geom_bar()

Für Histogramme verwenden wir normalerweise ein kartesisches Koordinatensystem. Wir können aber auch ein anderes Koordinatensystem wählen. Eine Variante sind polare Koordinaten. Mit einem polaren Koordinatensystem erreichen wir kreisförmige Darstellungen. Wir müssen dazu die Dimension, die auf das Zentrum des Diagramms zeigt, festlegen und als Parameter übergeben. In unserem Fall ist das die y-Dimension.

Wir stellen unsere Daten in einem polaren Koordinatensystem dar, indem wir mit der coord_polar()-Funktion ggplot mitteilen, dass wir ein anderes Koordinatensystem wünschen.

daten2 |>
    ggplot(aes(x=q00_demo_gen, fill = q00_demo_gen)) +
        geom_bar() +
        coord_polar("y") 

Unser Plot hat jetzt unschöne Beschriftungen. Die werden wir mit einem Formatierungsthema los. ggplot hat verschiedenen Formatierungen als Thema vordefiniert. Eines davon ist das Thema void. Diese Formatierung entfernt alle Hintergründe, Achsen und Beschriftungen ausser Legenden.

daten2 |>
    ggplot(aes(x=q00_demo_gen, fill = q00_demo_gen)) +
        geom_bar() +
        coord_polar("y") +
        theme_void()

Das sieht doch gleich viel besser aus.

Hinweis

Solche ringartigen Visualisierungen werden als Zielscheiben- oder Donut-Diagramme bezeichnet.

18.5.2 Torten-Diagramme

Für Torten- bzw. Kreisdiagramme müssen alle Balken eines Balkendiagramms übereinander gestapelt werden. Das erreichen wir, indem wir für die x-Achse einen konstanten Wert angeben. Z.B. nehmen wir dazu die leere Zeichenkette. So werden merkwürdige Beschriftungen im Diagramm vermieden. Damit wir die Balken auseinanderhalten können, färben wir sie ein.

daten2 |>
    ggplot(aes(x ="", fill = q00_demo_gen)) +
        geom_bar() 

Mit der Funktion coord_flip werden die Achsen vertauscht und das Diagramm gedreht.

daten2 |>
    ggplot(aes(x ="", fill = q00_demo_gen)) +
        geom_bar() +
        coord_flip()

Wir erkennen nun deutlich, dass ggplot immer versucht möglichst viel Fläche zu nutzen.

Das Interessante an dieser Darstellung ist aber nicht dieses Format, sondern dass wir dieses Diagramm ebenfalls in einem polaren Koordinatensystem darstellen können.

daten2 |>
    ggplot(aes(x ="", fill = q00_demo_gen)) +
        geom_bar() +
        coord_polar("y") + 
        theme_void()

Auf diese Weise erzeugen wir Tortendiagramme.