Kapitel 7 Deskriptive Statistik
Die beschreibende Statistik bietet neben Informationen über die Verteilungen und Zusammenhänge der interessierenden Merkmale ebenfalls die Möglichkeit, unplausible Werte zu identifizieren, die mit den im vorherigen Kapitel gelernten Methoden entfernt oder korrigiert werden müssen. Die Angabe der in diesem Kapitel eingeführten Lage- und Streuungsmaße, Häufigkeiten und Zusammenhangsmaße dürfen in keiner wissenschaftlichen Arbeit fehlen.
7.1 Lagemaße und Streuungsmaße
Für dieses Kapitel müssen die Packages des tidyverse
und remp
installiert und geladen werden.
Wir werden in diesem Kapitel den big5_mod
Datensatz ohne die Spalte namens ID
verwenden und bezeichnen diesen als big5_mod1
.
# A tibble: 200 × 5
Alter Geschlecht Extraversion Neurotizismus Gruppe
<dbl> <chr> <dbl> <dbl> <fct>
1 36 m 3 1.9 Mittel
2 30 f 3.1 3.4 Jung
3 23 m 3.4 2.4 Jung
4 54 m 3.3 4.2 Weise
# ℹ 196 more rows
Einen ersten Überblick über die Daten können wir mit der direkt in R integrierten Funktion summary()
erhalten, der wir lediglich den Namen des Datensatzes übergeben müssen.
Alter Geschlecht Extraversion Neurotizismus Gruppe
Min. :13.00 Length:200 Min. :2.300 Min. :1.400 Jung :147
1st Qu.:18.75 Class :character 1st Qu.:2.800 1st Qu.:2.700 Mittel: 39
Median :23.00 Mode :character Median :3.000 Median :3.100 Weise : 14
Mean :26.48 Mean :3.076 Mean :3.133
3rd Qu.:31.25 3rd Qu.:3.300 3rd Qu.:3.600
Max. :60.00 Max. :4.300 Max. :4.600
Hier sehen wir einen Vorteil von Faktoren. Während wir die Häufigkeiten der Altersgruppe ausgegeben bekommen, kann R für die Spalte mit Geschlecht lediglich die Anzahl an Character Werten zählen. Für weitere Informationen über Faktoren und deren Umgang schaue dir erneut Kapitel 4.3.2 und 6.10 an.
Falls wir gruppierte Lage- und Streuungsmaße erhalten oder andere Werte wie den Standardfehler ausrechnen möchten, müssen wir auf die summarise()
Funktion aus dem Package dplyr
(enthalten im tidyverse
) zurückgreifen. Auch hier werden wir einzelne Befehle mit der Pipe (|>
) aneinanderketten (siehe Kapitel 6.1).
Exemplarisch soll zunächst der Mittelwert mit der Funktion mean()
und die Standardabweichung mit sd()
berechnet werden. Beide Funktionen müssen wir dabei innerhalb der Funktion summarise()
verwenden. Auf der linken Seite des Gleichheitszeichens stehen auch hier wieder die Namen der neu erstellten Spalten.
# A tibble: 1 × 2
M SD
<dbl> <dbl>
1 3.08 0.347
Zum Gruppieren der Variablen wird die Funktion group_by()
verwendet.
# A tibble: 2 × 3
Geschlecht M SD
<chr> <dbl> <dbl>
1 f 3.05 0.358
2 m 3.11 0.328
Dabei können der Funktion beliebig viele Spalten übergeben werden. So könnte man bspw. nicht nur nach Geschlecht, sondern auch nach der Altersgruppe gruppieren.
big5_mod1 |>
group_by(Geschlecht, Gruppe) |>
summarise(
M = mean(Extraversion),
SD = sd(Extraversion)
)
# A tibble: 6 × 4
# Groups: Geschlecht [2]
Geschlecht Gruppe M SD
<chr> <fct> <dbl> <dbl>
1 f Jung 3.07 0.373
2 f Mittel 3.07 0.299
3 f Weise 2.83 0.269
4 m Jung 3.12 0.324
# ℹ 2 more rows
Alternativ können wir zum Gruppieren anstelle von group_by()
auch das Argument .by
hinzufügen. Während der Datensatz nach group_by()
gruppiert ist, was bei weiterer Verwendung mit ungroup()
aufgelöst werden müsste, gruppiert das .by
Argument nur einmalig. Das Argument kann auch mit der in Kapitel 6.4 kennengelernten Funktion mutate()
verwendet werden. Da die Ausgabe von summarise()
in der Regel bereits ein Endergebnis darstellt, ist die Wahl zwischen group_by()
oder .by
größtenteils abhängig von persönlicher Präferenz.
big5_mod1 |>
summarise(
M = mean(Extraversion),
SD = sd(Extraversion),
.by = c(Geschlecht, Gruppe)
)
# A tibble: 6 × 4
Geschlecht Gruppe M SD
<chr> <fct> <dbl> <dbl>
1 m Mittel 3.13 0.281
2 f Jung 3.07 0.373
3 m Jung 3.12 0.324
4 m Weise 2.96 0.546
# ℹ 2 more rows
Neben der Funktionen für den Mittelwert und der Standardabweichung gibt es noch diverse weitere: n()
für die Anzahl an Beobachtungen, min()
und max()
für Minimum und Maximum, var()
für die Varianz, sqrt()
für die Quadratwurzel, median()
für den Median und quantile()
zur Berechnung der jeweiligen Quantile.
Für die Berechnung des Standardfehlers teilen wir direkt innerhalb des Funktionsaufrufes die Standardabweichung durch die Wurzel aus der Anzahl der Personen.
big5_mod1 |>
summarise(
N = n(),
Min = min(Alter),
Mean = mean(Alter),
Median = median(Alter),
Max = max(Alter),
SD = sd(Alter),
SE = SD / sqrt(N)
)
Grundsätzlich kann jede Funktion summarise()
übergeben werden, die einen einzelnen Wert berechnet. Somit unterscheidet sich die Anwendung maßgeblich vom bereits kennengelernten mutate()
. Dort musste die Ausgabe immer eine Reihe von Werten umfassen, die der Anzahl der Zeilen im Datensatz entspricht.
Auch hier können wir mehrere Spalten gleichzeitig mithilfe von across()
auswerten (siehe Kapitel 6.4.2). Die Syntax ändert sich in dem Fall im Vergleich zu vorher. Hier müssen wir die verschiedenen Funktionen mit entsprechendem Namen innerhalb einer Liste übergeben. Listen als solche werden erst später eingeführt und müssen uns an dieser Stelle nicht weiter interessieren (siehe Kapitel 11.4).
big5_mod1 |>
summarise(across(
.cols = Extraversion:Neurotizismus,
.fns = list(M = mean, SD = sd))
)
# A tibble: 1 × 4
Extraversion_M Extraversion_SD Neurotizismus_M Neurotizismus_SD
<dbl> <dbl> <dbl> <dbl>
1 3.08 0.347 3.13 0.682
Bei vielen Lagemaßen kann es schnell umständlich werden, jede einzeln aufzurufen. Wenn man keine Lust hat, dies jedes Mal manuell abzutippen, kann man auch direkt vereinfachte Funktionen zur deskriptiven Statistik verwenden. Das remp Package bietet die Funktion descriptive()
an. Dieser muss man kein weiteres Argument übergeben. Es wird die Anzahl, das Minimum, das erste Quartil, der Mittelwert, der Median, das zweite Quartil, die Standardabweichung und der Standardfehler für sämtliche numerische Spalten zurückgegeben. Alle anderen Datentypen werden von dieser Funktion ignoriert.
# A tibble: 3 × 10
Variable N Min Q1 Mean Median Q3 Max SD SE
<chr> <int> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 Alter 200 13 18.8 26.5 23 31.2 60 11.4 0.8
2 Extraversion 200 2.3 2.8 3.08 3 3.3 4.3 0.35 0.02
3 Neurotizismus 200 1.4 2.7 3.13 3.1 3.6 4.6 0.68 0.05
Auch hier können wir die Berechnungen auf dieselbe Art und Weise gruppieren.
Alternativen für einen schnellen Überblick bieten beispielsweise auch das skimr
Package mit der Funktion skim()
oder describe()
aus dem psych
Package. Beide können auch nicht-numerische Spalten auswerten und erstere gibt zu jeder Spalte sogar ein kleines Histogramm aus.
Wie dir vielleicht bereits aufgefallen ist, sieht die Ausgabe von descriptive()
anders aus als die von summarise()
. Während erstere die Variablen untereinander in unterschiedliche Zeilen übersichtlich auflistet, fügt summarise()
die Ergebnisse spaltenweise hinzu. Wenn wir denselben Output wie in descriptive()
erreichen möchten, müssen wir zuerst den Datensatz in ein langes Format bringen (siehe Kapitel 6.6). Nun gruppieren wir nach der neuen Spalte namens Variable
. Anschließend können wir wie gewohnt mit summarise()
die deskriptiven Statistiken berechnen. Nichts anderes macht die Funktion descriptive()
hinter den Kulissen.
big5_mod1 |>
pivot_longer(
cols = c(Alter, Extraversion, Neurotizismus),
names_to = "Variable",
values_to = "Wert"
) |>
group_by(Variable) |>
summarise(
Q1 = quantile(Wert, 0.25),
Mean = mean(Wert),
Q3 = quantile(Wert, 0.75),
Schiefe = skewness(Wert),
Kurtosis = kurtosis(Wert)
)
# A tibble: 3 × 6
Variable Q1 Mean Q3 Schiefe Kurtosis
<chr> <dbl> <dbl> <dbl> <dbl> <dbl>
1 Alter 18.8 26.5 31.2 1.34 3.97
2 Extraversion 2.8 3.08 3.3 0.761 3.95
3 Neurotizismus 2.7 3.13 3.6 -0.132 2.56
Beachte an dieser Stelle, dass für die Funktionen skewness()
und kurtosis()
das moments
Package installiert und geladen sein muss.
Übung 7.1. (Noch nicht enthalten) Starte die Übung mit uebung_starten(7.1)
.
7.2 Häufigkeiten und Kontingenztafeln
Auch in diesem Unterkapitel verwenden wir unter anderem die Packages aus dem tidyverse
.
Eine Möglichkeit Häufigkeiten zu zählen, haben wir bereits mit n()
innerhalb von summarise()
kennengelernt. Eine Alternative stellt die count()
Funktion aus selbigem Package dar. Hier können wir uns group_by()
sparen und stattdessen die gruppierenden Spalten direkt in count()
schreiben.
# A tibble: 2 × 2
Geschlecht n
<chr> <int>
1 f 118
2 m 82
Dabei können beliebig viele Spalten übergeben werden. Um die höchste Anzahl zu Beginn auszugeben, würden wir zusätzlich das sort
Argument auf TRUE
setzen.
# A tibble: 6 × 3
Geschlecht Gruppe n
<chr> <fct> <int>
1 f Jung 89
2 m Jung 58
3 f Mittel 20
4 m Mittel 19
# ℹ 2 more rows
Zum Darstellen der Anteile der jeweiligen Gruppen, müssen wir innerhalb von mutate()
die einzelnen Häufigkeiten durch Anzahl in der jeweiligen Gruppe teilen (siehe Kapitel 6.4).
# A tibble: 6 × 4
Geschlecht Gruppe n Prop
<chr> <fct> <int> <dbl>
1 f Jung 89 0.445
2 f Mittel 20 0.1
3 f Weise 9 0.045
4 m Jung 58 0.29
5 m Mittel 19 0.095
6 m Weise 5 0.025
Hier werden die Verhältnisse über alle Häufigkeiten berechnet, da count()
keinen gruppierten Datensatz zurückgibt. Sollen die Häufigkeiten innerhalb einer Gruppe berechnet werden, muss zusätzlich mithilfe von group_by()
explizit neu gruppiert werden.
big5_mod |>
count(Geschlecht, Gruppe) |>
group_by(Geschlecht) |>
mutate(Prop = n / sum(n)) |>
ungroup()
# A tibble: 6 × 4
Geschlecht Gruppe n Prop
<chr> <fct> <int> <dbl>
1 f Jung 89 0.754
2 f Mittel 20 0.169
3 f Weise 9 0.0763
4 m Jung 58 0.707
5 m Mittel 19 0.232
6 m Weise 5 0.0610
Für die Erstellung von Kontingenztafeln, die wir mit statistischen Tests auswerten können, benötigen wir allerdings eine andere Funktion namens table()
. Damit können wir ähnlich wie mit count()
die Häufigkeiten kategorialer Merkmale abbilden. Die Werte müssen dabei als Wertereihe (bzw. Vektor) mit dem Dollar-Operator aus dem Datensatz extrahiert werden (siehe Kapitel 4.5).
f m
118 82
Zur Erstellung einer klassischen Vierfeldertafel wird eine zusätzliche Variable in die Funktion geschrieben. Wenn wir also untersuchen möchten, ob es Unterschiede in der Häufigkeit extrovertierter Menschen zwischen den Geschlechtern gibt, wählen wir erst die Spalte Extraversion
des Datensatzes big5_mod
und anschließend die Spalte Geschlecht
. Beachte die logische Abfrage bei der Extraversion: wenn Extraversion größer als 3 ist, wird eine 1 und ansonsten eine 0 zurückgegeben. Mit dem optionalen Argument dnn
können für eine bessere Übersichtlichtkeit die Dimensionsnamen festgelegt werden (hier z.B. Extrovertiert
und Geschlecht
).
tb <- table(big5_mod$Extraversion > 3, big5_mod$Geschlecht,
dnn = c("Extrovertiert", "Geschlecht"))
tb
Geschlecht
Extrovertiert f m
FALSE 66 43
TRUE 52 39
Häufig fehlen zumindest ein paar Werte in den jeweiligen Spalten. Um diese ebenfalls ausgegeben zu bekommen, setzen wir das Argument useNA
innerhalb der Funktion table()
auf "ifany"
. Dadurch werden fehlende Werte nur dann angezeigt, falls diese tatsächlich vorkommen. Ein weiteres nützliches Argument ist exclude
zum Ausschluss einer Faktorstufe für die Erstellung einer Kontingenztafel zur späteren Auswertung. Wäre bei der Variable Geschlecht
eine dritte Stufe namens divers
mit wenigen Beobachtungen vorhanden, könnten wir diese so ausblenden. Voraussetzung ist der Datentyp Faktor für die Variable (siehe Kapitel 4.3.2).
Es können beliebig viele Häufigkeiten von Merkmalen miteinander in Beziehung gesetzt werden. Allerdings sind mehr als drei Dimensionen nur selten sinnvoll zu interpretieren.
, , = FALSE
f m
FALSE 47 39
TRUE 33 23
, , = TRUE
f m
FALSE 19 4
TRUE 19 16
Nach Erstellen der Kontingenztafeln mithilfe von table()
können die Verhältnisse der Merkmale mit der Funktion proportions()
ausgegeben werden. Dies stellt eine Alternative zur bereits kennengelernten Kombination aus count()
und mutate()
dar.
Geschlecht
Extrovertiert f m
FALSE 0.330 0.215
TRUE 0.260 0.195
Der Vorteil ist hier, dass wir zusätzlich bestimmen können, ob wir auf die Zeilen oder Spalten bedingen möchten. Zum Konditionieren auf die Zeilen, muss nur eine 1
hinzugefügt werden.
Geschlecht
Extrovertiert f m
FALSE 0.6055046 0.3944954
TRUE 0.5714286 0.4285714
Äquivalent dazu wird mit einer zusätzlichen 2
auf die Spalten bedingt.
Geschlecht
Extrovertiert f m
FALSE 0.5593220 0.5243902
TRUE 0.4406780 0.4756098
Möchte man die Kontingenztafel für jede Spalte ausgeben lassen, kann table()
ohne Klammern in der Funktion map()
genutzt werden. Diese wendet table()
auf jeden Spalte der Reihe nach an und speichert diese in Form einer Liste ab.
Zur besseren Übersicht schalten wir an dieser Stelle noch ein select()
davor, um nur das Geschlecht und die Altersgruppe auszuwählen. Wir könnten aber auf dieselbe Art und Weise sämtlich Spalten in einer Kontingenztafel ausgeben lassen.
$Geschlecht
f m
118 82
$Gruppe
Jung Mittel Weise
147 39 14
So können auch alle Verhältnisse ausgegeben werden.
$Geschlecht
f m
0.59 0.41
$Gruppe
Jung Mittel Weise
0.735 0.195 0.070
Diese Art des wiederholten Berechnens einer Funktion wird in Kapitel 12 genauer erläutert. Vom Prinzip her ist die Anwendung von map()
in diesem Fall wie das Nutzen von across()
innerhalb von mutate()
(siehe Kapitel 6.4.2). Allerdings muss die Ausgabe in mutate()
oder auch in summarise()
das gleiche Format für alle Spalten haben. Wenn wir Kontingenztafeln mit unterschiedlich vielen Kategorien in den jeweiligen Spalten erstellen, ist diese Bedingung jedoch nicht erfüllt. Daher müssen wir in diesem Fall auf map()
zurückgreifen.
Übung 7.2. (Noch nicht enthalten) Starte die Übung mit uebung_starten(7.2)
.
7.3 Zusammenhangsmaße
Zwei der wichtigsten Zusammenhangsmaße sind die Kovarianz und die darauf basierende Korrelation. Eine Korrelation berechnen wir mit der cor()
Funktion, welche standardmäßig die Produkt-Moment-Korrelation berechnet.
[1] 0.06972529
Für die Rangkorrelation nach Spearman oder die Kendall-Tau Korrelation muss das Argument method
auf "spearman"
oder kendall
gesetzt werden.
[1] 0.04874732
Um mehrere Korrelationen auf einmal zu berechnen, übergeben wir der Funktion cor()
mehr als zwei Spalten. Dabei können wir der Funktion grundsätzlich unbegrenzt viele numerische Spalten übergeben. Erst wählen wir die gewünschten Spalten aus und bezeichnen das Zwischenergebnis als big5_sub
.
Diesen Datensatz mit ausschließlich numerischen Spalten übergeben wir dann der Funktion cor()
.
Alter Extraversion Neurotizismus
Alter 1.0000000 -0.12250136 -0.23019948
Extraversion -0.1225014 1.00000000 0.06972529
Neurotizismus -0.2301995 0.06972529 1.00000000
Auf dieselbe Art und Weise kann die Kovarianz mithilfe der Funktion cov()
berechnet werden.
Alter Extraversion Neurotizismus
Alter 128.8837940 -0.48201005 -1.78158291
Extraversion -0.4820101 0.12012462 0.01647437
Neurotizismus -1.7815829 0.01647437 0.46473467
Zusammenhangsmaße für Kontingenztafeln werden in Kapitel 9.6 besprochen.
Übung 7.3. (Noch nicht enthalten) Starte die Übung mit uebung_starten(7.3)
.