
Data Science 1 - Programmieren & Visualisieren
Saskia Otto & Monika Eberhard
Universität Hamburg, IMF
Wintersemester
![]()
if..else.., ifelse() und case_when() formulieren können.for-Schleifen für wiederkehrende Aufgaben schreiben können.Eine komplette Übersicht der wichtigsten Funktionen gibt es hier:


Diese wie alle anderen DSB Cheatsheets gibt es auf Moodle und der DSB Website unter Ressourcen > Cheatsheets & Guides.

Faktoren sind Vektoren, die nur vorbestimmte Werte (Faktorstufen = levels) enthalten können, und werden für kategoriale Variablen verwendet. Intern sind sie ganzzahlige Vektoren mit den Attributen class (‘factor’) und levels.
Stellen Sie sich vor, Sie haben einen Vektor vom Typ ‘character’, der Monate enthält:
Es findet keine Sortierung in einer hilfreichen Art und Weise statt.
→ Ein einfaches factor(x1) oder as.factor(x1) löst die Probleme noch nicht – die Faktorstufen werden weiterhin alphabetisch sortiert.
factor()
Übergeben Sie dem Argument levels einen Vektor mit allen gültigen Faktorstufen in gewünschter Reihenfolge.
levels(f1) lassen Sie sich die gültigen Faktorstufen anzeigen.cut()Sichtbare Namen der Faktorstufen umbenennen mit 'labels'
[1] 12 4 1 3
Levels: 1 2 3 4 5 6 7 8 9 10 11 12
→ labels wird immer zusammen mit levels angegeben und muss dieselbe Länge und Reihenfolge haben: Das erste Label benennt die erste Faktorstufe um, das zweite die zweite usw.

fct_rev()fct_infreq()fct_inorder()fct_collapse()fct_reorder()fct_relevel()p <- bshydro15 |> ggplot() +
guides(x = guide_axis(angle = 45)) +
theme(text = element_text(size = 16))
p1 <- p + geom_bar(aes(month)) + ggtitle("Standardeinstellung")
p2 <- p + geom_bar(aes(fct_rev(month))) + ggtitle("fct_rev()")
p3 <- p + geom_bar(aes(fct_infreq(month))) + ggtitle("fct_infreq()")
p4 <- p + geom_bar(aes(fct_collapse(
month,
q1 = c("Jan", "Feb", "Mar"),
q2 = c("Apr", "May", "Jun"),
q3 = c("Jul", "Aug", "Sep"),
q4 = c("Oct", "Nov", "Dec")
))) +
xlab("annual quarter") +
ggtitle("fct_collapse()")
gridExtra::grid.arrange(p1, p2, p3, p4, nrow = 2)
![]()
![]()

unclass() zeigt die Anzahl der TAGE bzw. SEKUNDEN seit dem 1. Januar 1970 (00:00:00).Date → repräsentiert nur Kalenderdaten (in Tibbles: <date>)POSIXct → repräsentiert Kalenderdaten und Uhrzeit bis zur Sekunde, einschließlich Zeitzone (in Tibbles: <dttm>)
Datum- und Zeitangaben werden beim Import oft nicht automatisch erkannt, sondern als ‘character’ eingelesen. Das Paket lubridate (seit tidyverse 2.0 ein Kernpaket) macht die Umwandlung einfach:
ymd(), ydm(), mdy(), myd(), dmy(), dym()Eine der 6 Datumfunktionen kombinieren mit:
_h → nur Stunde_hm → Stunde und Minute_hms → Stunde, Minute und Sekunde[1] "2026-11-17 12:11:00 UTC"
[1] "2026-11-17 12:11:59 CET"
→ Ohne tz Argument wird die Zeitzone UTC (Coordinated Universal Time) angenommen.

year(), semester(), quarter()month(), week()mday() - day of the monthyday() - day of the yearwday() - day of the weekhour(), minute(), second()Zwischen POSIXct und Date wechseln Sie mit as_date() und as_datetime() – dabei kann Information (die Uhrzeit) verloren gehen.
![]()
![]()
Folgender Tibble enthält mehrere Datum- bzw. Datum/Zeit-Variablen, die aber alle als ‘character’ Datentyp vorliegen:
# A tibble: 10 × 5
x1 x2 x3 x4 x5
<chr> <chr> <chr> <chr> <chr>
1 2015-07-26 2015/26/07 Jul 26, 2015 2015-07-26 18:16:00 26.07.2015T18:16
2 2015-07-03 2015/03/07 Jul 03, 2015 2015-07-03 16:42:00 03.07.2015T16:42
3 2015-09-01 2015/01/09 Sep 01, 2015 2015-09-01 04:45:00 01.09.2015T04:45
4 2015-06-03 2015/03/06 Mar 03, 2015 2015-06-03 08:08:00 03.06.2015T08:08
5 2015-10-15 2015/15/10 Oct 15, 2015 2015-10-15 21:05:00 15.10.2015T21:05
6 2015-10-01 2015/01/10 Oct 01, 2015 2015-10-01 10:38:00 01.10.2015T10:38
7 2015-03-14 2015/14/03 Mar 14, 2015 2015-03-14 05:55:00 14.03.2015T05:55
8 2015-02-25 2015/25/02 Jun 25, 2015 2015-02-25 08:12:00 25.02.2015T08:12
9 2015-06-03 2015/03/06 Sep 03, 2015 2015-06-03 11:09:00 03.06.2015T11:09
10 2015-09-14 2015/14/09 Jul 14, 2015 2015-09-14 05:38:00 14.09.2015T05:38
# A tibble: 10 × 5
x1 x2 x3 x4 x5
<date> <date> <date> <dttm> <dttm>
1 2015-07-26 2015-07-26 2015-07-26 2015-07-26 18:16:00 2015-07-26 18:16:00
2 2015-07-03 2015-07-03 2015-07-03 2015-07-03 16:42:00 2015-07-03 16:42:00
3 2015-09-01 2015-09-01 2015-09-01 2015-09-01 04:45:00 2015-09-01 04:45:00
4 2015-06-03 2015-06-03 2015-03-03 2015-06-03 08:08:00 2015-06-03 08:08:00
5 2015-10-15 2015-10-15 2015-10-15 2015-10-15 21:05:00 2015-10-15 21:05:00
6 2015-10-01 2015-10-01 2015-10-01 2015-10-01 10:38:00 2015-10-01 10:38:00
7 2015-03-14 2015-03-14 2015-03-14 2015-03-14 05:55:00 2015-03-14 05:55:00
8 2015-02-25 2015-02-25 2015-06-25 2015-02-25 08:12:00 2015-02-25 08:12:00
9 2015-06-03 2015-06-03 2015-09-03 2015-06-03 11:09:00 2015-06-03 11:09:00
10 2015-09-14 2015-09-14 2015-07-14 2015-09-14 05:38:00 2015-09-14 05:38:00

Auch wenn Sie keine aufwendige Textanalyse vorhaben, kann es für Sie hilfreich sein Wissen über die Handhabung und Verarbeitung von Zeichenketten in R zu haben!

Sie möchten z.B.
→ In stringr (Teil des tidyverse) starten alle Funktionen mit str_ und haben konsistente Argumente.

str_to_lower() str_to_upper() str_to_sentence() str_to_title() [1] "the difference" "between stupidity" "and genius is that"
[4] "genius has its limits."
[1] "THE DIFFERENCE" "BETWEEN STUPIDITY" "AND GENIUS IS THAT"
[4] "GENIUS HAS ITS LIMITS."
[1] "The difference" "Between stupidity" "And genius is that"
[4] "Genius has its limits."
[1] "The Difference" "Between Stupidity" "And Genius Is That"
[4] "Genius Has Its Limits."

sepal.length sepal.width petal.length petal.width species
1 5.1 3.5 1.4 0.2 setosa
2 4.9 3.0 1.4 0.2 setosa
3 4.7 3.2 1.3 0.2 setosa
4 4.6 3.1 1.5 0.2 setosa
5 5.0 3.6 1.4 0.2 setosa
6 5.4 3.9 1.7 0.4 setosa

str_trim() → Entfernt ‘white space’ am Anfang und Ende einer Zeichenkette.Anwendungsbeispiel: Kategorien mit Leerzeichen bereinigen
'data.frame': 34 obs. of 3 variables:
$ station : chr "ER1 " "ER2 " "ER3 " "ER4 " ...
$ zinc : chr "BACK " "HIGH " "HIGH " "MEDIUM " ...
$ diversity: num 2.27 1.25 1.15 1.62 1.7 0.63 2.05 1.98 1.04 2.19 ...
[1] "BACK " "HIGH " "MEDIUM " "LOW "
[1] "BACK" "HIGH" "MEDIUM" "LOW"

str_c(..., sep = "", collapse = NULL) → Fügt 2 oder mehr Skalare oder Vektoren (egal welcher Datentyp!) elementweise zu einem Zeichenvektor zusammen.
[1] "A + B"
[1] "The difference between stupidity and genius is that genius has its limits."
[1] "A.1, B.2, C.3"


Deskriptive Statistiktabelle
iris |> mutate(
Species = str_c("Iris ", Species)) |>
group_by(Species) |>
summarise(
slm = round(mean(Sepal.Length), 1),
sls = round(sd(Sepal.Length), 2),
slms = str_c(slm, sls, sep=" ± ")
) |>
select(Species, slms) |>
knitr::kable(
col.names = c("Species",
"Mean Sepal Length (± st.dev)")
) # erstellt Tabellen in LaTeX, HTML| Species | Mean Sepal Length (± st.dev) |
|---|---|
| Iris setosa | 5 ± 0.35 |
| Iris versicolor | 5.9 ± 0.52 |
| Iris virginica | 6.6 ± 0.64 |


str_replace() | 1str_replace() | 2 [1] "Cruise" "Station"
[3] "Type" "yyyy.mm.ddThh.mm"
[5] "Latitude..degrees_north." "Longitude..degrees_east."
[7] "Bot..Depth..m." "PRES..db."
[9] "TEMP..deg.C." "PSAL..psu."
[11] "DOXY..ml.l."
[1] "cruise" "station" "type"
[4] "yyyy_mm_ddthh_mm" "latitude_degrees_north" "longitude_degrees_east"
[7] "bot_depth_m" "pres_db" "temp_deg_c"
[10] "psal_psu" "doxy_ml_l"

Adaptiert vom RegEx cheatsheet von Ian Kopacka.
![]()
![]()
[1] "Placement in the"
[2] "genus is provisional pending"
[3] "the discovery of juvenile specimens."

In der Abfrage können neben Operatoren auch Funktionen verwendet werden, solange diese TRUE oder FALSE zurückgeben.
if (Abfrage) {
mache folgendes
}
if (Abfrage) {
mache dies
} else {
mache das
}
Wenn bei der Abfrage TRUE rauskommt, wird die (erste) Anweisung ausgeführt.
ifelse()→ ifelse() erzeugt hier nicht eine Farbe, sondern einen Farbvektor mit einem Eintrag pro Datenpunkt: wenn ‘setosa’, dann “blue”, ansonsten “red”.
case_when()if.. → else if.. → else.. verschachteln.case_when():
.default verwendet.# A tibble: 87 × 6
name height mass gender species type
<chr> <int> <dbl> <chr> <chr> <chr>
1 Luke Skywalker 172 77 masculine Human other
2 C-3PO 167 75 masculine Droid robot
3 R2-D2 96 32 masculine Droid robot
4 Darth Vader 202 136 masculine Human large
5 Leia Organa 150 49 feminine Human other
6 Owen Lars 178 120 masculine Human other
7 Beru Whitesun Lars 165 75 feminine Human other
8 R5-D4 97 32 masculine Droid robot
9 Biggs Darklighter 183 84 masculine Human other
10 Obi-Wan Kenobi 182 77 masculine Human other
# ℹ 77 more rows
Auf älteren dplyr-Versionen (< 1.1.0) gibt es .default noch nicht; dort wird stattdessen TRUE ~ "other" als letzte Zeile verwendet.
![]()
![]()
Der Körper einer Bedingung (wie auch Schleife und Funktion) wird immer in geschweifte Klammern gesetzt, damit er über mehrere Zeilen gehen kann.
In der Abfrage muss ein Operator stehen, welcher die Abfrage wahr macht, denn der Codeblock in der Bedingung wird ja ausgeführt. Richtig ist daher:
Anhand der zweimaligen geschweiften Klammern wird deutlich, dass es sich um eine ‘if..else..’ Bedingung handelt.
An der Ausgabe 0 ist zu erkennen, dass der Alternativbefehl (in ‘else’) ausgeführt wurde. In die zweite Lücke muss daher ein Operator, bei dem die Abfrage FALSE ergibt:

Eine Schleife enthält Code (den Schleifenkörper), der wiederholt ausgeführt wird. So muss der Code nicht zehnmal geschrieben werden, wenn er zehnmal ausgeführt werden soll. Schleifen können beliebig verschachtelt werden.

for): führen eine bestimmte Anzahl an Wiederholungen aus, die durch einen Zähler kontrolliert wird.while) bzw. fußgesteuerte Schleifen (repeat): laufen, solange eine logische Bedingung erfüllt ist. Achtung: Ändert sich die Bedingung nie, entsteht eine Endlosschleife!
for Schleife | Struktur 1
for Schleife | Struktur 2for Schleife | Stile
for Schleife | Bestes Vorgehenc() wachsen, wird die Schleife bei vielen Wiederholungen sehr langsam.seq_along(): Ist der Vektor leer, führt 1:length() trotzdem Iterationen aus (mit Fehlern oder NAs), seq_along() dagegen keine.![]()
[1] "file_001.csv" "file_002.csv" "file_003.csv" "file_004.csv" "file_005.csv"
[6] "file_006.csv" "file_007.csv" "file_008.csv" "file_009.csv" "file_010.csv"
Import aller 10 Dateien und Zusammenführung zu EINEM Dataframe
# Leere Liste für die importierten Datensätze
data_list <- vector("list", length = length(files))
# Schleife, bei der in jeder Iteration eine Datei importiert wird
for (i in seq_along(files)) {
data_list[[i]] <- read.csv(files[i])
}
# Zusammenfügen der einzelnen Dataframes in der Liste
data_df <- dplyr::bind_rows(data_list)'data.frame': 200 obs. of 3 variables:
$ station: chr "A" "A" "A" "A" ...
$ x : int 40 24 23 12 46 48 34 35 36 41 ...
$ y : num 28.93 14.49 1.67 9.51 20.64 ...
# A tibble: 10 × 2
# Groups: station [10]
station n
<chr> <int>
1 A 20
2 B 20
3 C 20
4 D 20
5 E 20
6 F 20
7 G 20
8 H 20
9 I 20
10 J 20
![]()
![]()
Hier ist keine Abfrage zu sehen, sondern es wird jeweils ein Zähler definiert. Also muss es sich um die Zählschleife (‘for..’) handeln, und zwar um 2 ineinander verschachtelte. Wichtig ist hierbei, dass der Zähler unterschiedlich ist: Die erste Schleife hat meist den Index i, die nächste j, usw.
Im innersten Schleifenkörper werden die beiden Indizes mit paste() und dem Trennzeichen ‘/’ zusammengefügt. Damit dies in der Konsole sichtbar ist, braucht es die Funktion print().

Eine Funktion ist eine Sammlung von Code, die jederzeit über ihren Namen aufgerufen werden kann. Funktionen strukturieren die Arbeit und unterteilen komplexe Probleme in kleine, einfache Einheiten.
Funktion mit Argument
[1] "Hi Anne!"
Error in sag_hi() : argument "name" is missing, with no default
\[g_1 = \frac{\frac{1}{n}\sum\limits_{i=1}^{n}\left(x_i - \bar{x}\right)^3} {\left(\frac{1}{n}\sum\limits_{i=1}^{n}\left(x_i - \bar{x}\right)^2\right)^{3/2}}\]

Eine Funktion gibt immer nur ein Objekt zurück. Sollen mehrere Ergebnisse ausgegeben werden, fassen Sie diese mit list() zu einem Listenobjekt zusammen, z.B. return(list(mean = m, sd = s)).
Was machen wir, wenn der Vektor NAs enthält?
![]()
![]()
Eine Funktion wird mit function() definiert. Sie sollte nicht auf Objekte zugreifen, die nicht innerhalb der Funktion definiert oder als Argument übergeben werden. Hier wird auf x und y zugegriffen, daher müssen diese als Argumente definiert werden (function(x, y)). Das berechnete Produkt z wird explizit mit return(z) ausgegeben.

for Schleifen lassen sich in eine Funktion packen, der man dann eine andere Funktion als Argument übergibt.
Die ‘*apply’ Familie in base R (apply(), lapply(), sapply(), …) und die ‘map’ Familie im tidyverse-Paket purrr wenden eine Funktion auf jedes Element einer Liste, jede Spalte eines Datensatzes usw. an – ohne eine Schleife schreiben zu müssen:

lapply()$Sepal.Length
[1] 5.1 4.9 4.7 4.6 5.0 5.4 4.4 4.8 4.3 5.8 5.7 5.2 5.5 4.5 5.3 7.0 6.4 6.9 6.5
[20] 6.3 6.6 5.9 6.0 6.1 5.6 6.7 6.2 6.8 7.1 7.6 7.3 7.2 7.7 7.4 7.9
$Sepal.Width
[1] 3.5 3.0 3.2 3.1 3.6 3.9 3.4 2.9 3.7 4.0 4.4 3.8 3.3 4.1 4.2 2.3 2.8 2.4 2.7
[20] 2.0 2.2 2.5 2.6
$Petal.Length
[1] 1.4 1.3 1.5 1.7 1.6 1.1 1.2 1.0 1.9 4.7 4.5 4.9 4.0 4.6 3.3 3.9 3.5 4.2 3.6
[20] 4.4 4.1 4.8 4.3 5.0 3.8 3.7 5.1 3.0 6.0 5.9 5.6 5.8 6.6 6.3 6.1 5.3 5.5 6.7
[39] 6.9 5.7 6.4 5.4 5.2
$Petal.Width
[1] 0.2 0.4 0.3 0.1 0.5 0.6 1.4 1.5 1.3 1.6 1.0 1.1 1.8 1.2 1.7 2.5 1.9 2.1 2.2
[20] 2.0 2.4 2.3
$Species
[1] setosa versicolor virginica
Levels: setosa versicolor virginica

![]()
![]()

Alle Aufgaben der Übungswoche finden Sie im Handbuch:

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