Häufigste Funktionen

Daten vorbereiten

In aller Regel sind Vorarbeiten am Datensatz notwendig, um Analyseschritte durchzuführen. Diese Schritte sind oft von großer Bedeutung und auch recht zeitintensiv.

Es gibt einige Pakete, die das Bearbeiten von Datensätzen ermöglichen. Eines der bekanntesten und aufgrund seiner Verständlichkeit oft genutzten Pakete ist dplyr. Die Idee hinter dplyr ist das zum einen nur Tabellen (data frames oder tibbles) verarbeitet werden und zum anderen die Verarbeitung über das sogenannte pipen erleichtert wird. Der Code wird in dplyr in eine lange Kette gefasst, was zuerst eventuell unnötig erscheint. Aber dadurch ist der Code gut lesbar und es müssen nur wenige Funktionen gelernt werden, die aber in Kombination die gängigsten Verarbeitungsschritte abbilden können. Durch diese Zerlegung in Teilschritte haben wir in den einzelnen Funktionen einen umgrenzten Funktionsumfang, der leicht verständlich ist. Durch die Kombination mehrer Funktionen können aber auch komplexere Schritte vollzogen werden. Auch liefern Funktionen aus dem Paket dplyr immer einen tibble (Tabelle) aus.

Die umfangreiche Dokumentation zu dplyr findet sich hier.

Häufigste Funktionen

Die häufigsten Funktionen, die mit dplyr genutzt werden sind die folgenden:

Funktion Operation
select() Spalte(n) wählen
slice() Zeile(n) wählen
filter() Zeile(n) filtern
arrange() Zeile(n) ordnen
mutate() neue Spalten / Variablen
summarize() Werte zusammenfassen
group_by() gruppieren

Diese werden dir nun Schritt für Schritt vorgestellt, bevor wir das piping, das zweite Prinzip von dplyr kennenlernen. Diese Beispiele sind in gewisserweise künstlich, da man dplyr fast ausschließlich mit piping nutzt. Für das Verständnis der Funktionen ist es aber hilfreich, diese erstmal vorab kennenzulernen.

In allen Beispiel nutzen wir einen fiktiven Datensatz, der die Studienmotivation (mot) von Studierenden der Universitäten Gießen, Marburg und Frankfurt abgefragt hat.

Einen Überblick in den Datensatz gibt es erstmal hier:

Im Datensatz wurde u.a. die Zufriedenheit mit der Demokratie (stfdem), der Distrikt (district), das Vertrauen in das Parlament (trstprl) und das Geschlecht (gndr) abgefragt.

Das package dplyr kann einzeln geladen werden, es empfiehlt sich aber das package tidyverse zu laden, das weitere Pakete wie ggplot2 direkt mitlädt.

# install.packages(
#   "tidyverse", 
#   dependencies = TRUE
# )
library("tidyverse")

select()

Mit der select() Funktion können einzelne oder mehrere Spalten aus einem Datensatz ausgewählt werden. Die Ausgabe ist immer ein tibble.

Im Beispiel wollen wir uns nur die Variablen Geschlecht (gndr) und den Distrikt (district) anzeigen lassen.

head(pss)
##    idno   district   gndr agea         edu wkhtot     income stfdem stfeco
## 1 10000 Distrikt 1   male   41 ES-ISCED IV     34 7th decile      7      6
## 2 10001 Distrikt 1   male   65 ES-ISCED II     20 6th decile      8      7
## 3 10002 Distrikt 1   male   48 ES-ISCED IV     27 7th decile      6      6
## 4 10003 Distrikt 1 female   49  ES-ISCED V     30 6th decile      5      4
## 5 10004 Distrikt 1 female   48 ES-ISCED IV     29 5th decile      4      5
## 6 10005 Distrikt 1 female   64  ES-ISCED V     30 6th decile      6      6
##   trstprl trstprt trstplt trstlgl lrscale
## 1       3       5       4       6       4
## 2       5       5       5       4       3
## 3       4       4       6       5       6
## 4       2       7       4       3       6
## 5       6       6       6       6       2
## 6       1       3       2       4       7
select(
  pss,
  c(
    gndr, 
    district
  )
)

slice()

Dagegen können wir mit slice() einzelne Zeilen ausgeben lassen. So zum Beispiel Zeile \(50\) bis \(55\) oder in Kombination mit der Funktion seq() jede \(100.\) Zeile.

slice(
  pss,
  50:55
)
##    idno   district   gndr agea          edu wkhtot     income stfdem stfeco
## 1 10049 Distrikt 1 female   65  ES-ISCED II     30 4th decile      5      7
## 2 10050 Distrikt 1 female   47  ES-ISCED IV     30 5th decile      5      2
## 3 10051 Distrikt 1 female   57 ES-ISCED III     21 5th decile      4      5
## 4 10052 Distrikt 1   male   42  ES-ISCED IV     27 9th decile      3      5
## 5 10053 Distrikt 1 female   47 ES-ISCED III     38 5th decile      5      5
## 6 10054 Distrikt 1 female   43 ES-ISCED III     42 2nd decile     10      6
##   trstprl trstprt trstplt trstlgl lrscale
## 1       6       5       6       7       7
## 2       2       5       7       4       5
## 3       5       6       2       4       3
## 4       5       4       5       5       5
## 5       4       3       0       5       2
## 6       8       5       7       4       3
slice(
  pss, 
  seq(
    0, 
    1000,
    100
  )
)
##     idno   district   gndr agea          edu wkhtot     income stfdem stfeco
## 1  10099 Distrikt 1 female   53         <NA>     41 7th decile      5      6
## 2  10199 Distrikt 1   male   58 ES-ISCED III     39 5th decile      6      5
## 3  10299 Distrikt 1 female   45 ES-ISCED III     29 5th decile      4      6
## 4  10399 Distrikt 1 female   63 ES-ISCED III     37 5th decile      7      6
## 5  10499 Distrikt 1 female   56  ES-ISCED IV     38 6th decile      5      5
## 6  10600 Distrikt 1   male   71  ES-ISCED II     44 5th decile      7      7
## 7  10700 Distrikt 1   male   70 ES-ISCED III     30 6th decile      4      6
## 8  10800 Distrikt 1   male   75  ES-ISCED II     48 5th decile      8      6
## 9  10900 Distrikt 1   male   67  ES-ISCED II     48 3rd decile      4      4
## 10 11000 Distrikt 1 female   69 ES-ISCED III     41 5th decile      4      5
##    trstprl trstprt trstplt trstlgl lrscale
## 1        1       4       4       8       8
## 2        6       4       4       5       8
## 3        7       3       6       2       5
## 4        4       5       6       6       8
## 5        3       5       4       7       6
## 6        5       4       4       4       7
## 7        3       7       7       3       8
## 8        5      10       4       5       6
## 9        3       3       4       3       5
## 10       6       3       5       4       7

filter()

Neben der Auswahl von bestimmten Zeilen (Fällen) oder Spalten (Variablen) können wir mit filter() den Datensatz eingrenzen. So können wir zum Beispiel uns nur die Fälle anzeigen lassen, die in Distrikt 1 leben.

filter(
  pss, 
  district == "Distrikt 1"
)

Auch können wir mehrere Bedingungen einführen. Zum Beispiel nur Personen, die in Distrikt 5 leben und männlich (male) sind.

filter(
  pss,
  district == "Distrikt 5" & gndr == "male"
)

Alle bereits bekannten logischen Verbindungen funktionieren auch hier. Zur Erinnerung hier nochmal die logischen Konnektoren:

  • logisches und: &

  • logisches oder: |

  • logisches gleich: ==

  • logisches ungleich: !=

  • logisches größer: >

  • logisches kleiner: <

  • logisches kleiner gleich: <=

  • logisches größer gleich: >=

arrange()

Zur Ordnung von Datensätzen kann die Funktion arrange() genutzt werden. Hierbei kann man entweder aufsteigend oder absteigend sortieren lassen. Zum Beispiel nach den Arbeitsstunden:

pssAsc <- arrange(
  pss, 
  wkhtot
)
head(pssAsc)
##    idno   district   gndr agea         edu wkhtot     income stfdem stfeco
## 1 20438 Distrikt 5   male   37 ES-ISCED II      6 6th decile      4      4
## 2 10078 Distrikt 1   male   54 ES-ISCED IV      7 9th decile      6      4
## 3 20249 Distrikt 5   male   48 ES-ISCED IV      7 9th decile      5      5
## 4 10072 Distrikt 1   male   52 ES-ISCED IV      8 9th decile      2      5
## 5 10757 Distrikt 1   male   37 ES-ISCED IV      9 8th decile      4      5
## 6 20103 Distrikt 5 female   25 ES-ISCED IV      9 6th decile      3      0
##   trstprl trstprt trstplt trstlgl lrscale
## 1       6       5       4       3       3
## 2       1       7       3       7       9
## 3       4       5       4       6       6
## 4       3       1       4       2       7
## 5       4       6       4       5       7
## 6       1       5       3       4       1

Über die Funktion desc() innerhalb von arrange()werden die Fälle absteigend sortiert. desc steht für descending, also absteigend. Alternativ kann man einfach ein Minuszeichen vor den Variablennamen setzen und erhält ebenfalls absteigend sortierte Fälle.

pssDesc <- arrange(
  pss,
  desc(wkhtot)
)

head(pssDesc)
##    idno    district   gndr agea          edu wkhtot     income stfdem stfeco
## 1 40446 Distrikt 10   male   63         <NA>     65 1st decile      5      6
## 2 50618 Distrikt 12 female   51         <NA>     63 2nd decile      5      6
## 3 50494 Distrikt 12 female   NA  ES-ISCED II     62 2nd decile      3      4
## 4 50491 Distrikt 12 female   NA ES-ISCED III     60 4th decile      5      4
## 5 20294  Distrikt 5   male   59 ES-ISCED III     59 6th decile      7      8
## 6 40525 Distrikt 10   male   40  ES-ISCED II     59 4th decile      3      7
##   trstprl trstprt trstplt trstlgl lrscale
## 1       2       2       9       5       7
## 2       5       4       6       4       5
## 3       3       3       4       2       1
## 4       3       6       6       6       3
## 5       6       4       7       3       5
## 6       1       3       4       1       4
# Alternativ Minuszeichen vor Variable
pssDesc2 <- arrange(
  pss, 
  -wkhtot
)

mutate()

Um neue Variablen zu berechnen oder eine Variable zu rekodieren, wird mutate() verwendet. Wir berechnen im Beispiel eine Variable, die die Differenz zur durchschnittlichen Arbeitszeit innerhalb unserer Erhebung ausgibt.

mutate(
  pss, 
  wkhtotCen = wkhtot - mean(wkhtot, na.rm = TRUE)
)

Wenn wir Dummy- oder kategoriale Variablen neu erschaffen möchten, benötigen wir die Funktion case_when() zusätzlich. In der Funktion case_when() gibt man hierarchisch fest, welche Bedingung geprüft und wie rekodiert werden soll. Wir könnten zum Beispiel die Variable district recoden und aus der character-Variable eine integer-Variable machen. Wichtig hierbei ist, dass die Überprüfung wie in einer if-Bedingung nacheinander geprüft werden. Dabei sollte man von der spezifischten Bedingung zur allgemeinen Bedingung codieren (andernfalls gibt es unsinnige Variablen!).

mutate(
  pss,
  districtRec = case_when(
    district == "Distrikt 1" ~ 1, 
    district == "Distrikt 5" ~ 5, 
    district == "Distrikt 7" ~ 7,
    district == "Distrikt 10" ~ 10, 
    district == "Distrikt 12" ~ 12,
  )
)

Auch können hierbei mehrere Bedingungen verknüpft werden: Jetzt wollen wir einen Dummy berechnen, der anzeigt, ob Personen in Distrikt 12 leben und weiblich (female) sind.

mutate(
  pss, 
  d12gndr = case_when(
    district == "Distrikt 12" & gndr == "female" ~ 1
  )
)

In diesem Beispiel haben wir jetzt nur die eine Bedingung für den Wert 1 auf der neuen Variable angegeben. Wie wir sehen, wird dann allen anderen Fälle automatisch NAzugeordnet. Wir wollen aber allen anderen Fällen den Wert 0 zuordnen. Um jetzt nicht die verschiedenen Kombinationen aufschreiben zu müssen bedienen wir uns eines weiteren Arguments der Funktion case_when():

mutate(
  pss, 
  d12gndr = case_when(
    district == "Distrikt 12" & gndr == "female" ~ 1,
    TRUE ~ 0
  )
)

Mit dem Argument TRUE ~ 0 legen wir fest, dass alle anderen Werte den Wert 0 zugeordnet bekommen. So müssen nicht alle anderen Kombinationen als Code geschrieben werden.

summarize()

Die Funktion summarize() erlaubt es uns aus Spalten einen Wert zusammenzufassen. So zum Beispiel den Mittelwert einer Spalte.

summarize(
  pss, 
  mean(wkhtot)
)
##   mean(wkhtot)
## 1      34.3008

Nutzbar ist jede Funktion, die eine Spalte als Input verlangt: Also unter anderen first(), last(), nth(), n(), n_distinct(), IQR(), min(), max(), mean(), median(), var() und sd().

group_by()

Oft haben wir in Datensätzen kategoriale Variablen nach denen wir den Datensatz gruppieren wollen. So könnten wir zum Beispiel den Datensatz nach dem Studienfach gruppieren. Dies machen wir mit der Funktion group_by():

group_by(
  pss,
  gndr
)

Scheinbar hat sich im Datensatz nichts geändert, aber hier ist der wichtige Unterschied zu arrange(): group_by() sortiert nicht den Datensatz, sondern gruppiert den Datensatz. Die Ausgabe ändert sich daher nicht. Wenn wir uns zum Beispiel den Mittelwert der Semester nach Studiengang anzeigen lassen möchten, verketten wir group_by() und summarize() (weiter unten machen wir das eleganter mit dem Piping-Operator):

summarize(
  group_by(
    pss, 
    gndr
  ), 
  mean(wkhtot)
)
## # A tibble: 2 × 2
##   gndr   `mean(wkhtot)`
##   <fct>           <dbl>
## 1 female           34.5
## 2 male             34.1

Hier sehen wir nun was group_by() macht: Anstatt eines Mittelwertes erhalten wir hier nun vier Mittelwerte (für jeden Studiengang im Datensatz einen). Wichtig: Das Gruppieren sollte immer im Nachfolgenden mit der Funktion ungroup() gelöst werden.