-
Notifications
You must be signed in to change notification settings - Fork 0
/
datr_moreadvanced.Rmd
223 lines (183 loc) · 7.71 KB
/
datr_moreadvanced.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
---
title: "Weitere Tipps"
output:
html_document:
includes:
after_body: footer.html
---
Hier sind weitere, nützliche Tipps, die ich gerne sehr viel früher gewusst hätte.
# dplyr pipes %>%
Manchmal möchte man mehrere Befehle nacheinander auf ein R-Objekt anwenden. Das werden dann entweder mehrere Befehle, die man nacheinander in mehreren Zeilen ausführt oder ein sehr großer, geschachtelter Befehl. Unser Beispieldatensatz ist derselbe wie im [Kapitel zur deskriptiven Statistik](datr_descriptivestats.html):
```{r, include=FALSE}
library(data.table)
library(dplyr)
data(mtcars)
mtcars2 <- within(mtcars, {
vs <- factor(vs, labels = c("V", "S"))
am <- factor(am, labels = c("auto", "manu"))
gear <- ordered(gear)
carb <- ordered(carb)
})
mtcars2$cyl <- as.factor(mtcars2$cyl)
mtcars <- mtcars2 %>% select(mpg, hp, am, cyl)
```
<div class = "row"> <div class = "col-md-6">
```{r}
head(mtcars) # Erste Zeilen
```
</div> <div class = "col-md-6">
```{r, eval=FALSE}
str(mtcars) # Struktur des Datensatzes
```
```{r, echo=FALSE, warning=FALSE, message=FALSE, error=FALSE}
str(mtcars, width=40, strict.width="cut")
```
</div> </div>
Sagen wir, wir wollen nur die Autos, die einen Verbrauch von weniger als 20 `mpg` haben und 6 oder 8 Zylinder. Außerdem benötigen wir dann lediglich die Spalte mit der `hp` und wollen diese sortiert nach Größe anzeigen. Dies könnte man z.B. so umsetzen:
```{r}
mtcars2 <- subset(mtcars, mpg < 20)
mtcars3 <- subset(mtcars2, cyl != "4")
mtcars4 <- mtcars3$hp
sort(mtcars4)
```
Man könnte es auch in einen einzigen Befehl schachteln:
```{r}
sort(subset(subset(mtcars, mpg < 20), cyl != "4")$hp)
```
Der erste Ansatz hat den Vorteil, dass man mehr Kontrolle über die einzelnen Schritte hat - also z.B. einen Zwischenschritt schnell entfernen kann. Der zweite Ansatz nimmt weniger Platz ein.
Die *dplyr pipes* aus dem `dplyr` package versuchen das Beste aus beiden Ansätzen zu kombinieren. Anstatt mehrere Funktionen ineinander schachteln zu müssen, kann man sie mit den `%>%` Operatoren aneinanderknüpfen. Eine detaillierte Einleitung dazu gibt es z.B. [hier](https://seananderson.ca/2014/09/13/dplyr-intro/). Man würde es also wie folgt umsetzen:
```{r}
library(dplyr)
mtcars %>%
subset(mpg < 20) %>%
subset(cyl != "4") %>%
pull(hp) %>%
sort
```
> Der Befehle `pull()` extrahiert eine Spalte aus einem Datensatz direkt in das Format eines Vektors. Will man eine oder mehrere Spalten extrahieren aber weiterhin im Spaltenformat lassen, kann man stattdessen den `select()` Befehl nutzen.
## dplyr vs. data.table
Manch einem mag aufgefallen sein, dass die packages `dplyr` und `data.table` in Sachen Datenhandling überlappen, also unterschiedliche Funktionen zum selben Prozess zur Verfügung stellen. Tatsächlich nutze ich of beide Pakete gleichzeitig. Es ist ein wenig Geschmackssache und abhängig von der jeweiligen Aufgabe, welcher Code am besten zum Ziel führt. Eine recht ausführliche Gegenüberstellung der beiden packages gibt es [hier](https://stackoverflow.com/questions/21435339/data-table-vs-dplyr-can-one-do-something-well-the-other-cant-or-does-poorly).
# %in% Funktion
Die %in% Funktion kann verschieden Arten nützlich sein. Wenn wir z.B. eine neue Spalte erstellen wollen, die lediglich "TRUE" anzeigt wenn ein Auto 4 oder 6 Zyliner hat, aber "FALSE" wenn es 8 hat, ginge das so:
```{r, include=FALSE}
somecars <- mtcars %>% subset(mpg>17 & mpg<19)
```
<div class = "row"> <div class = "col-md-6">
```{r}
# ohne %in%
somecars$cyl == "4" | somecars$cyl == "6"
```
</div> <div class = "col-md-6">
```{r}
# mit %in%
somecars$cyl %in% c("4", "6")
```
</div> </div>
Es ist also klar, dass die %in% mit mehreren Stufen sehr schnell sehr platzsparend wird. Übrigens gibt es m.E. keine %not_in% Funktion, aber man kann sie sich z.B. so selber bauen:
```{r}
`%not_in%` <- Negate(`%in%`)
```
<div class = "row"> <div class = "col-md-6">
```{r}
# ohne %not_in%
somecars$cyl != "4" & somecars$cyl != "6"
```
</div> <div class = "col-md-6">
```{r}
# mit %not_in%
somecars$cyl %not_in% c("4", "6")
```
</div> </div>
# Pivot-artige Häufigkeitsliste
Die `table()` Funktion im [Kapitel zur deskriptiven Statistik](datr_descriptivestats.html) ist zwar nützlich, aber oft brauche ich sie in einem *long-format*, also mit einer einzigen Spalte aller Anzahlen. Ich hätte die Anzahlen also gerne ähnlich aufbereitet wie man es in Excel mit Pivot-Tabellen kann. Dafür nutze ich folgende Kombination aus `dplyr` und `data.table` Befehlen:
<div class = "row"> <div class = "col-md-6">
```{r}
# mit einer Spalte
mtcars %>%
select(cyl) %>%
table(exclude=NULL) %>%
data.table %>%
setorder(-N) %>% show
```
</div> <div class = "col-md-6">
```{r}
# mit zwei Spalten
mtcars %>%
select(cyl, am) %>%
table(exclude=NULL) %>%
data.table %>%
setorder(-N) %>% show
```
</div> </div>
# Faktorstufen ordnen
Spätestens beim Erstellen von Plots mit `ggplot()` stößt man auf das Problem, dass die Faktorstufen einer Variable, die `as.factor` definiert ist, anscheinend einer festen Reihenfolge unterliegen, die sich nicht ganz so schnell ändern lässt - zumindest nicht durch z.B. sortieren des Datensatzes.
Man beachte bei diesem Beispiel, dass die Reihenfolge (a, b, c) im Datensatz selbst stimmt und sogar genau so in den `as.factor()` Befehl eingegeben wurde. Dennoch ordnet R die Stufen automatisch alphabetisch, was man sowohl im plot, als auch mit dem `levels()` Befehl sehen kann:
```{r, echo=FALSE, message=FALSE, warning=FALSE}
library(ggplot2)
```
```{r}
dat <- data.frame(fkt = as.factor(c("a", "c", "b")),
num = c(21, 20, 22))
```
<div class = "row"> <div class = "col-md-6">
```{r}
dat
levels(dat$fkt)
```
</div> <div class = "col-md-6">
```{r, out.width = '60%', fig.align='center', fig.height=3, fig.width=3}
ggplot(data=dat, aes(y=num, x=fkt)) +
geom_point(size=3)
```
</div> </div>
Tatsächlich ist die Reihenfolge der Faktorstufen mit im Objekt abgespeichert und meist standardmäßig alphabetisch angeordnet. Es gibt mehrere Möglichkeiten um diese Reihenfolge zu ändern. Ich selbst nutze seit einiger Zeit das `forcats` package.
### Manuell anordnen
Will man eine manuelle Reihenfolge bestimmen, so geht das mit dem Befehl `fct_relevel`:
<div class = "row"> <div class = "col-md-6">
```{r}
library(forcats)
dat <- dat %>%
mutate(fkt=fct_relevel(fkt, c("a","c","b")))
levels(dat$fkt)
```
</div> <div class = "col-md-6">
```{r, out.width = '60%', fig.align='center', fig.height=3, fig.width=3}
ggplot(data=dat, aes(y=num, x=fkt)) +
geom_point(size=3, color="olivedrab")
```
</div> </div>
### Nach einer anderen Variable ordnen lassen
Will man die Faktorstufen lieber nach z.B. der y-Variable (`num`) des Plots ordnen, so geht das mit `fct_reorder`:
<div class = "row"> <div class = "col-md-6">
```{r}
library(forcats)
dat <- dat %>%
mutate(fkt=fct_reorder(fkt, num, .desc=TRUE))
levels(dat$fkt)
```
</div> <div class = "col-md-6">
```{r, out.width = '60%', fig.align='center', fig.height=3, fig.width=3}
ggplot(data=dat, aes(y=num, x=fkt)) +
geom_point(size=3, color="firebrick")
```
</div> </div>
# pacman package
Will man oft viele packages laden und/oder einige davon sogar erst noch installieren, weil man z.B. auf verschiedenen PCs arbeitet, dann bietet sich die `p_load` Funktion des `pacman` package an. Es lädt **und installiert, wenn nötig** eine vorgegebene Liste an packages:
<div class = "row"> <div class = "col-md-6">
```{r, warning=FALSE, message=FALSE}
# Ohne pacman package:
library(data.table)
library(dplyr)
library(forcats)
library(ggplot2)
library(ggfortify)
library(lme4)
library(lmerTest)
```
</div> <div class = "col-md-6">
```{r, warning=FALSE, message=FALSE}
# Mit pacman package:
library(pacman)
p_load(data.table, dplyr, forcats, ggplot2, ggfortify, lme4, lmerTest)
```
</div> </div>