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.
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