Vorlesung 1

Heute bewusst ohne KI
Für diese erste Vorlesung lösen wir die Aufgaben ohne KI-Unterstützung. Für die Grundlagen ist der eigene Denkweg wichtiger; später im Kurs schauen wir uns gezielt an, wie man KI sinnvoll und kritisch einsetzt.
| Zeit | Inhalt |
|---|---|
| 08:30 - 10:00 | R und RStudio: Posit Workbench, Panes, Konsole, Editor, Tastenkürzel Orientierung, zwei Kurzübungen, kurze Arbeitsphase |
| 10:15 - 11:45 | Hilfe und Pakete: Hilfeseiten lesen, Beispiele ausführen, Paket-Hilfe, erste Funktionen Orientierung, zwei Kurzübungen, Arbeitsphase mit eigener Recherche |
| 12:30 - 14:00 | Objekte und Datenstrukturen: Zuweisungen, Environment, Vektoren, Matrizen, Listen, Data Frames, Faktoren mehrere Kurzübungen, zwei Arbeitsphasen, gemeinsame Besprechung |
| 14:15 - 15:45 | Logische Operatoren und Kontrollstrukturen: any, all, which, if, if / else if / else, ifelse, for, while, FizzBuzzmehrere Kurzübungen, zwei Arbeitsphasen, Transfer auf Daten |
| 16:00 - 17:30 | Eigene Funktionen und Kommentare: Funktionen definieren, Listen zurückgeben, Code strukturieren und dokumentieren zwei Kurzübungen, Abschlussaufgabe, Besprechung |
Pausen und Besprechungen nutzen wir, um offene Fragen direkt zu klären und den weiteren Ablauf bei Bedarf anzupassen.
Ctrl/Cmd + Enter: aktuelle Zeile oder Auswahl ausführenCtrl/Cmd + 1 und Ctrl/Cmd + 2: zwischen Editor und Konsole springenTipp
Dauerhafter Code gehört in den Editor. Von dort aus schicken Sie einzelne Zeilen oder markierte Blöcke gezielt in die Konsole.
log(7) und (15 + 3)^2.vorlesung1_start.R.me, drücken Sie Tab und schauen Sie sich die Vorschläge an.Esc.Ctrl/Cmd + 1, Ctrl/Cmd + 2 und Ctrl/Cmd + L aus.Tab für Code Completion testenEsc und Ctrl/Cmd + L bewusst ausprobierenvorlesung1_start.R.# Erste Schritte in RStudio.logg(7) und lesen Sie die Fehlermeldung.Merksatz
Die Konsole ist zum Ausprobieren da. Alles, was Sie später noch brauchen, sollte in einem Skript stehen.
?mean oder help(mean)help.search("weighted mean"), ??"weighted mean" oder apropos("mean")example(mean)help(package = "datasets")Description, Usage, Arguments, Exampleslibrary(...), installieren: install.packages(...)Hinweis
Wenn Sie eine Funktion noch nicht kennen, lesen Sie zuerst Description und Usage, danach Arguments und erst dann die Examples.
abs() macht.mean.Usage, Arguments und Examples.example(mean) ein Beispiel aus."weighted mean".apropos("mean") aus.DescriptionUsageArgumentsExamplessearch(), welche Pakete aktuell geladen sind.datasets.iris an.mtcars.class(iris) und class(iris$Species).datasets nicht geladen ist, laden Sie es bewusst mit library(datasets).datasets öffnendatasets.AirPassengers oder ChickWeight.class(...), welche Struktur der Datensatz hat, und zeigen Sie die ersten drei Einträge an.?funktion oder help(funktion) öffnen Sie eine bekannte Hilfeseite direkt.help.search(...), ?? oder apropos(...) suchen Sie nach unbekannten Funktionen.example(...) zeigt schnell, wie eine Funktion verwendet wird.help(package = "...") ist der richtige Einstieg für Datensätze und Paketüberblicke.Merksatz
Wenn der Funktionsname unbekannt ist: erst suchen, dann lesen, dann ein Beispiel ausführen.
<- zugewiesen.ls() sehen Sie alle Objekte, mit rm(...) löschen Sie gezielt.getwd() prüfen Sie das aktuelle Arbeitsverzeichnis.| Typ | Beschreibung | Typ prüfen / erzeugen | Beispiel |
|---|---|---|---|
numeric |
Dezimalzahlen | is.numeric(x), as.numeric(x) |
3.14 |
integer |
ganze Zahlen | is.integer(x), as.integer(x) |
5L |
logical |
Wahrheitswerte | is.logical(x), as.logical(x) |
TRUE |
character |
Textzeichenketten | is.character(x), as.character(x) |
"R" |
factor |
kategoriale Werte mit Levels | is.factor(x), factor(x) |
factor(c("rot", "blau")) |
Hinweis
Für eine erste Diagnose helfen mode(...), class(...) und str(...): zuerst den Typ prüfen, dann die Struktur lesen.
| Wert | Bedeutung | Typischer Anlass | Prüfen |
|---|---|---|---|
NA |
fehlender Wert | Beobachtung fehlt | is.na(x) |
NaN |
ungültiges Rechenergebnis | 0 / 0 |
is.nan(x) |
NULL |
leeres Objekt | Element fehlt vollständig | is.null(x) |
Inf, -Inf |
positive / negative Unendlichkeit | 1 / 0, -1 / 0 |
is.infinite(x) |
Achtung
Typkonvertierung kann Informationen verlieren oder neue fehlende Werte erzeugen, z. B. bei as.numeric(c("3", "R")).
| Struktur | Dimension | Homogen? | Typischer Inhalt | Erzeugung |
|---|---|---|---|---|
vector |
1D | ja | Werte eines Typs | c(1, 2, 3) |
matrix |
2D | ja | rechteckige Tabelle eines Typs | matrix(1:6, nrow = 2) |
list |
1D | nein | gemischte Objekte | list(a = 1:3, b = "R") |
data.frame |
2D | nein | tabellarische Beobachtungen mit verschiedenen Variablentypen | data.frame(x = 1:3, y = c("a", "b", "c")) |
Hinweis
factor ist keine eigene mehrdimensionale Datenstruktur, sondern ein spezieller Vektor für kategoriale Variablen.
| Dimension | Homogene Datentypen | Heterogene Datentypen |
|---|---|---|
1 dimensional |
vector |
list |
2 dimensional |
matrix |
data.frame |
Merksatz
Homogen bedeutet: Alle Elemente haben denselben atomaren Typ. Heterogen bedeutet: Verschiedene Typen dürfen nebeneinander vorkommen.
| Struktur | Syntax | Auswahl | Ergebnis |
|---|---|---|---|
vector |
x[1] |
erstes Element | Vektor der Länge 1 |
vector |
x[c(2, 4)] |
Elemente an Position 2 und 4 | Vektor |
vector |
x[x > 0] |
alle positiven Werte | Vektor |
matrix |
m[2, 3] |
Zelle in Zeile 2, Spalte 3 | einzelner Wert |
matrix |
m[, 2] |
gesamte zweite Spalte | Vektor |
matrix |
m[, 2, drop = FALSE] |
zweite Spalte, Struktur bleibt erhalten | Matrix mit einer Spalte |
| Struktur | Syntax | Auswahl | Ergebnis |
|---|---|---|---|
list |
l[1] |
erstes Element als Teilmenge | list |
list |
l[[1]] |
Inhalt des ersten Elements | Inhalt des Elements |
list |
l$Matrix |
benanntes Element | Inhalt des Elements |
data.frame |
df["Alter"] |
Spalte als Teilmenge | data.frame mit einer Spalte |
data.frame |
df[["Alter"]] |
Spalte direkt | Vektor oder Faktor |
data.frame |
df$Alter |
benannte Spalte direkt | Vektor oder Faktor |
data.frame |
df[1, ] |
erste Zeile | data.frame |
data.frame |
df[1, "Alter"] |
Zelle in Zeile 1, Spalte Alter |
einzelner Wert |
[], [[ ]] und $ bewusst wählen| Operator | Geeignet für | Idee | Standardrückgabe |
|---|---|---|---|
[] |
alle indexierbaren Strukturen | Teilmenge auswählen | Struktur bleibt meist erhalten |
[[ ]] |
list, data.frame |
genau ein Element holen | Inhalt des Elements |
$ |
benannte list, benannter data.frame |
benanntes Element holen | Inhalt des Elements |
Achtung
df["Alter"] bleibt ein Data Frame, df[["Alter"]] und df$Alter liefern die Spalte direkt. Wenn die Struktur erhalten bleiben soll, helfen bei Matrizen und Data Frames oft [] und bei Bedarf drop = FALSE.
str()factor speichert kategoriale Merkmale intern als Codes mit Labels.levels(...) zeigt und verändert Faktorstufen.str(...) macht Faktoren, Listen und Data Frames schnell lesbar.iris und mtcars zeigen gut, welche Variablen metrisch und welche kategorial sind.Achtung
as.numeric(automarke_factor) liefert die internen Codes der Levels und nicht die sichtbaren Labels.
x aus und berechnen Sie x^y.x mit dem Wert 7.ls() anzeigen.z mit rm(z) und prüfen Sie erneut mit ls().getwd() an.x und y und prüfen Sie, ob die Arbeitsumgebung leer ist.ls() und rm(...) bewusst einsetzengetwd() prüfen10000.quadrate <- (1:20)^2
m <- matrix(quadrate, nrow = 4, ncol = 5, byrow = FALSE)
df <- as.data.frame(m)m zu.m.df die ersten zwei Zeilen der Spalten V2 und V3 aus.class(df["V2"]), class(df[["V2"]]) und class(df$V2).m zusätzlich nur die zweite und vierte Spalte aus.[Zeile, Spalte] bei Matrix und Data Framedf["V2"], df[["V2"]] und df$V2 unterscheidenclass(...) prüfenl$Matrix zu.class(l["Matrix"]) und class(l[["Matrix"]]).l$Character aus.str(l).["Matrix"] und [[ "Matrix" ]] unterscheideniris und mtcarsstr(iris), welche Struktur iris hat.Species.Species anzeigen.autos <- mtcars.autos die Variablen cyl und am in Faktoren um.autos[, c("mpg", "cyl", "am")].autos, für die am == 1 gilt, und nur die Spalten mpg, cyl und am.str(...) lesenfactordatasetscyl, gear und am in Faktoren um.autos.auswahl mit allen Autos, für die mpg > 20 und am == 1 gilt.auswahl nur mpg, cyl, gear und am.class(auswahl["gear"]) und class(auswahl[["gear"]]).mpg in autos.str(iris), wie sich iris von mtcars unterscheidet.getwd(), wo Sie aktuell arbeiten.quadrate mit save(...) als Datei quadrate.RData.quadrate aus dem Environment.load(...).ls(), ob das Objekt wieder verfügbar ist.ls()rm(x)x[c(2, 4)]x[-c(1, 6)]m[2, 3] oder df[3, 2]data.frame: df["V2"]df[["V2"]] oder df$V2l[["Matrix"]]Merksatz
Bei Unsicherheit immer zuerst fragen: Will ich eine Teilmenge derselben Struktur oder genau den enthaltenen Wert?
TRUE oder FALSE.<, >, <=, >=, ==, !=, %in%any(), all(), which(), which.max()x > 3 kann einen ganzen logischen Vektor liefern.any(...) und all(...) verdichten einen Vektor wieder auf genau einen Wert.if (...) brauchen wir genau einen logischen Wert.Achtung
if (...) braucht genau ein TRUE oder FALSE. Für ganze Vektoren oder Spalten ist meist ifelse(...) die bessere Wahl.
if / else if / elseif prüft eine Bedingung und führt bei TRUE genau einen Zweig aus.else ergänzt den Fall, dass die Bedingung FALSE ist.else if erweitert die Entscheidung um weitere Fälle.ifelse(...) ist etwas anderes und arbeitet elementweise auf Vektoren.Merksatz
Mehrere Fälle formulieren Sie in R mit if / else if / else, nicht mit mehreren voneinander losgelösten if-Blöcken.
for und while im Vergleichfor eignet sich, wenn die Anzahl der Schritte oder ein Indexvektor vorher feststeht.while eignet sich, wenn eine Bedingung solange gelten soll, bis sie kippt.for initialisieren wir oft zuerst ein Zielobjekt und greifen dann mit [i] zu.while brauchen wir immer Startwert, Bedingung und Aktualisierung.Achtung
Eine while-Schleife endet nur, wenn sich die Bedingung im Schleifenkörper irgendwann wirklich ändert.
any(...), ob Werte kleiner als 2 enthalten sind.all(...), ob alle Werte ungleich 0 sind.which(...) die Positionen der Werte kleiner als 2 aus.%in%, ob 5:7 in x enthalten ist.which.max(...), an welcher Position das Maximum steht.any(...) und all(...)which(...), %in% und which.max(...)if / else if / else formulieren"nicht bestanden" für Werte unter 50, "bestanden" für Werte von 50 bis 89, "sehr gut" ab 90.status.punkte <- 42 und punkte <- 95.for-Schleifen mit Index sauber schreibendf <- data.frame(
Name = c("Mueller", "Meyer", "Schneider", "Meyer", "Meier"),
Alter = c(45, 23, 62, 32, 22)
)Geburtsjahr zunächst mit NA.Geburtsjahr mit einer for-Schleife und dem Referenzjahr 2026.ifelse(...) die Spalte Volljaehrig für Alter >= 18.[i]ifelse(...) und Schleife bewusst trennenwhile-Schleifen sicher verwendenwhile-Schleife, die jeden Monat 15 Euro zu betrag addiert.monate um 1.betrag mindestens 100 ist.betrag und monate aus.zahlen <- 1:30.if / else if / else: FizzBuzz bei Teilbarkeit durch 15, Fizz bei Teilbarkeit durch 3, Buzz bei Teilbarkeit durch 5, sonst die Zahl selbst.for-Schleife über alle Werte aus zahlen.1:30 aus.ausgabe <- character(length(zahlen)).%%.%% 15 == 0, dann 3, dann 5.kunden <- data.frame(
Name = c("Mueller", "Meyer", "Schneider", "Meyer", "Meier"),
Umsatz = c(120, 650, 430, 880, 210),
Newsletter = c(TRUE, TRUE, FALSE, TRUE, FALSE)
)ifelse(...) die Spalte VIP für den Fall Umsatz >= 500 und Newsletter == TRUE.which(...), welche Zeilen VIP == TRUE sind.if / else, das die Meldung "Es gibt VIP-Kunden" oder "Es gibt keine VIP-Kunden" in meldung speichert.Bonus an und füllen Sie sie mit einer for-Schleife: 20 für VIP-Kunden, sonst 5.Segment mit einer if / else if / else-Kaskade: "A" für Umsatz >= 800, "B" für Umsatz >= 400, sonst "C".any(...), ob ein Bonus größer als 10 ist, und mit all(...), ob alle Umsätze positiv sind.Segment am besten innerhalb derselben for-Schleife wie Bonus.any(...) und all(...) verdichten mehrere logische Werte auf genau einen Wert.if / else if / else passt für einzelne Entscheidungen mit zwei oder mehr Fällen.ifelse(...) passt für elementweise Vektorlogik.for passt für bekannte Wiederholungen oder einen festen Indexvektor.while passt für Wiederholungen mit offener Laufzeit und klarer Abbruchbedingung.if, ein fehlendes Update in while oder die falsche Reihenfolge bei FizzBuzz.Merksatz
Fragen Sie bei jeder Aufgabe zuerst: Entscheide ich einmal, elementweise für viele Werte oder wiederholt über mehrere Schritte?
return(...) zurückgegeben.list.# machen Code später nachvollziehbar.Tipp
Eine Funktion ist selbst ein Objekt. Sie können sie ohne Klammern anzeigen lassen, um ihren Code noch einmal zu prüfen.
rabatt_preis(preis, rabatt).return(...) zurück.preis = 80 und rabatt = 0.15.preis = 120 und rabatt = 0.25.return(...)rabatt_preis(...) in das Skript.# Rabattberechnung.auftragsbericht <- function(preis, kosten, menge) {
umsatz <- preis * menge
gesamtkosten <- kosten * menge
gewinn <- umsatz - gesamtkosten
# hier Status ergänzen
return(list(
umsatz = umsatz,
gesamtkosten = gesamtkosten,
gewinn = gewinn
))
}if / else if / else, das status auf "Verlust", "Break-even" oder "Gewinn" setzt.status zur Rückgabe-Liste hinzu.(preis, kosten, menge) mit (20, 25, 10), (20, 20, 10) und (30, 18, 10).$gewinn und $status.status, dann die Rückgabe, dann die Tests.$ eindeutig bleibt.Merksatz
Eine gute Funktion ist kurz, klar benannt, kommentiert und mit mehreren Beispielen geprüft.

Programmierung für Data Science – Vorlesung 1 – Prof. Dr. Michael Bücker