library(tidyverse)
<- readxl::read_excel("data/victim_blaming.xlsx") vb
6 Deskriptivstatistik
Wir laden das tidyverse
-Paket und öffnen den Datensatz des Victim Blaming Experiments.
6.1 Daten zusammenfassen
Für die deskriptive Statistik sind insbesondere zwei tidyverse-Funktionen nützlich: summarise()
und group_by()
. summarise()
erlaubt es, Variablen zu aggregieren, d.h. die Daten aus mehreren Fällen in einem Wert zusammenzufassen. Wie bei mutate()
können wir mehrere Variablen berechnen, indem diese mit ,
getrennt werden. Es bietet sich an, für die neu enstandenen Aggregatvariablen beschreibende Namen zu wählen.
Der grundlegende Aufbau jedes summarise()
Befehls ist summarise(fun_x = fun(x))
, wobei jede Funktion verwendbar ist, die aus einem beliebig langen Datenvektor einen einzelnen Wert zurückgibt, z.B. min()
und max()
für Minimum und Maximum, aber auch mean()
und andere Funktionen. Ein wichtiges Prinzip des tidyverse ist, dass jede Funktion wie mutate()
oder summarise()
nicht nur als Input einen Tibble bekommt, sondern als Output ebenfalls wieder einen solchen Tibble zurückliefert, den wir dann ggf. im nächsten Schritt weiterverarbeiten können.
6.2 Maße der zentralen Tendenz
Zu den Maßen zentraler Tendenz zählen das arithmetische Mittel mean()
, der Median median()
, und der Modalwert. Wir können summarise()
nutzen, um diese Berechnungen anzustellen. Dazu betrachten wir die Altersvariable v_1
im Datensatz.
|>
vb summarise(
mean_alter = mean(v_1),
median_alter = median(v_1),
min_alter = min(v_1),
max_alter = max(v_1)
)
# A tibble: 1 × 4
mean_alter median_alter min_alter max_alter
<dbl> <dbl> <dbl> <dbl> 1 19.8 20 16 22
Als Ergebnis der Pipe steht ein Tibble mit einer Zeile und vier Spalten. Wir sehen, dass die Befragten zwischen 16 und 22 Jahre alt sind, mit einem Mittelwert von rund 19.8. Der Medianwert ist 20.
Wenn die Variable, die wir zusammenfassen wollen, fehlende Werte NA
enthält, schlagen die meisten statistischen Funktionen fehl und liefern NA
zurück.
|>
vb summarise(min_strafe = min(v_9a)) # klappt nicht wegen NA
# A tibble: 1 × 1
min_strafe
<dbl> 1 NA
Wollen wir trotzdem nützliche Ergebnisse bekommen, müssen wir als zusätzlichen Funktionsparameter na.rm = TRUE
verwenden. Damit werden vor der Berechnung des Kennwerts die fehlenden Werte entfernt. Das gilt für fast alle Funktionen, die wir in dieser Sitzung verwenden.
|>
vb summarise(min_strafe = min(v_9a, na.rm = TRUE)) # klappt besser
# A tibble: 1 × 1
min_strafe
<dbl> 1 0
Merke: Immer fun(..., na.rm = TRUE)
aufrufen, um fehlende Werte zu ignorieren.
6.3 Dispersionsmaße
Dispersionsmaße geben die Streuung der Datenpunkte wieder, sie sollten immer zusätzlich zu den Maßen der zentralen Tendenz angegeben werden. Die zwei wichtigsten Maße sind:
- Standardabweichung
sd()
- Spannweite, also der Abstand zwischen
min()
undmax()
.
Der bekannte summarise()
-Workflow ist auch für die Berechnung dieser Maße anwendbar. Bei der Berechnung der Spannweite nutzen wir die Möglichkeit, auch komplexere Berechnungen statt nur einer einzelnen Funktion durchzuführen, in diesem Fall die Differenz von Maximum und Minimum.
|>
vb summarise(
sd_alter = sd(v_1, na.rm = TRUE),
range_alter = max(v_1, na.rm = TRUE) - min(v_1, na.rm = TRUE),
)
# A tibble: 1 × 2
sd_alter range_alter
<dbl> <dbl> 1 1.94 6
In der Forschungspraxis und nach APA-Guidelines ist es üblich, metrische Variablen anhand von Mittelwert und Standardabweichung zu beschreiben. Das können wir auch für mehrere Variablen in einem Schritt erledigen.
|>
vb summarise(
mean_alter = mean(v_1, na.rm = TRUE),
sd_alter = sd(v_1, na.rm = TRUE),
mean_empathie = mean(v_13, na.rm = TRUE),
sd_empathie = sd(v_13, na.rm = TRUE)
)
# A tibble: 1 × 4
mean_alter sd_alter mean_empathie sd_empathie
<dbl> <dbl> <dbl> <dbl> 1 19.8 1.94 3.75 0.980
Wollen wir das aber für mehr als zwei Variablen machen, wird diese Darstellung schnell unübersichtlich, da immer mehr Spalten dazukommen. Eine übersichtlichere Darstellung erhalten wir mit folgendem Code, der sich die map_dfr()
-Funktion zunutze macht und die Tabelle so aufbaut, dass in den Spalten die statistischen Maße stehen und für jede neuen Variable eine Zeile hinzukommt:
|>
vb select(v_1, v_13) |> # Hier wählen wir die Variablen aus, die wir auswerten wollen
map_dfr(
~ tibble
(M = mean(.x, na.rm = TRUE), # Hier reihen wir die statistischen Maße hintereinander, die wir auswerten wollen. Satt des Variablennamen steht ein .x, dort wird dann jeweils nacheinander die Variable eingesetzt, die unter "select" ausgewählt wurden
SD = sd(.x, na.rm = TRUE)
),.id = "Variable"
# Hier wird festgelegt, dass die erste Spalte mit den Variablennamen als Überschrift "Variable" haben soll. )
# A tibble: 2 × 3
Variable M SD
<chr> <dbl> <dbl>
1 v_1 19.8 1.94 2 v_13 3.75 0.980
6.4 Gruppenvergleiche
Die zweite nützliche Funktion für die Deskriptivstatistik im tidyverse ist group_by()
, die wir in der Analyse zwischen den Datensatz und die summarise()
Funktion schieben. Die Funktion teilt den Datensatz anhand der angegeben Variable und ermöglicht so ganz leicht Gruppenvergleiche. Achtung: group_by()
führt zunächst lediglich dazu, dass die Daten gruppiert werden. Die Effekte von group_by()
zeigen sich erst in den nachfolgenden tidyverse-Funktionen, welche dann automatisch die Gruppierung bei der Erstellung neuer Variablen beachten. Dieses Vorgehen erlaubt es, mit summarise()
deskriptive Statistiken für Untergruppen zu erstellen. Im folgenden Beispiel berechnen wir zunächst wieder Mittelwert und Standardabweichung der Altersvariable.
|>
vb summarise(
mean_alter = mean(v_1, na.rm = TRUE),
sd_alter = sd(v_1, na.rm = TRUE)
)
# A tibble: 1 × 2
mean_alter sd_alter
<dbl> <dbl> 1 19.8 1.94
Wenn die Randomisierung gelungen ist, sollten sich diese Werte nicht stark zwischen den Experimentalbedingungen unterscheiden. Das prüfen wir, indem wir den Datensatz vor der Aggregation nach der Variable stimulus_rec
gruppieren und dann dieselbe summarise()
Funktion nutzen.
|>
vb group_by(stimulus_rec) |> # nur dies haben wir eingefügt
summarise(
mean_alter = mean(v_1, na.rm = TRUE),
sd_alter = sd(v_1, na.rm = TRUE)
)
# A tibble: 4 × 3
stimulus_rec mean_alter sd_alter
<chr> <dbl> <dbl>
1 Extravertiert mit Info 19.9 1.95
2 Extravertiert ohne Info 19.9 1.74
3 Introvertiert mit Info 19.6 2.01 4 Introvertiert ohne Info 19.6 2.01
Da die Gruppierungsvariable vier Ausprägungen hat, bekommen wir auch einen Tibble mit vier Zeilen (eine pro Gruppe) ausgegeben. Da Gruppenvergleiche für eine Vielzahl von Analyseverfahren notwendig sind, wird uns die group_by()
Funktion auch in den nachfolgenden Sitzungen zu T-Tests, ANOVA oder Kreuztabellen wieder begegnen.
group_by()
in Verbindung mit der Erstellung von Objekten
Im obigen Beispiel verändern wir den vb
-Datensatz nicht und wir erstellen auf Basis der Gruppierung kein neues Objekt. Auch folgt auf die summarise()
-Funktion keine weitere Funktion, die ohne Gruppierung ausgeführt werden sollte. Trifft aber eines von beiden zu - wir erstellen ein neues Objekt oder es folgen weitere Funktionen - ist es wichtig, den ungroup()
-Befehl zu verwenden. Ansonsten wird auch im Weiteren mit der Gruppierung gearbeitet und die group_by()
-Funktion wirkt sich dann also auch auf weitere Auswertungen etc. aus.
<- vb |> # Im Unterschied zu oben erstellen wir hier ein neues Objekt `ergebnistabelle`
ergebnistabelle group_by(stimulus_rec) |>
summarise(
mean_alter = mean(v_1, na.rm = TRUE),
sd_alter = sd(v_1, na.rm = TRUE)
|>
) ungroup() # Hier wird die Gruppierung aufgehoben
6.5 Häufigkeiten
Eine basale deskriptive Statistik sind Häufigkeiten. Das tidyverse bietet für die Berechnung von Häufigkeiten die Funktion n()
.
|>
vb summarise(n_cases = n())
# A tibble: 1 × 1
n_cases
<int> 1 586
Der Datensatz hat also 586 Zeilen oder Fälle. Dies ist an sich noch nicht sehr interessant, zumal wir mit der dim()
Funktion auch schon die Anzahl Zeilen und Spalten ausgeben lassen können. Wenn wir den Datensatz aber nach einer bestimmten Variable mit group_by()
gruppieren, erhalten wir die absoluten Häufigkeiten der Gruppierungsvariable.
|>
vb group_by(stimulus_rec) |>
summarise(n_cases = n())
# A tibble: 4 × 2
stimulus_rec n_cases
<chr> <int>
1 Extravertiert mit Info 153
2 Extravertiert ohne Info 137
3 Introvertiert mit Info 139 4 Introvertiert ohne Info 157
Da diese Operation sehr häufig genutzt wird, gibt es auch noch eine Kurzform count()
, die automatisch eine neue Variable n
erzeugt.
|>
vb count(stimulus_rec)
# A tibble: 4 × 2
stimulus_rec n
<chr> <int>
1 Extravertiert mit Info 153
2 Extravertiert ohne Info 137
3 Introvertiert mit Info 139 4 Introvertiert ohne Info 157
Wie bekommen wir nun relative Häufigkeiten und Prozentwerte? Die Antwort kennen wir schon: Wir berechnen neue Variablen mit mutate()
.
|>
vb count(stimulus_rec) |>
mutate(
rel_freq = n / sum(n), # relative Häufigkeit
percent = rel_freq * 100 # Prozentwerte
)
# A tibble: 4 × 4
stimulus_rec n rel_freq percent
<chr> <int> <dbl> <dbl>
1 Extravertiert mit Info 153 0.261 26.1
2 Extravertiert ohne Info 137 0.234 23.4
3 Introvertiert mit Info 139 0.237 23.7 4 Introvertiert ohne Info 157 0.268 26.8
Dichotome Variablen, die 0/1 codiert sind, haben viele Vorteile in der Datenanalyse. Einer davon ist, dass der Mittelwert einer solchen Variable der relativen Häufigkeit der Ausprägung 1 entspricht. Damit können wir mit einem einzigen summarize()
z.B. Mehrfachantworten oder andere Variablengruppen auszählen. Hier die relativen Häufigkeiten einiger vorgeschlagenen Strafen:
|>
vb summarise(
ermahnung = mean(v_9a, na.rm = TRUE),
entschuldigung = mean(v_9e, na.rm = TRUE),
nachsitzen = mean(v_9f, na.rm = TRUE)
)
# A tibble: 1 × 3
ermahnung entschuldigung nachsitzen
<dbl> <dbl> <dbl> 1 0.479 0.815 0.147
Fast die Hälfte der Befragten findet eine Ermahnung richtig, über 80% fordern eine Entschuldigung, aber weniger als 15% Nachsitzen.
Zum Schluss können wir die Häufigkeitstabelle auch noch nach Häufigkeiten (statt nach den Experimentalbedingungen) sortieren, auch diese Funktion haben wir schon kennengelernt: arrange()
. Wir speichern das Ergebnis der gesamten Datentransformation in einem neuen Objekt, das wir später wiederverwenden wollen.
<- vb |>
freq_stimulus count(stimulus_rec) |>
mutate(percent = n / sum(n) * 100) |> # Prozentwerte
arrange(desc(n)) # absteigende Häufigkeiten
freq_stimulus
# A tibble: 4 × 3
stimulus_rec n percent
<chr> <int> <dbl>
1 Introvertiert ohne Info 157 26.8
2 Extravertiert mit Info 153 26.1
3 Introvertiert mit Info 139 23.7 4 Extravertiert ohne Info 137 23.4
Wir werden group_by()
und count()
in der Sitzung zu Kreuztabellen wiedersehen, da die Funktionen auch mehrere Gruppierungsvariablen berücksichtigen können.
6.6 Glossar
Funktion | Definition |
---|---|
arrange() | Sortieren eines Dataframes/Tibbles |
arrange() | Sortieren einer Variable (default: aufsteigend, für absteigend: desc()) |
count() | Zählen der Häufigkeit, mit der jede Ausprägung einer Variable vorkommt |
group_by() | Einteilung des Dataframes/Tibbles in Gruppen anhand der angegebenen Variable(n) |
max() | Anzeige des größten Wertes in einer Variable |
mean() | Berechnung des arithmetischen Mittels |
median() | Berechnung des Medians |
min() | Anzeige des kleinsten Wertes in einer Variable |
mutate() | Verändern oder Erstellen einer oder mehrerer Variablen in einem Dataframe/Tibble |
sd() | Berechnung der Standardabweichung |
summarise() | Aggregieren einer oder mehrerer Variablen eines Dataframes/Tibbles zu einer oder mehreren neuen Variablen |
6.7 Hausaufgabe
Für die Hausaufgabe analysieren wir den Datensatz gewohnheiten.xlsx
.
- Was ist das Durchschnittsalter in der Stichprobe (arithmetisches Mittel, Median)? Und welche Altersrange (Spannweite) wurde befragt?
- Wieviele Männer und Frauen wurden befragt?
- Unterscheiden sich Männer und Frauen im Durchschnitt darin, wie sehr sie den Fernseher vermissen würden? (mit Antwortsatz)
Für die Aufgaben gilt:
- Geben Sie als Kommentar (mit # beginnend) an, welche Frage Sie bearbeiten, darunter folgt der zugehörige Code.
- Die Antwortsätze folgen darunter, sofern gefordert, ebenfalls als Kommentar (mit # beginnend).