---
title: "Vorlesung 3: tidyverse & Abbildungen (Teil 1)"
author: "Jonathan Harrington / Johanna Cronenberg"
date: "April 2021"
output: 
  html_document:
    number_sections: TRUE
    toc: true
    theme: flatly
    highlight: pygments
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
```

```{r klippy, echo=FALSE, include=TRUE}
klippy::klippy(position = c('top', 'right'))
```

<style>
div.green {background-color: #ecffeb; border-radius: 5px; padding: 20px;}
div.gray {background-color: #e8e8e8; border-radius: 5px; padding: 20px;}
</style>

# Packages und Daten laden

Starten Sie das R Projekt, das Sie für diesen Kurs angelegt haben. Öffnen Sie hierfür RStudio und benutzen Sie die Schaltfläche oben rechts oder navigieren Sie zu Ihrem Kursverzeichnis und klicken Sie auf die `.Rproj` Datei. 

Laden Sie dann die folgenden Packages:

```{r}
library(tidyverse)
library(magrittr)
```

Wir werden diese Woche mit verschiedenen Data Frames arbeiten, die wir vom IPS-Server laden. Die URL legen wir als Variable an und benutzen diese dann in der Funktion `file.path()`.

```{r}
url <- "http://www.phonetik.uni-muenchen.de/~jmh/lehre/Rdf"
asp <- read.table(file.path(url, "asp.txt"))
int <- read.table(file.path(url, "intdauer.txt"))
coronal <- read.table(file.path(url, "coronal.txt"))
vdata <- read.table(file.path(url, "vdata.txt"))
```

# Summary Statistics

Wenn man sich einen Überblick über Daten verschaffen möchte, sind sogenannte *summary statitics* (deskriptive Statistiken) häufig hilfreich. Zu solchen deskriptiven Werten zählen z.B. das arithmetische Mittel (Mittelwert), Median, Varianz, Standardabweichung, Minimum, Maximum, usw. Hier zeigen wir zunächst wie man solche Werte ohne Funktionen aus dem *tidyverse* berechnen kann. Da R eine Statistik-Software ist, sind solche Basis-Funktionen wie zur Berechnung des Mittelwerts immer verfügbar. Im Folgenden demonstrieren wir die wichtigsten Funktionen zur Berechnung von *summary statistics* anhand der F1-Werte in `vdata`:

```{r}
mean(vdata$F1)             # arithmetisches Mittel
median(vdata$F1)           # Median
var(vdata$F1)              # Varianz
sd(vdata$F1)               # Standardabweichung
min(vdata$F1)              # Minimum
max(vdata$F1)              # Maximum
range(vdata$F1)            # Minimum & Maximum
quantile(vdata$F1, 0.25)   # 1. Quartil
quantile(vdata$F1, 0.75)   # 3. Quartil
IQR(vdata$F1)              # interquartiler Bereich
```

## Mittelwert & Median

Das arithmetische Mittel wird berechnet, indem man die Summe einer Anzahl $n$ an Zahlen bildet, und diese Summe dann durch die Anzahl $n$ teilt. Hier ist ein sehr einfaches Beispiel:

```{r}
zahlen <- 1:5
summe <- sum(zahlen)
summe
anzahl <- length(zahlen)
anzahl
# Mittelwert:
summe/anzahl
# zum Vergleich:
mean(zahlen)
```

Der Median hingegen ist die mittig liegende Zahl in einer sortierten Zahlenreihe. Nehmen wir wieder obiges Beispiel (die Zahlen sind bereits aufsteigend sortiert):

```{r}
zahlen
median(zahlen)
```

Bei einer geraden Anzahl von Zahlen berechnet man den Median als den Mittelwert der zwei mittig liegenden Werte, zum Beispiel:

```{r}
zahlen <- 1:6
median(zahlen)
mean(c(3, 4))
```

Der Median ist robuster gegen sogenannte Ausreißer (engl. *outlier*) als der Mittelwert. Ausreißer sind Datenpunkte, die deutlich extremer sind als die Mehrheit der Datenpunkte. Hier wieder ein einfaches Beispiel:

```{r}
zahlen <- c(1:5, 100)
zahlen
mean(zahlen)
median(zahlen)
```

Die Zahl 100 ist ganz offensichtlich ein Ausreißer im Vektor `zahlen`. Der Mittelwert ist wegen dieses Ausreißers jetzt um ein Vielfaches höher als vorher, während der Median sich nur leicht verändert hat.

## Varianz & Standardabweichung

Varianz und Standardabweichung sind verwandte Maße für die Streuung von Werten um ihren Mittelwert. Genauer gesagt ist die Varianz die Summe der quadrierten Abweichungen der Messwerte von ihrem Mittelwert geteilt durch die Anzahl der Messwerte minus 1, während die Standardabweichung die Quadratwurzel der Varianz ist. Am folgenden Beispiel können Sie nachvollziehen, wie man die Varianz und Standardabweichung "händisch" berechnet:

```{r}
zahlen <- c(12, 6, 24, 3, 17)
# Mittelwert
m <- mean(zahlen)
m
# quadrierte Abweichungen
quadr_abw <- (zahlen - m)^2
quadr_abw
# Anzahl der Messwerte
n <- length(zahlen)
n
# Summe der quadrierten Abweichungen
summe <- sum(quadr_abw)
summe
# Varianz:
varianz <- summe / (n - 1)
varianz
# Mit der Funktion var():
var(zahlen)
```

Um jetzt die Standardabweichung daraus zu berechnen, die in der Statistik viel häufiger verwendet wird als die Varianz, brauchen wir nur noch die Quadratwurzel aus der Varianz zu ziehen:

```{r}
std_abw <- sqrt(varianz)
std_abw
# oder mit sd()
sd(zahlen)
```

## Quantile

Ein Quantil teilt Datenpunkte so auf, dass ein bestimmter Teil der Datenpunkte unterhalb des Quantils liegen. Quantil ist ein Überbegriff; je nachdem in wie viele Stücke man die Datenpunkte aufteilt, sagt man auch Perzentil (100 Stücke) oder Quartil (4 Stücke). Der Median ist ebenfalls ein Quantil, denn 50% der Daten liegen immer unter dem Median. In R berechnet die Funktion `quantile()` die Quantile. Die Funktion bekommt zuerst die Datenpunkte (also einen numerischen Vektor) und anschließend die Proportion der Datenpunkte, die unter dem zu berechnenden Wert liegen soll. Wichtige Quantile sind das erste und dritte Quartil, also die Schwellwerte, unter denen ein Viertel bzw. drei Viertel aller Datenpunkte liegen. 

```{r}
quantile(vdata$F1, 0.25)   # 1. Quartil
quantile(vdata$F1, 0.75)   # 3. Quartil
IQR(vdata$F1)              # interquartiler Bereich
```

Die Differenz zwischen dem ersten und dritten Quartil wird auch interquartiler Bereich oder Interquartilsabstand (*interquartile range*) genannt und kann mit der Funktion `IQR()` berechnet werden.

## Beispiel Boxplot

Ein Boxplot enthält viele der deskriptiven Informationen, die wir bis jetzt behandelt haben:

- Median: Der Strich innerhalb der Box ist der Median.
- Box: Die Box umfasst die mittleren 50% aller Datenpunkte. Das untere Ende der Box ist das erste Quartil (Q1), das obere Ende ist das dritte Quartil (Q3). Das heißt die Box ist genauso groß wie der Interquartilsabstand.
- Whiskers: Die Whiskers erstrecken sich vom Q1 und vom Q3 aus zu dem niedrigsten/höchsten Datenpunkt, der innerhalb von `1.5 * IQR` liegt. Diese Berechnung der Länge der Whiskers als `1.5 * IQR` gilt für Boxplots, die mit `ggplot2` erstellt wurden, aber nicht jeder Boxplot wird so berechnet.
- Punkte: Ausreißer, also alle restlichen Datenpunkte, die nicht in der Box und den Whiskers enthalten sind.

Hier sehen Sie den Boxplot für `F1` aus dem Data Frame `vdata`:

![](img/boxplot.png)

Wie man diesen Boxplot erstellt, erfahren Sie später in dieser Vorlesung.

# Daten manipulieren mit `dplyr` (Fortsetzung)

## Grouping & Summarising

Zu Beginn dieser Vorlesung haben wir *summary statistics* für F1-Werte aus dem Data Frame `vdata` berechnet. Natürlich geht das auch innerhalb der *tidyverse*-Syntax, nämlich mit der Funktion `summarise()` aus dem Package `dplyr`. Diese Funktion verändert den Data Frame grundlegend, denn die ursprünglichen Daten werden zu neuen Werten zusammengefasst. Dies betrifft sowohl die Anzahl der Spalten als auch der Anzahl der Zeilen. `summarise()` erstellt neue Spalten und keine der originalen Spalten werden beibehalten. Die Funktion bekommt als Argument also den/die neuen Spaltennamen und wie die Werte in dieser neuen Spalte berechnet werden sollen:

```{r}
vdata %>% summarise(mittelwert = mean(F1))
```

Der Output dieser Pipe ist ein Data Frame mit nur einer Spalte und einer Zeile. Wir können aber auch mehrere deskriptive Werte gleichzeitig berechnen und erhalten dadurch mehr Spalten:

```{r}
vdata %>% summarise(mittelwert = mean(F1),
                    std_abw = sd(F1),
                    summe = sum(F1),
                    maximum = max(F1),
                    Q1 = quantile(F1, 0.25))
```

Die Funktionen `mutate()` und `summarise()` haben also gemein, dass sie neue Spalten erstellen; während in `mutate()` aber alle ursprünglichen Zeilen und Spalten erhalten bleiben, erstellt `summarise()` einen ganz neuen Data Frame mit deutlich weniger Zeilen als ursprünglich vorhanden waren (denn hier wurden Werte *zusammengefasst*).

Was würden Sie jetzt tun, wenn Sie den F1-Mittelwert für nur einen bestimmten Vokal `V` aus dem Data Frame berechnen wollen? Vermutlich würden Sie dies wie folgt lösen (für den Vokal `V == "E"`):

```{r}
vdata %>% 
  filter(V == "E") %>% 
  summarise(mittelwert = mean(F1))
```

Der F1-Mittelwert für "E" ist also ca. 426 Hz. Wenn Sie sich für die vokalspezifischen F1-Mittelwerte interessieren, dann ist es nicht mehr sinnvoll, für jeden einzelnen Vokal den obigen Code zu benutzen. Stattdessen gibt es die Funktion `group_by()`. `group_by()` bekommt als Argumente alle Spalten, nach denen gruppiert werden soll. `summarise()` berechnet die gewünschten *summary statistics* anschließend **pro Gruppe**. In unserem Beispiel gruppieren wir nach Vokal und berechnen dann den Mittelwert pro Vokal:

```{r}
vdata %>% 
  group_by(V) %>% 
  summarise(mittelwert = mean(F1))
```

Es wurden zwei Spalten erstellt: Die eine enthält die sieben verschiedenen Vokale aus dem originalen Data Frame, die andere die vokalspezifischen F1-Mittelwerte. Sie können natürlich auch nach mehr als einer Spalte gruppieren. Es ist zum Beispiel anzunehmen, dass sich der mittlere F1 nicht nur von Vokal zu Vokal unterscheidet, sondern dass auch der Gespanntheitsgrad `Tense` einen Einfluss hat. Deshalb gruppieren wir nach Vokal und Gespanntheitsgrad und berechnen dann den mittleren F1:

```{r}
vdata %>% 
  group_by(V, Tense) %>% 
  summarise(mittelwert = mean(F1))
```

Wir sehen jetzt also den F1-Mittelwert für nicht gespannte "%", gespannte "%" (ignorieren Sie die seltsame Vokal-Kodierung), nicht gespannte "A", gespannte "A", usw.

<div class="gray">
**Weiterführende Infos: `summarise()` warning**

Oben sehen Sie eine Warnmeldung, die von `summarise()` geworfen wurde. Warnmeldungen sind dazu da, Sie auf etwas aufmerksam zu machen -- Sie sollten sie also nicht ignorieren. Diese Warnmeldung zeigt erstmal an, dass das Ergebnis des Codes ein gruppierter Data Frame ist (Objektklasse `grouped_df`) und dass die Gruppierungsvariable `V` ist:

```{r}
vdata %>% 
  group_by(V, Tense) %>% 
  summarise(mittelwert = mean(F1)) %>% 
  class()
```

Die Warnmeldung zeigt außerdem, dass man die Gruppierung des Ergebnisses auch verändern kann, indem man das `summarise()`-Argument `.groups` verwendet. Dieses Argument kann verschiedene Werte annehmen, wie Sie auf der Hilfsseite der Funktion `summarise()` nachlesen können.

Bei den vorherigen Code Snippets, bei denen wir `group_by()` im Zusammenspiel mit `summarise()` verwendet haben, ist die Warnmeldung übrigens deshalb nicht aufgetaucht, weil wir nur nach einer Variable gruppiert haben; im Ergebnis wird diese Gruppierung automatisch aufgehoben.
</div>

Es ist wichtig zu verstehen, dass nur nach kategorialen Spalten gruppiert werden kann. Es ergibt keinen Sinn, nach nicht-kategorialen numerischen Spalten zu gruppieren, denn hier gibt es keine Gruppen (jeder Wert ist vermutlich einzigartig). Der Sinn von `summarise()` ist es aber ja gerade, deskriptive Statistiken für kategoriale Gruppen zu berechnen.

Zuletzt wollen wir noch die Funktionen `n()` und `n_distinct()` vorstellen. `n()` benötigt keine Argumente und wird nach `group_by()` innerhalb `summarise()` verwendet, um die Anzahl an Beobachtungen (Zeilen) pro Gruppe zurückzugeben. `n_distinct()` bekommt als Argument den Namen einer Spalte und findet heraus, wie viele unterschiedliche (einzigartige) Werte einer Variable es pro Gruppe gibt.

```{r}
# Anzahl an Zeilen für jede Kombination von V und Tense
vdata %>% 
  group_by(V, Tense) %>% 
  summarise(count = n())
# Anzahl der einzigartigen Sprecher pro Region und sozialer Klasse
coronal %>% 
  group_by(Region, Socialclass) %>% 
  summarise(count = n_distinct(Vpn))
```

<div class="gray">
**Weiterführende Infos: Funktionen eindeutig beschreiben**

Da die Funktionen aus dem *tidyverse*, insbesonderen aus `dplyr`, sehr gängige Namen haben (`filter()`, `summarise()`, `rename()`), werden sie leicht von Funktionen mit demselben Namen aus anderen Paketen maskiert. Wenn Sie also von einer dieser Funktionen einen Fehler bekommen, laden Sie entweder noch einmal das Paket, aus dem die Funktion stammen soll (z.B. `library(dplyr)`), oder nutzen Sie die folgende Schreibweise: `dplyr::filter()`.

</div>

## Arranging

In der alltäglichen Arbeit mit Data Frames kann es sinnvoll sein, den Data Frame nach Zeilen oder Spalten zu ordnen. Für das Ordnen der Zeilen wird `arrange()` benutzt, für das Ordnen der Spalten `relocate()`. Hier ordnen wir den Data Frame `int` aufsteigend nach Dauer:

```{r}
int %>% arrange(Dauer)
```

`arrange()` kann auch alphabetisch oder nach mehreren Spalten ordnen:

```{r}
int %>% arrange(Vpn, Dauer)
```

Um absteigend zu ordnen, wird `desc()` (*descending*) innerhalb von `arrange()` genutzt:

```{r}
int %>% arrange(Vpn, desc(Dauer))
```

`relocate()` bekommt als Argumente die Namen aller Spalten, die umsortiert werden sollen. Wenn sonst keine weiteren Argumente angegeben werden, werden die Spalten an den Anfang des Data Frames gesetzt. Ansonsten können die Argumente `.before` und `.after` verwendet werden, um anzugeben, vor oder nach welche Spalten die anderen Spalten gesetzt werden sollen:

```{r}
vdata %>% slice(1)
vdata %>% relocate(Subj) %>% slice(1)
vdata %>% relocate(Subj, Cons) %>% slice(1)
vdata %>% relocate(where(is.numeric), .after = Subj) %>% slice(1)
vdata %>% relocate(where(is.character), .before = dur) %>% slice(1)
```

# Daten abbilden mit `ggplot2`

[`ggplot2`](https://ggplot2.tidyverse.org/) ist eine Library aus dem `tidyverse`, die Ihnen sehr viele Möglichkeiten für die Visualisierung von Daten liefert. `gg` steht für *grammar of graphics*. Der Befehl, mit dem Sie eine Abbildung beginnen, ist `ggplot()`; das Hauptargument dieser Funktion ist der gewünschte Data Frame. Dann fügt man das sog. *aesthetic mapping* mittels `aes()`, sowie Funktionen für die Art der Abbildung, die Beschriftungen, die Legende, etc., hinzu. Jede Funktion wird mit `+` verbunden (nicht mit Pipes!).

## Boxplots

Boxplots sind die wohl wichtigsten wissenschaftlich genutzten Abbildungen. In R werden sie mit dem Befehl [`geom_boxplot()`](https://ggplot2.tidyverse.org/reference/geom_boxplot.html) erstellt. Zuerst zeigen wir, wie der oben verwendete Boxplot erstellt wurde. Die Funktion `ggplot()` bekommt den Data Frame `vdata`. In den *aesthetic mappings* `aes()` tragen wir ein, dass F1 auf der y-Achse aufgetragen werden soll. Zuletzt bestimmen wir noch, dass ein Boxplot gezeichnet werden soll.

```{r}
ggplot(vdata) + 
  aes(y = F1) + 
  geom_boxplot()
```

Zugegeben, der Boxplot sieht ein bisschen anders aus als der Boxplot oben. Wie man diesen Plot "verschönert", lernen Sie nächste Woche. Boxplots eignen sich sehr gut zum Vergleichen von Werten für verschiedene kategoriale Gruppen. Dann werden diese Gruppen (üblicherweise) auf der x-Achse aufgetragen und auf der y-Achse wieder die gewünschten Werte. Hier sehen Sie ein Beispiel für die Dauer verschiedener Konsonanten aus dem Data Frame `asp`:

```{r}
ggplot(asp) +
  aes(x = Kons, y = d) +
  geom_boxplot()
```

Boxplots können auch horizontal erstellt werden (wobei das meist weniger übersichtlich ist). Dann werden die Kategorien auf der y-Achse und die Werte auf der x-Achse aufgetragen:

```{r}
ggplot(asp) +
  aes(x = d, y = Kons) +
  geom_boxplot()
```

Manchmal ist ein sogenannter *Notch* gewünscht; dafür nutzen wir das Argument `notch = TRUE` in der Funktion `geom_boxplot()` (und ggf. `notchwidth`, um die Tiefe des Notches anzupassen):

```{r}
ggplot(asp) +
  aes(x = Kons, y = d) +
  geom_boxplot(notch = TRUE)
ggplot(asp) +
  aes(x = Kons, y = d) +
  geom_boxplot(notch = TRUE, notchwidth = 0.3)
```

<div class="gray">
**Weiterführende Infos: Aesthetic mappings & Piping Data Frames**

Streng genommen sind die *aesthetic mappings* immer ein Argument der Funktion, die über die Art des Plots bestimmt (also z.B. `geom_boxplot()`). Später werden Sie feststellen, dass manche Plots bestimmte *aesthetic mappings* benötigen bzw. zulassen, die andere Plots nicht verarbeiten können. Wir lagern die *aesthetic mappings* in den allermeisten Fällen aus der Plot-Funktion aus, weil das übersichtlicher ist. Es steht Ihnen aber frei, die *aesthetic mappings* in die Funktion als Argument reinzuschreiben:

```{r}
ggplot(asp) +
  geom_boxplot(aes(x = Kons, y = d), 
               notch = TRUE, 
               notchwidth = 0.3)
```

Innerhalb eines `ggplot` werden die einzelnen Funktion immer und ausschließlich mit einem Pluszeichen verbunden. Der Data Frame allerdings kann mit einer einfachen Pipe an `ggplot()`übergeben werden:

```{r}
asp %>%
ggplot() +
  aes(x = Kons, y = d) +
  geom_boxplot()
```

Das ist besonders hilfreich, wenn Sie vor dem Plotten erst noch weitere Funktionen auf den Data Frame anwenden wollen, bevor sie die daraus entstehenden Daten plotten. Hier filtern wir zum Beispiel zuerst nach Betonung, bevor wir anschließend nur noch die Dauer der betonten Wörter plotten:

```{r}
asp %>%
  filter(Bet == "be") %>% 
  ggplot() + 
  aes(x = Kons, y = d) +
  geom_boxplot()
```

</div>

## Scatter- & Lineplots

Scatterplots werden mit den Funktionen [`geom_point()`](https://ggplot2.tidyverse.org/reference/geom_point.html) und/oder [`geom_line()`](https://ggplot2.tidyverse.org/reference/geom_path.html) erstellt. Man kann auch beide Funktionen gleichzeitig verwenden. Auf die x- und y-Achse werden üblicherweise nur numerisch-kontinuierliche Daten aufgetragen. Im Folgenden plotten wir zum Beispiel Lautstärke in Dezibel gegen Dauer.

```{r}
# Punkte:
ggplot(int) +
  aes(x = Dauer, y = dB) +
  geom_point() 

# Linie:
ggplot(int) +  
  aes(x = Dauer, y = dB) + 
  geom_line()

# Beides:
ggplot(int) +
  aes(x = Dauer, y = dB) + 
  geom_line() + 
  geom_point()
```

Manchmal ist es hilfreich, vertikale oder horizontale [Referenzlinien](https://ggplot2.tidyverse.org/reference/geom_abline.html) in einem Plot einzuzeichnen. Horizontale Linien werden mit `geom_hline()` erzeugt, vertikale gerade Linien mit `geom_vline()`. Um eine horizontale Linie zu zeichnen, muss bekannt sein, an welcher Stelle die Linie die y-Achse schneidet. Deshalb bekommt `geom_hline()` immer das Argument `yintercept`. Bei `geom_vline()` muss mit `xintercept` die Schnittstelle der vertikalen Linie mit der x-Achse eingetragen werden. Wir fügen zum obigen Scatterplot zwei gerade Linien hinzu:

```{r}
ggplot(int) +
  aes(x = Dauer, y = dB) +
  geom_point() + 
  geom_vline(xintercept = 150) + 
  geom_hline(yintercept = 35)
```

## Barplots

Eine weitere wichtige Abbildungsform sind Barplots, die mit [`geom_bar()`](https://ggplot2.tidyverse.org/reference/geom_bar.html) erzeugt werden. Dabei darf nur entweder `x` oder `y` in den *aesthetic mappings* verwendet werden. Das liegt daran, dass auf die jeweils andere Achse grundsätzlich ein *count* oder eine Proportion aufgetragen wird, die von `ggplot` berechnet wird. Der folgende Plot zeigt zum Beispiel, wie viele Vorkommnisse dreier Regionen im Data Frame `coronal` zu finden sind.

```{r}
ggplot(coronal) +
  aes(x = Region) +
  geom_bar()
```

Die Balken können wir auch horizontal plotten, indem wir in den *aesthetic mappings* `y` statt `x` angeben:

```{r}
ggplot(coronal) +
  aes(y = Region) +
  geom_bar()
```

Die Werte der Balken können Sie ganz einfach nachvollziehen, indem Sie sich die Anzahl der Vorkommnisse der drei Regionen mittels der Funktion `table()` anzeigen lassen:

```{r}
table(coronal$Region)
```

Beim Barplot können Sie aber wie z.B. beim Boxplot noch eine weitere (kategoriale) Variable plotten. Die zweite Variable, die abgebildet werden soll, wird mit dem Argument `fill` angegeben, das die Levels der Variable als Füllfarben darstellt. Sie werden nächste Woche u.a. lernen, wie man Farben selbst bestimmen kann. Im Folgenden sieht man, wie häufig die Frikative `Fr` "s" (rot) und "sh" (blau) jeweils in den drei Regionen produziert wurden.

```{r}
ggplot(coronal) +
  aes(x = Region, fill = Fr) +
  geom_bar()
```

Lassen Sie uns mittels der zuvor gelernten Funktionen für Grouping und Summarising die Werte in diesem Plot nachvollziehen. Dafür gruppieren wir nach Region und Frikativ und lassen uns dann mit `n()` innerhalb von `summarise()` die Anzahl der Zeilen im Data Frame pro Gruppenkombination bestimmen.

```{r}
coronal %>% 
  group_by(Region, Fr) %>% 
  summarise(count = n())
```

Die Funktion `geom_bar()` kann als Argument noch `position` bekommen...

```{r}
# ...um Proportionen anstatt einer absoluten Anzahl darzustellen:
ggplot(coronal) +
  aes(x = Region, fill = Fr) +
  geom_bar(position = "fill")

# ...um die Balken nebeneinander zu stellen:
ggplot(coronal) +
  aes(x = Region, fill = Fr) +
  geom_bar(position = "dodge")
```

## Histogramme & Wahrscheinlichkeitsdichte

Histogramme zeigen die Verteilung von numerisch-kontinuierlichen Datenpunkten, indem sie den Wertebereich in mehrere kleine Bereiche einteilt. Ähnlich wie beim Barplot zeigen dann Balken (*bins*) an, wie viele Werte in einem bestimmten Wertebereich liegen. In `ggplot` werden Histogramme mit [`geom_histogram()`](https://ggplot2.tidyverse.org/reference/geom_histogram.html) erstellt. In den *aesthetic mappings* legen wir mit dem Argument `x` fest, welche Daten wir anschauen wollen, zum Beipspiel die F1-Verteilung:

```{r}
ggplot(vdata) + 
  aes(x = F1) + 
  geom_histogram()
```

Um die einzelnen Balken besser voneinander unterscheiden zu können, lassen wir die Balken weiß umranden, indem wir `geom_histogram()` das Argument `color = "white"` übergeben:

```{r}
ggplot(vdata) + 
  aes(x = F1) + 
  geom_histogram(color = "white")
```

Wir können auch selbst bestimmen, wie breit die Balken sein sollen, nämlich mit `binwidth`. Im Moment umfasst ein Balken ca. 40 Hz. Die folgenden Abbildungen zeigen die exakt selben Daten, aber mit Balken von 10 Hz und Balken von 100 Hz:

```{r}
ggplot(vdata) + 
  aes(x = F1) + 
  geom_histogram(color = "white",
                 binwidth = 10)

ggplot(vdata) + 
  aes(x = F1) + 
  geom_histogram(color = "white",
                 binwidth = 100)
```

Sie sehen, dass dies für die Repräsentation der Daten einen großen Unterschied macht -- gehen Sie also immer mit Bedacht vor, wenn Sie die *binwidth* von Histogrammen verändern.

Mit dem Histogramm verwandt ist die Wahrscheinlichkeitsdichte (engl. *probability density*). Die einzige Änderung, die wir dafür vornehmen müssen, ist `aes()` das Argument `y = ..density..` zu übergeben. Dies verändert die y-Achse so, dass statt der Anzahl an Datenpunkten die Wahrscheinlichkeitsdichte der Datenpunkte angezeigt wird. *Per definitionem* ist die Fläche unter den Balken der Wahrscheinlichkeitsdichte insgesamt 1.

```{r}
ggplot(vdata) + 
  aes(x = F1, y = ..density..) + 
  geom_histogram(color = "white",
                 binwidth = 100)
```

Die Wahrscheinlichkeitsdichte wird berechnet als `count / (n * binwidth)`, wo `n` die Anzahl aller Datenpunkte ist. In dem Histogramm oben (mit `binwidth = 100`) liegen zum Beispiel 285 Datenpunkte (*count*) im Wertebereich zwischen 150 Hz und 250 Hz. Die Wahrscheinlichkeitsdichte für diesen Balken wird also wie folgt berechnet:

```{r}
count <- 285
n <- nrow(vdata)
binwidth <- 100
dens <- count / (n * binwidth)
dens
```

Dieser Wert stimmt mit dem *density*-Wert überein, den wir in der Wahrscheinlichkeitsdichteverteilung für denselben Balken sehen.

Die Fläche dieses Balkens in der Wahrscheinlichkeitsdichteverteilung wird berechnet als `binwidth * binheight`: 

```{r}
area <- binwidth * dens
area
```

Wenn man die Fläche aller Balken berechnet und summiert, ist die Gesamtfläche 1.

Stellen Sie sich nun ein Wahrscheinlichkeitsdichte-Histogramm vor, das aus unendlich vielen Balken besteht (die dementsprechend unendlich schmal sein müssen). Sie erhalten nicht mehr einzelne Balken sondern eine kontinuierliche Funktion, die sich Wahrscheinlichkeitsdichteverteilung (*probability density function*) nennt. Auch dafür kennt `ggplot2` eine Funktion: [`geom_density()`](https://ggplot2.tidyverse.org/reference/geom_density.html).

```{r}
ggplot(vdata) + 
  aes(x = F1) + 
  geom_density()
```

Hier gilt genau wie bei dem Histogramm mit der Wahrscheinlichkeitsdichte, dass das Integral (die Fläche) unter der Kurve 1 ist. Weshalb das wichtig ist, erfahren Sie übernächste Woche.

<div class="gray">
**Weiterführende Infos: Histogramme und Probability Density**

Für weitere Informationen schauen Sie sich gerne Wilke's *Fundamentals of Data Visualization in R*, [Kapitel 7](https://serialmentor.com/dataviz/histograms-density-plots.html) an.
</div>
