Data Science 1 - Programmieren & Visualisieren
Saskia Otto & Monika Eberhard
Universität Hamburg, IMF
Wintersemester 2024/2025
Typische Manipulationen | Kernfunktion in ‘dplyr’ |
---|---|
Manipuliere Beobachtungen (Zeilen) | filter() , arrange() |
Manipuliere Variablen (Spalten) | select() , rename() , mutate() , transmute() , |
Fasse Beobachtungen zusammen | summarise() |
Gruppiere Beobachtungen | group_by() , ungroup() |
Kombiniere Tabellen | bind_rows , bind_cols und join_ Funktionen |
(‘Linf’ = mittlere maximale Länge, ‘K’ = Rate in der sich der Fisch an ‘Linf’ annähert)
Mit freundlicher Genehmigung der Fotografen von fishbase.org (Konstantinos I. Stergiou, Jim Greenfield) und uwphoto.no(Rudolf Svensen).
arrange()
→ sortiert Zeilen (also Beobachtungen) nach spezifischen Variablen:
filter()
→ extrahiert Reihen, die ein logisches Kriterium erfüllen:
Verknüpfte Abfragen in filter()
werden mit Kommata aufgeführt (UND-Operator):
select()
→ extrahiert Spalten nach Namen oder mittels Helferfunktion:
select()
Quelle: ältere Version des sog. cheatsheets
Data Transformation with dplyr (lizensiert unter CC-BY-SA).
rename()
→ ändert die Namen einzelner Variablen (neuerName = alterName
):
mutate()
und transmute()
→ erstellen neue Variablen:
mutate()
/ transmute()
Sie können jede Berechnung mit einer Variablen machen, solange diese vektorisiert ist:
Quelle: ältere Version des sog. cheatsheets Data Transformation with dplyr (lizensiert unter CC-BY-SA).
Hilfreiches Tool
Bevor wir jetzt in die Datenmanipulation starten, werden wir ein sehr hilfreiches Werkzeug für verknüpfte Operationen kennenlernen!!!
%>%
|>
|>
arbeiten!|>
können diverse Funktionsaufrufe sequenziell miteinander verknüpfen werden, ohne Zwischenobjekte zu erstellen.|>
leitet den Inhalt des Objekts auf der linken Seite in den Ausdruck auf der rechten Seite.|>
| Wie?|>
| InterpretationErinnert doch fast an ein Kochrezept, oder?
|>
Kleiner Tipp:
Der Pipe-Operator lässt sich mit dem Shortcut strg (bzw. cmd) + shift + m automatisch schreiben.
Um den nativen Operator standardmäßig zu nutzen, muss vorweg unter
ein Häkchen gesetzt werden!
05:00
Wir wollen uns die Verteilung der Kelchblattlänge bei der Art Iris versicolor anschauen:
Gibt es eine Beziehung zwischen dem Längen/Breiten-Verhältnis bei Kron- und Kelchblättern der Art Iris setosa? Um dies grafisch untersuchen zu können, transformieren Sie den iris
Datensatz:
Erstellen Sie einen ‘tibble’ basierend auf dem iris
Datensatz, welcher nur die Spalte ‘Species’ enthält und eine neue (absteigend sortierte) Spalte mit dem Quotienten aus der Kelchblattlänge zu -breite. Der ‘tibble’ soll aber nur die Arten I. versicolor und I. virginica und Quotientenwerte größer 2 enthalten:
iris |>
mutate(sepal_lw = Sepal.Length/Sepal.Width) |>
filter(Species %in% c('versicolor', 'virginica'), sepal_lw > 2) |>
select(Species, sepal_lw) |>
arrange(desc(sepal_lw)) |>
as_tibble()
# A tibble: 79 × 2
Species sepal_lw
<fct> <dbl>
1 virginica 2.96
2 versicolor 2.82
3 virginica 2.75
4 versicolor 2.74
5 versicolor 2.73
6 virginica 2.73
7 virginica 2.68
8 virginica 2.64
9 virginica 2.57
10 virginica 2.53
# ℹ 69 more rows
summarise()
→ reduziert Variablen zu Einzelwerten:
Quelle: ältere Version des sog. cheatsheets
Data Transformation with dplyr (lizensiert unter CC-BY-SA).
Es gibt 2 sehr nützliche Funktionen, die man anstelle von summarise()
nutzen kann:
count()
→ zur Berechnung der Anzahl an Zeilendistinct()
→ zum Entfernen von Duplikaten (Zeilen mit komplett gleichem Inhalt in den jeweiligen Spalten)distinct()
# A tibble: 15 × 2
Species Sepal.Length
<fct> <dbl>
1 setosa 5.1
2 setosa 4.9
3 setosa 4.7
4 setosa 4.6
5 setosa 5
6 setosa 5.4
7 setosa 4.4
8 setosa 4.8
9 setosa 4.3
10 setosa 5.8
11 setosa 5.7
12 setosa 5.2
13 setosa 5.5
14 setosa 4.5
15 setosa 5.3
→ Wie Sie sehen, wurden die 50 Zeilen auf 15 reduziert.
iris
1Berechnung einer Statistik für mehrere Variablen gleichzeitig:
iris |>
summarise(
SL_mean = mean(Sepal.Length),
SW_mean = mean(Sepal.Width),
PL_mean = mean(Petal.Length),
PW_mean = mean(Petal.Width)
)
SL_mean SW_mean PL_mean PW_mean
1 5.843333 3.057333 3.758 1.199333
→ Viel Schreibarbeit wenn mehr als nur der Mittelwert berechnet werden soll…
across()
Berechnung einer Statistik für mehrere Variablen gleichzeitig:
across()
| 2Berechnung mehrerer deskriptiver Statistiken für alle kontinuierlichen Variablen → hier muss eine Liste dem .fns
Argument übergeben werden:
iris |>
summarise(
across(
.cols = Sepal.Length:Petal.Width,
.fns = list(mean = mean, median = median, sd = sd)
)
)
Sepal.Length_mean Sepal.Length_median Sepal.Length_sd Sepal.Width_mean
1 5.843333 5.8 0.8280661 3.057333
Sepal.Width_median Sepal.Width_sd Petal.Length_mean Petal.Length_median
1 3 0.4358663 3.758 4.35
Petal.Length_sd Petal.Width_mean Petal.Width_median Petal.Width_sd
1 1.765298 1.199333 1.3 0.7622377
…was ist, wenn wir die Statistiken für bestimmte Gruppen (wie hier die Arten) getrennt bestimmen wollen????
group_by()
nimmt eine existierende Tabelle und konvertiert sie in eine gruppierte Tabelle, in der Operationen gruppenweise durchgeführt werden können.ungroup()
entfernt Gruppierungen (bei summarise()
nicht nötig, aber bei z.B. count()
).iris
iris |>
group_by(Species) |> # einfach diesen Befehl einschieben
summarise(
across(
.cols = Sepal.Length:Petal.Width,
.fns = mean
)
)
# A tibble: 3 × 5
Species Sepal.Length Sepal.Width Petal.Length Petal.Width
<fct> <dbl> <dbl> <dbl> <dbl>
1 setosa 5.01 3.43 1.46 0.246
2 versicolor 5.94 2.77 4.26 1.33
3 virginica 6.59 2.97 5.55 2.03
iris
iris
05:00
Berechnen Sie pro Art: Median, Mittelwert, Standardabweichung und Minimalwert für die Kronblattlänge:
iris |>
group_by(Species) |>
summarise(
pl_median = median(Petal.Length),
pl_mean = mean(Petal.Length),
pl_sd = sd(Petal.Length),
pl_min = min(Petal.Length)
)
# A tibble: 3 × 5
Species pl_median pl_mean pl_sd pl_min
<fct> <dbl> <dbl> <dbl> <dbl>
1 setosa 1.5 1.46 0.174 1
2 versicolor 4.35 4.26 0.470 3
3 virginica 5.55 5.55 0.552 4.5
Berechnen Sie die Stichprobengröße (= Zeilenanzahl) pro Ernährungsgruppe im ChickWeight
Datensatz:
Rows: 578
Columns: 4
$ weight <dbl> 42, 51, 59, 64, 76, 93, 106, 125, 149, 171, 199, 205, 40, 49, 5…
$ Time <dbl> 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 21, 0, 2, 4, 6, 8, 10, 1…
$ Chick <ord> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, …
$ Diet <fct> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, …
bind_rows()
→ hängt 2 oder mehr Tabellen zeilenweise aneinander:
intersect()
, union()
, setdiff()
bind_cols()
→ hängt 2 oder mehr Tabellen spaltenweise aneinander:
XXX_join()
Funktionen!XXX_join()
→ Die Funktionsgruppe verbindet Tabellen basierend auf gleichen Werten in übereinstimmenden Spalten:
# ------------------------------ Vorbereitung ----------------------------------
#### Laden von Paketen
library(tidyverse) # laedt 9 Pakete
#### Eigene Funktionen
# -------------------- Import und Datenaufbereitung ----------------------------
# (analog zu Uebungswoche 1)
#### Import von TXT-Datei
# (-> Lektion L01 in DSB-03-Datenaufbereitung oder per Anleitung durchs Tidyversum)
daphnia <- read.table("daphnia.txt", sep = ",", header = TRUE)
#### Datensichtung
# (-> Lektion L02 in DSB-03)
# Betrachtung des Inhalts
daphnia
# View(daphnia)
head(daphnia) # zeigt erste 6 Zeilen (Kopfzeilen)
tail(daphnia) # zeigt letzte 6 Zeilen (Endzeilen)
# Identifikation der Objektklasse (Vektor, Matrix, dataframe,..)
class(daphnia)
# Ausgabe der Anzahl an Zeilen und Spalten
nrow(daphnia) # Anzahl Zeilen
ncol(daphnia) # Anzahl Spalten
dim(daphnia) # Anzahl aller Dimensionen
# Spaltennamen
names(daphnia)
# Datentyp pro Spalte
typeof(daphnia$round)
typeof(daphnia$pop.treatment)
# Alles auf einmal anzeigen lassen
str(daphnia)
# Bei kategorialen Variablen ist es sinnvoll sich alle Gruppen anzeigen zu lassen
unique(daphnia$round) # ist zwar numerisch, aber evtl. gibt es nur wenige Gruppen
unique(daphnia$exp_id)
unique(daphnia$clone)
unique(daphnia$pop.treatment)
# -> man kann diese Funktion auch auf alle Spalten gleichzeitig anwenden:
# mit der map() Funktion aus dem tidyverse Paket 'purrr'
# (bald im Kurs DSB-06-Fortgeschrittene Programmierung)
map(daphnia, ~unique(.))
#### Datentransformation
# (-> siehe Lektion L04-L06 in DSB-03 und L01-L02 in DSB-05-Handling spezieller Datentypen)
# Trennen der Spalte pop.treatment und Umkonvertierung von character zu factor
daphnia <- daphnia |>
separate(col = "pop.treatment", into = c("population", "treatment"), sep = "/") |>
mutate(population = as.factor(population), treatment = as.factor(treatment))
# Filtern und Anzahl Zeilen ausgeben
daphnia |>
filter(population == "popM", treatment == "control", survived_t14 == 0) |>
count() # -> bei 2 Zeilen trifft die Bedingung zu
starwars
: DS1_W08_Uebungsskript_Datentransformation.RSie sind jetzt so weit, …
inner_XXX()
Funktionen aus dem dplyr Paket zusammenführen können. Dies wird relevant für Aufgabe A2 und alle folgenden bei Fallstudie 1 und 3, Aufgabe B und alle folgenden bei Fallstudie 2, sowie für alle Aufgaben bei Fallstudie 4.
Cheatsheet zum tidyr Paket frei verfügbar unter diesem Link.
Enthält wichtigste Funktionen der Datenaufbereitung
Download Link (alternativ auch im Moodle-Kurs)
Dann testen Sie doch Ihr Wissen in folgendem Abschlussquiz…
Bei weiteren Fragen: saskia.otto(at)uni-hamburg.de
Diese Arbeit is lizenziert unter einer Creative Commons Attribution-ShareAlike 4.0 International License mit Ausnahme der entliehenen und mit Quellenangabe versehenen Abbildungen.
Kurswebseite: Data Science 1