1 + 8
R Tutorial (Teil 1): Grundlagen
Wie funktioniert dieses Tutorial?
Dieses Tutorial ist für alle Studierenden gedacht, die noch nie mit R und RStudio gearbeitet haben oder die sich eine Auffrischung wünschen, bei der es nochmal mit den absoluten Basics losgeht. Das Tutorial ist so geschrieben, dass Sie Schritt für Schritt durch die wichtigsten Grundlagen geführt werden, die Ihnen die Arbeit mit dem Statistikprogramm R ermöglichen. In allen unseren Lehrveranstaltungen und in vielen Veranstaltungen anderer Lehr- und Forschungseinheiten (z.B. die Empras) ist es notwendig, eine statistische Software wie R zu verwenden. R stellt damit ein wichtiges Handwerkszeug für das empirische Arbeiten dar, das Ihnen nicht nur hilft, gelehrte Inhalte besser zu verstehen, sondern Ihnen auch ermöglicht, selbst statistische Analysen durchzuführen. Bevor wir also inhaltlich in unseren Vorlesungen in die Statistik einsteigen, sollen Sie sich hier mit den Grundlagen von R vertraut machen.
In diesem Tutorial werden wir Ihnen Schritt für Schritt die Struktur und die grundlegende Funktionsweise von R und RStudio erläutern. Sie werden zwischendrin immer wieder Kästen unterschiedlicher Farben entdecken:
In den blauen Kästen geben wir nützliche Hinweise, die die Arbeit mit R und RStudio genauer erläutern.
In den grünen Kästen behandeln wir weiterführende Themen zur Funktionalität von R und RStudio. Wenn Sie wollen, können Sie diese Kästen beim ersten Durchlauf überspringen, damit es Ihnen leichter fällt den Überblick über die Basics zu behalten.
In den gelben Kästen weisen wir Sie auf Fallstricke und mögliche Fehlerquellen hin. Versuchen Sie sich diese Punkte besonders einzuprägen, damit R immer das tut was Sie möchten.
In den orangen Kästen finden Sie eine Reihe von Übungsaufgaben. Bitte führen Sie alle Übungen selber an Ihrem eigenen Computer durch.
Wie benutzen Sie dieses Tutorial?
R zu lernen ist genauso wie eine neue Sprache zu lernen. Man muss die Inhalte immer wieder wiederholen, bis das Gelernte in der Praxis selbstständig angewendet werden kann. Seien Sie nicht zu streng zu sich selbst und erwarten Sie nicht, dass Sie nach dem ersten Durchlauf des Tutorials bereits alle Inhalte verinnerlicht haben. Unser Tutorial soll Sie dazu animieren, die gelehrten Inhalte gleich auszuprobieren. Deshalb haben wir den Text und unsere Beispiele immer wieder ergänzt durch Bilder und kleine GIFs (kurze Videos ohne Ton), die die Arbeit mit dem Programm erläutern. Ein ganz wichtiger Teil des Tutorials sind außerdem die Übungen, die in den roten Kästen präsentiert werden. Im ersten dieser Kästen werden wir Sie gleich dazu auffordern, die gezeigten Programme auf Ihrem eigenen Computer zu installieren. Unsere Erfahrung zeigt, dass das Erlernen von R und RStudio nur dann funktioniert, wenn Sie von Anfang an versuchen, selbst damit zu arbeiten und die Inhalte regelmäßig wiederholen.
Bitte tun Sie das auch! Es wird sich auf jeden Fall lohnen!
1 Erste Schritte in R und R-Studio
R, wie wir es verwenden, besteht aus zwei Programmen: R und RStudio. R und RStudio sind nicht das Gleiche, bauen aber aufeinander auf.
Was ist R?
- Programmiersprache mit Fokus auf Statistik, open-source und kostenlos
- Der “Motor”, das Programm, das all unsere Berechnungen ausführt
- Kann alles, was wir brauchen (und noch viel mehr)
- Sollte regelmäßig upgedated werden
Was ist RStudio?
- Zusätzliches Programm (Editor) zur einfacheren Bedienung von R, open-source und kostenlos
- Greift im Hintergrund auf R zu, funktioniert also nicht ohne Installation von R
- Kann also alles was R auch kann, ist aber benutzerfreundlicher
- Sollte regelmäßig upgedated werden
1.1 Installation
Wenn Sie einen privaten Computer nutzen ist es hilfreich und notwendig zu wissen, wie man Programme darauf installiert. Die einzelnen Schritte dazu hängen von Ihrem jeweiligen Modell ab. Da es sehr viele verschiedene Computer- und Betriebssystemmodelle gibt, können wir hier nicht für jede Variante eine genaue Anleitung zur Programminstallation anbieten.
Bitte machen Sie sich also soweit mit Ihrem Gerät vertraut, dass Sie auch Programme (“Apps”) wie R und RStudio installieren und verwenden können.
Die folgenden Schritte geben eine kleine Übersicht über die häufigsten Wege der Programminstallation:
Installation auf Computern mit Windows-Betriebssystem
Installationsdateien werden bei Windows normalerweise als ausführbare Datei mit der Dateiendung “.exe” heruntergeladen. Durch einen Doppelklick auf diese Datei wird das Installationsprogramm gestartet und Sie müssen nur noch den Anweisungen auf dem Bildschirm folgen.Installation auf Computern mit Mac-Betriebssystem
Auf einem Mac gibt es bei heruntergeladenen Installationsdateien zwei Varianten, bei denen sich die folgenen Schritte unterscheiden. Diese Varianten erkennen Sie an der jeweiligen Dateiendung, die entweder “.pkg” (z.B. beim Programm R) oder “.dmg” (z.B. beim Programm RStudio) ist.
Dateiendung pkg
- Doppelklick im Ordner „Downloads“ auf die heruntergeladene Installationsdatei (sie wird als geöffnetes Postpaket dargestellt).
- Die auf dem Bildschirm angezeigten Anweisungen befolgen.
Dateiendung dmg
- Herunterladen der DMG-Datei: Die meisten Programme werden über die Webseite des Herstellers als .dmg-Datei heruntergeladen. Diese Datei finden Sie danach normalerweise im „Downloads“-Ordner oder auf dem Desktop.
- Öffnen der DMG-Datei: Doppelklicken Sie auf die heruntergeladene DMG-Datei, um sie zu „mounten“. Ein neues Fenster mit dem Programmsymbol erscheint. Falls kein Fenster erscheint, prüfen Sie Ihren Desktop - ein „virtuelles Laufwerk“ wird dort angezeigt.
- Drag-and-Drop: Ziehen Sie das Programmsymbol in den „Programme“-Ordner im Finder. Dieser Schritt kopiert die Anwendung fest auf Ihr System.
- Entfernen des virtuellen Laufwerks: Klicken Sie nach dem Kopieren mit der rechten Maustaste auf das virtuelle Laufwerk auf dem Desktop und wählen Sie „Auswerfen“ oder drücken Sie CMD+E, um das Laufwerk sicher zu entfernen.
- Sicherheitsabfragen: Wenn Sie eine Anwendung öffnen, die aus dem Internet heruntergeladen wurde, könnte es sein, dass macOS eine Sicherheitswarnung anzeigt. Bestätigen Sie, dass Sie die Anwendung vertrauen, indem Sie auf „Öffnen“ klicken.
Installation auf Computern mit Linux-Betriebssystem
Wenn Sie Linux als Betriebssystem nutzen, ist eine Anleitung dieser Art für Sie vermutlich nicht notwendig… ;-)Um R zu installieren, klicken wir hier und dann auf 1: Install R. Dann müssen wir die richtige Version für unser Betriebssystem auswählen, herunterladen und (wie jedes andere Programm auch) installieren.
Um im Anschluss RStudio zu installieren, klicken wir hier und dann auf 2: Install RStudio. Damit sollte automatisch die richtige Version für unser Betriebssystem heruntergeladen werden, die wir dann (wie jedes andere Programm auch) installieren können.
Installieren Sie R und RStudio auf Ihrem Computer.
Hinweis: Leider ist eine Installation auf Tablets mit iOS oder Android Betriebssystem nicht möglich. Sie benötigen also einen Laptop oder Desktop-Computer. Ob Sie Mac-, Windows- oder Linux-Nutzerin sind, ist völlig egal. Es ist sehr wichtig, dass Sie eine Möglichkeit finden, wie Sie R auf Ihrem eigenen Gerät nutzen können. Wenn Sie keine Möglichkeit finden, wenden Sie sich bitte an uns, vielleicht finden wir dann eine Lösung. Der Nutzen des nachfolgenden Tutorials ist nahezu Null, wenn Sie nicht selbst versuchen, die gezeigten Übungen zu lösen.
R und RStudio sollten regelmäßig aktualisiert werden, um sicherzustellen, dass wir die neuesten Funktionen und Sicherheitsupdates nutzen. RStudio erinnert uns normalerweise automatisch, wenn ein Update verfügbar ist. Diese Erinnerung von RStudio können Sie nutzen, um ebenfalls eine neue Version von R zu installieren. Leider gibt es von R selbst keine automatische Erinnerung.
Weder R noch RStudio können automatisch geupdated werden. Um R und RStudio zu aktualisieren, besuchen wir einfach erneut die Website von oben und laden die neueste Version herunter, so als würden wir das Programm gerade zum ersten mal installieren.
R kann auf Mac einfach über die bestehende Version installiert werden. Auf Windows müssen wir die alte Version manuell deinstallieren (z.B. über Start > Einstellungen > Apps > Apps &-Features), falls wir verhindern wollen, dass wir mehrere Versionen von R gleichzeitig installiert haben. Normalerweise findet RStudio aber automatisch die neueste Version von R, wenn Sie RStudio einmal komplett schließen und wieder neu öffnen.
RStudio kann normalerweise sowohl bei Mac als auch bei Windows über die bestehende Version installiert werden, ohne dass wir die alte Version manuell löschen müssen.
Nach der Installation von R und RStudio arbeiten wir nur noch mit RStudio. R selbst müssen wir zu keinem Zeitpunkt öffnen (wenn Sie wollen, können Sie die Desktopverknüpfung zu R direkt löschen, um Verwechslungen mit RStudio zu vermeiden).
Als nächstes öffnen wir RStudio, indem wir auf die RStudio Verknüpfung auf dem Desktop, im Startmenü bei Windows oder im Finder unter Programme bei Mac klicken. Wenn wir RStudio zum ersten mal öffnen, gliedert sich die Ansicht in die folgenden drei Bereiche:
1.2 R als Taschenrechner
Wenn wir RStudio geöffnet haben, können wir in das Fenster namens Console (unten links) direkt R Befehle/Code eingeben und ausführen lassen. Zum Einstieg verwenden wir R wie einen Taschenrechner, um einfache Rechnungen auszuführen. Tippen Sie…
…in die Console und bestätigen Sie die Eingabe mit der Enter
- oder Return
-Taste (↵).
Alle R-Befehle, die wir in der Console oder in Skripten (was das ist, sehen wir später) ausführen, werden in diesem Tutorial in grauen Kästen stehen:
1 + 8
[1] 9
Direkt unterhalb dieser Kästen steht der Output (das Ergebnis) des ausgeführten Befehls, der nach Tastendruck auf die ↵ Taste in der Console in der nächsten Zeile erscheint. Vor dem Ergebnis wird immer [1]
angezeigt. Warum das so ist können wir erstmal ignorieren.
Den Code innerhalb der grauen Blöcke können Sie kopieren, indem Sie mit der Maus über die obere rechte Ecke des Kastens fahren und auf das Kopiersymbol klicken. Anschließend können Sie den Code bei sich in der Console (oder im Skript) mit dem Befehl command + v beim Mac oder Strg + v bei Windows einfügen.
Code von der Website kopieren

Wir können mit den Symbolen auf unserer Tastatur schon die wichtigsten Rechenarten ausführen:
Symbol auf der Tastatur | Rechnung/Operation |
---|---|
+ |
Addition |
- |
Subtraktion |
* |
Multiplikation |
/ |
Division |
^ |
Exponentiation (Potenz) |
. |
Angabe von Dezimalstellen |
( und ) |
Struktur der Rechnung (Klammersetzung) |
sqrt() |
Quadratwurzel |
log() |
(Natürlicher) Logarithmus |
7 / 8
Lösung
[1] 0.875
1.6 * 7
Lösung
[1] 11.2
log(54)
Lösung
[1] 3.988984
3^2
Lösung
[1] 9
3 + 6) * 4 (
Lösung
[1] 36
3 + 7 * 4
Lösung
[1] 31
1.3 Logische Vergleiche
Wir können in R zwei Zahlen miteinander vergleichen und feststellen, ob diese gleich oder ungleich sind. Wir können auch überprüfen, ob eine Zahl größer oder kleiner ist als eine andere Zahl. Eine solche Frage wird dann in R mit entweder Ja (TRUE
) oder Nein (FALSE
) beantwortet. Solche Vergleiche werden logische Vergleich genannt und sind auch nicht nur auf Zahlen beschränkt (mehr dazu später).
Wenn wir uns zum Beispiel dafür interessieren, ob die Zahl 7 größer ist als die Zahl 3 können wir dies mit dem Code 7 > 3
herausfinden:
7 > 3
[1] TRUE
Da 7 tatsächlich größer ist als 3, erhalten wir von R die Antwort TRUE
.
Symbol auf der Tastatur | Rechnung oder Operation |
---|---|
== |
Gleich |
!= |
Ungleich |
> bzw. < |
Größer bzw. Kleiner |
>= bzw. <= |
Größer oder gleich bzw. Kleiner oder gleich |
Zur Überprüfung, ob zwei Zahlen identisch sind, muss man den Operator ==
verwenden und erhält den Rückgabewert TRUE
(ja, die Zahlen sind identisch) oder FALSE
(nein, die Zahlen sind nicht identisch). Das einfache =
weist einer Variable einen Wert zu (dazu später mehr).
8 > 7
Lösung
[1] TRUE
3 > 4
Lösung
[1] FALSE
3 <= 4
Lösung
[1] TRUE
4 >= 4
Lösung
[1] TRUE
6 == 7
Lösung
[1] FALSE
6 != 7
Lösung
[1] TRUE
8 != 8
Lösung
[1] FALSE
Neben den einfachen logischen Vergleichen von oben ist es auch möglich, mehrere logische Vergleiche miteinander zu kombinieren. Als Verknüpfung sind vor allem das logische UND sowie das logische ODER relevant.
Symbol auf der Tastatur | Operation | Bedeutung |
---|---|---|
& |
logisches UND | Sind beide Vergleiche wahr? |
| |
logisches ODER | Ist mindestens einer der Vergleiche wahr? |
Als Antwort eines kombinierten logischen Vergleichs erhält man erneut entweder den Rückgabewert TRUE
oder FALSE
. Um sicherzugehen, dass R alle Symbole in der von uns gewünschten Reihenfolge auswertet, kann es sinnvoll sein Klammern zu setzen.
Beispiel 1:
Ist die Zahl 7 größer als 5 UND ist die Zahl 9 kleiner als 8?
7 > 5) & (9 < 8) (
[1] FALSE
Beispiel 2:
Ist die Zahl 7 größer als 5 ODER ist die Zahl 9 kleiner als 8 (oder beides)?
7 > 5) | (9 < 8) (
[1] TRUE
1.4 Datentypen Teil 1
Im folgenden wollen wir Ihnen die wichtigsten Datentypen vorstellen, denen wir bei unserer Arbeit mit R begegnen werden.
numeric, integer, double
Wie wir in Abschnitt 1.2 gesehen haben, können wir in R mit dem Datentyp “Zahl” umgehen. Intern wird dafür der Begriff numeric verwendet. Es gibt manchmal Situationen, in denen R weiter unterscheidet ob es sich um eine ganze Zahl (integer) oder eine Dezimalzahl (double) handelt. Mit jedem dieser drei Datentypen können mathematische Berechnungen vorgenommen werden. Für unsere Anwendungen ist es in der Regel egal, ob eine Zahl von R als numeric, integer oder double verstanden wird. Wir werden die Unterschiede daher nicht im Detail besprechen.
logical
Im Abschnitt 1.3 haben wir dann nach einem logischen Vergleich eine Information erhalten, die nur zwei Ausprägungen haben kann: TRUE
oder FALSE
. Diese Informationen haben in R den Datentyp logical. Ist für einen Wert nun der Datentyp logical hinterlegt, weiß R, dass eben nur diese beiden Ausprägungen möglich sind.
Tatsächlich sind auch mit dem Datentyp logical manche mathematischen Berechnungen möglich. Wie kann das sein? Intern wird der logische Wert TRUE
als \(1\) verstanden, der Wert FALSE
als 0. Damit müsste die Berechnung TRUE
\(+\) TRUE
\(= 2\) ergeben:
TRUE + TRUE
[1] 2
Diese Eigenschaft logischer Werte mag zunächst mal sinnfrei erscheinen. Wir können sie uns jedoch an vielen Stellen zu Nutze machen. Zum Beispiel könnten wir in einer beliebig großen Menge an logischen Werten einfach alle Elemente addieren, um herauszufinden, wie viele Elemente dieser Menge die Ausprägung TRUE
haben.
character (string)
Eine weitere wichtige Funktion von R ist der Umgang mit Text. Text kann dabei unterschiedlich lang sein (ein Buchstabe, ein Name, ein Absatz, ein ganzes Buch). Dadurch dass Text eine beliebige Länge haben kann, die Reihenfolge der einzelnen Buchstaben jedoch ungeheuer wichtig ist (sonst wäre der Text ja nicht lesbar), spricht man von Zeichenketten. Die Übersetzung dieses Begriffs auf Englisch wäre character string. Deshalb findet sich in R für Text häufig die Bezeichnung character oder string die synonym verwendet werden.
Durch die beliebige Länge eines Texts ist es notwendig, eindeutig zu markieren, wo die Zeichenkette beginnt und wo sie aufhört. Das machen wir mit Anführungszeichen ""
die wir um den Text herumlegen.
"Das ist mein Text"
[1] "Das ist mein Text"
Mit Text können natürlich keine sinnvollen mathematischen Berechnungen angestellt werden, weshalb der Versuch dazu zur Fehlermeldung führt, dass ein Teil der Berechnung keine Zahl (non-numeric
) ist:
"Das ist mein Text" + 1
Error in "Das ist mein Text" + 1: non-numeric argument to binary operator
1.5 Zuweisungen
Alles womit wir in R arbeiten können wird auch als Objekt bezeichnet. Das Ergebnis eines logischen Vergleichs ist beispielsweise ein Objekt vom Typ logical. Häufig wollen wir Objekte nicht nur einmalig und unmittelbar durch die Ausführung eines Befehls erstellen, sondern mit ihnen an späterer Stelle noch weiter rechnen. Dafür können wir mit einer so genannten Zuweisung bewusst Objekte mit von uns vergebenen Namen erstellen. Wir können dann die erstellten und benannten Objekte verwenden, ohne den ursprünglichen Befehl noch einmal ausführen zu müssen.
Die Zuweisung erfolgt mit dem Zuweisungspfeil <-
(ein “kleiner” Zeichen, direkt gefolgt von einem “Minus”). Links vom Pfeil steht der Objektname, mit dem wir später auf den Inhalt des Objekts zugreifen, rechts vom Pfeil die Operation, die uns als Ergebnis den Inhalt liefert, den wir zwischenspeichern wollen. Sobald wir das Objekt erstellt haben, ist es im Environment-Fenster (oben rechts in RStudio) zu finden. Hier sind dann auch nützliche Informationen zum Objekt angegeben, wie beispielsweise auch der Datentyp des Objekts.
Ein Beispiel
Wir wollen die Operation \(\sqrt{x}\) für \(x = 7\) einmal ausführen und das Ergebnis in einem Objekt mit dem Namen “A” abspeichern. Der Programmiervorgang ist typischerweise:
- Objektnamen bestimmen
- Zuweisungspfeil
- Auszuführende Operation
<- sqrt(7) A
Zuweisung

Wenn wir herausfinden wollen, ob die Zuweisung funktioniert hat und das Objekt A
nun den Zahlenwert der Quadratwurzel von \(7\) hat, können wir das Objekt A
einfach ausführen. Das heißt, wir geben A
nach der Zuweisung in die Console ein und drücken auf die Enter
-Taste:
<- sqrt(7)
A A
[1] 2.645751
Wenn wir jetzt nur den Befehl rechts von der Zuweisung ausführen, sehen wir als Ergebnis den gleichen Zahlenwert:
sqrt(7)
[1] 2.645751
Wenn wir den Zuweisungsbefehl in der Console durchführen, wird nicht angezeigt welcher konkrete Wert genau zugewiesen wurde. Mit dem Zuweisungsbefehl
<- sqrt(7) A
haben wir R nur angewiesen, die Zuweisung durchzuführen. Wir haben nicht den Befehl gegeben, den konkreten Wert anzuzeigen. Angezeigt wird der Inhalt des Objekts nur dann, wenn wir entweder das Objekt links vom Zuweisungspfeil A
, oder den Befehl rechts des Zuweisungspfeils sqrt(7)
in die Console eintippen und durchführen.
A
[1] 2.645751
sqrt(7)
[1] 2.645751
Ein Objekt kann auch überschrieben werden indem ihm mit dem Zuweisungspfeil ein neuer Inhalt zugewiesen wird. Das alte Objekt ist dann allerdings verloren. Bei der Objektzuweisung müssen wir also aufpassen, ob wir den gewählten Namen schon an anderer Stelle verwenden und ob wir das Objekt wirklich endgültig überschreiben wollen. Eine Übersicht bietet das Environment-Fenster, da dort alle bisher erstellen Objekte zusammengefasst sind.
Es wird empfohlen, möglichst eindeutige und sinnhafte Objektbezeichnungen zu wählen, um direkt zu wissen, was der Inhalt des Objekts ist. Z.B. pers_ID <- 123456
für die Zuweisung einer Personen-ID an ein Objekt.
Die Benennung von Objekten ist inhaltlich dem Nutzer überlassen. Vergeben Sie die Namen, die für Sie den Inhalt des benannten Objekts am besten beschreiben. Allerdings sind dabei einige Zeichen nicht erlaubt. Ein Objektname darf in der Regel keine Leerzeichen oder Bindestriche enthalten und nicht mit einer Ziffer oder einem Unterstrich beginnen.
Erlaubt:
<- 4
mein_Objekt <- 4
mein.Objekt <- 4
mein2tesObjekt <- 4 ObjektNummer2
Nicht Erlaubt:
<- 4
mein Objekt -Objekt <- 4
mein2tesObjekt <- 4
<- 4 _ObjektNummer2
Zusätzlich zu den oben genannten Regeln gibt es einige ganz bestimmte Wörter, die als Objektnamen nicht erlaubt sind, weil sie für besondere Objekte reserviert sind. Die Liste aller reservierten Wörter können Sie mit dem folgenden Befehl anzeigen lassen.
?Reserved
- Berechnen Sie \(16^3\) und weisen Sie das Ergebnis dem Objekt \(z\) zu.
- Berechnen Sie die Quadratwurzel von \(z\) und weisen Sie das Ergebnis dem Objekt \(y\) zu.
- Berechnen Sie den natürlichen Logarithmus von \(y\) und weisen Sie das Ergebnis dem Objekt \(x\) zu.
- Führen Sie die Schritte 1 - 3 ohne die Zuweisungen der Zwischenergebnisse in einer Zeile Code durch und vergleichen Sie das Ergebnis mit dem in \(x\) gespeicherten Wert.
Lösung
<- 16 ^ 3
z <- sqrt(z)
y <- log(y)
x x
[1] 4.158883
log(sqrt(16 ^ 3))
[1] 4.158883
Natürlich ist es auch möglich, alle anderen Datentypen einem Objekt zuzuweisen. Speichern wir beispielsweise Text in einem Objekt, so hat dieses Objekt dann den Typ character
, wie uns die Information im Environment-Fenster verrät.
Character-Objekt erstellen

2 Reproduzierbares Arbeiten mit RStudio
2.1 R Skripte
Bisher haben wir in der Console programmiert. Theoretisch würde dies ausreichen, um alle Funktionen von R zu nutzen. Das Vorgehen ist jedoch nicht zu empfehlen! Sobald wir RStudio schließen, gehen unsere Berechnungen verloren und sind nicht so einfach reproduzierbar.
Die Verwendung von R in der Console ist in etwa so, als würden wir für die Dekorierung unseres Ballsaals unserem Butler James über den Gang immer wieder einzelne Arbeitsaufträge zurufen, die James dann auch jedes Mal sofort erledigt. Etwas effizienter wäre es in diesem Bild, wenn wir uns überlegen, was wir gerne erledigt haben möchten und eine Liste mit Aufträgen schreiben. Wir drücken dann James diese Liste in die Hand und er erledigt einen Auftrag nach dem Anderen in der Reihenfolge in der sie auf der Liste stehen.
Das hat den Vorteil, dass wir auch am nächsten Tag noch mal auf die Liste schauen können um herauszufinden, welche einzelnen Arbeitsschritte nötig waren um den Ballsaal exakt so zu dekorieren wie beim letzten Mal.
Ein solches Vorgehen wählen wir auch bei der Verwendung von R. Die Liste mit Arbeitsaufträgen für unseren Butler R nennt man hier Skript.
Skript erstellen
Um ein neues Skript zu erstellen, klicken wir oben links in der Titelleiste auf File > New File > R Script. Alternativ können wir in RStudio oben links auf klicken und R Script auswählen. Das neue Skript öffnet sich im linken oberen Bildschirmbereich.
Skript erstellen

Als wir RStudio nach der Installation das erste Mal geöffnet haben, konnten wir feststellen, dass sich der Bildschirm in drei Bereiche gliedert. Nach dem Erstellen eines Skriptes taucht nun ein vierter Bereich oben links auf:
Das folgende GIF zeigt, wie wir die Größe der einzelnen Fenster in RStudio beliebig verändern können.
Fenstergröße verändern

Man kann die Console auch auf der rechten Bildschirmseite neben dem Skript anordnen. Dies kann nützlich sein, wenn wir sowohl das Skript- als auch das Konsolenfenster groß ausgeklappt sehen wollen. Um die Console rechts anzuordnen gehen wir in die Menüleiste > Tools > Globlal Options > Pane Layout. Hier können wir die Fensteranordnung auswählen und mit Apply bestätigen.
Console rechts anordnen

Im Skript können wir jetzt der Reihe nach alle Befehle schreiben, die wir gerne ausführen möchten. Im Gegensatz zur Console wird durch das Drücken der Enter
-Taste der Befehl jedoch nicht ausgeführt, sondern es kommt einfach ein Zeilenumbruch und wir können einen weiteren Befehl in die nächste Zeile schreiben.
Das Skript ist also eine Sammlung von Befehlen, die für ein bestimmtes Ziel in einer festen Reihenfolge (Zeile für Zeile von oben nach unten) durchgeführt werden
Möchten wir eine Zeile des Skriptes ausführen, können wir den Cursor in diese Zeile setzen (z.B. indem wir mit der Maus irgendwo in die Zeile klicken) und dann
- die Tastenkombination Strg + Enter (engl: Ctrl-Return) drücken. Auf einem Mac funktioniert auch command + Enter.
- im Skript-Fenster oben rechts auf
klicken.
Möchten wir mehrere Zeilen oder bestimmte Teile einer oder mehrerer Zeilen ausführen, können wir auch die gewünschten Befehle markieren und dann mit Variante 1 (Strg + Enter) oder 2 (Klick auf ) ausführen.
Skript ausführen
Öffnen Sie ein neues Skript in RStudio
Kopieren Sie die folgenden Zeilen und fügen Sie diese in das neue Skript ein.
<- 4 x <- 5 y + y # Addition 1 x <- x + y x + y # Addition 2 x
Markieren Sie alle gerade eingefügten Zeilen im Skript und führen Sie den Code mit Strg-Enter (Mac: command-Enter) aus. Was fällt Ihnen auf?
Lösung
<- 4 x <- 5 y + y # Addition 1 x
[1] 9
<- x + y x + y # Addition 2 x
[1] 14
Addition 1 und 2 ergeben zwei unterschiedliche Ergebnisse, weil dazwischen der Wert
x
verändert wird.Vertauschen Sie die dritte (
x + y
) und vierte Zeile (x <- x + y
), markieren Sie den gesamten Code erneut und führen Sie ihn aus. Was fällt Ihnen auf?Lösung
<- 4 x <- 5 y <- x + y x + y # Addition 1 x
[1] 14
+ y # Addition 2 x
[1] 14
Addition 1 und 2 ergeben nun die gleichen Ergebnisse, weil der Wert
x
nun vor der ersten Addition verändert wurde. Obwohl insgesamt die gleichen Befehle ausgeführt wurden, macht die Reihenfolge der Befehle einen entscheidenden Unterschied.
Skript abspeichern
Um ein Skript abzuspeichern, stehen uns mehrere Möglichkeiten zur Verfügung:
- In der Menüleiste: File > Save
- Mit der Tastenkombination Strg + s (Windows und Mac) oder command + s (nur Mac)
- In R Studio unter dem Symbol
in der linken oberen Ecke.
Kommentare
Oft ist es sinnvoll, Kommentare in unser Skript einzubauen, damit andere Personen oder wir selber später nachvollziehen können, was berechnet wurde.
Kommentare schreiben wir hinter ein #
Zeichen. Bei der Ausführung des Codes weiß R dann, dass es sich dabei um einen Kommentar handelt, und führt die Zeile nicht aus.
# hier wird 4 hoch 5 berechnet
4 ^ 5
[1] 1024
Bei Kommentaren die über mehr als eine Zeile gehen, muss zu Beginn jeder Zeile ein #
stehen. Es ist auch möglich, direkt hinter einen ausführbaren Befehl einen Kommentar zu schreiben:
4 ^ 5 # hier wird 4 hoch 5 berechnet
[1] 1024
Wir sehen, dass nur der Code vor dem #
ausgeführt wird.
Wenn Sie R neu lernen, macht es durchaus Sinn mit Kommentaren festzuhalten, was die Befehle in Ihrem Skript bewirken. Je besser Sie sich mit R auskennen, desto seltener brauchen Sie solche Kommentare, da die Information was Ihr Code tut streng genommen aus den Befehlen selbst hervorgeht (schließlich könnten Sie durch eigene Recherche jederzeit wieder herausfinden, wie die Befehle funktionieren). Umso nützlicher sind daher Kommentare, warum ein bestimmter Code notwendig ist um das Ziel Ihrer Analyse zu erreichen (und warum Sie nicht z.B. einen anderen Weg gewählt haben). Solche Informationen sind nicht sofort aus dem Code selbst ersichtlich und es ist immer wieder erstaunlich, wie schnell man vergisst, was man sich damals dabei gedacht hat als man etwas programmiert hat.
2.2 Umgang mit dem Workspace
Wenn wir in R arbeiten, erstellen wir dabei in der Regel verschiedene Objekte (z.B. x <- 42
), die dann in unserem Environment Fenster in RStudio angezeigt werden. Irgendwann sind wir für heute fertig mit unserer statistischen Analyse und wollen RStudio gerne schließen. Schließen wir RStudio, werden wir vom Programm gefragt, ob wir den Workspace, der alle unsere R Objekte aus dem Environment Fenster (und noch ein paar andere Sachen) enthält, speichern wollen.
Im Gegensatz zu unserem R Skript wollen wir den Workspace (in 99% der Fälle) nicht speichern!
- Nur was in unserem R Skript steht ist reproduzierbar! Wenn wir zwischendurch in der R Console Dinge ausprobiert, in unserem Skript Befehle gelöscht oder angepasst haben, wissen wir nicht mehr genau, wie die Objekte im Environment zustande gekommen sind.
- Daher ist es gute Praxis, sich selbst zu zwingen, dass alle für die Analyse notwendigen und speicherwürdigen Schritte im Skript enthalten sind und dass wir jedes mal wenn wir mit R arbeiten mit einer “frischen” Arbeitsumgebung (= leeres Environment) starten.
Wenn wir RStudio das nächste mal öffnen und wir hätten beim Schließen den Workspace gespeichert, würden alle R Objekte vom letzten mal automatisch wieder geladen. Das mag auf den ersten Blick vielleicht praktisch erscheinen, führt in der Praxis jedoch sehr häufig zu Problemen.
Workspace Einstellungen anpassen
Wir können in den Einstellungen von RStudio festlegen, dass…
- beim Öffnen kein Workspace geladen werden soll und
- beim Schließen von RStudio der Workspace nicht gespeichert wird und wir auch nicht mehr danach gefragt werden.
Dafür klicken wir in RStudio auf Tools > Global Options und wählen die in der Abbildung blau markierten Einstellungen aus.
Passen Sie wie beschrieben die Workspace Einstellungen in RStudio an.
Erstellen Sie mindestens ein R Objekt, z.B. mit dem Befehl
x <- 10
. Schließen Sie RStudio und beobachten Sie, dass Sie nicht danach gefragt werden, ob Sie den Workspace speichern wollen (Wenn Sie Änderungen an einem R Skript vorgenommen haben, werden Sie immer trotzdem gefragt, ob Sie das Skript speichern wollen).Öffnen Sie RStudio erneut und überprüfen Sie, dass das zuvor erstellte R Objekt nicht mehr existiert. Sie können dafür entweder versuchen das Objekt anzuzeigen (z.B. indem Sie in der Console den Namen des Objekts eingeben und Enter drücken) oder Sie versichern sich, dass das Environment-Fenster in RStudio leer ist.
2.3 R im Hintergrund neu starten
Auch während wir in RStudio arbeiten ist es sinnvoll, regelmäßig R “zurückzusetzen” und eine “frische Arbeitsumgebung” (= leeres Environment) zu schaffen. Damit wollen wir sicherstellen, dass der Code in unserem R Skript wie erwartet funktioniert und wir alle wichtigen Analyseschritte auch wirklich reproduzieren können.
Anstatt RStudio aufwendig zu schließen und wieder neu zu öffnen, können wir stattdessen im Hintergrund R neu starten, indem wir in RStudio entweder…
- auf Session > Restart R klicken oder
- die Tastenkombination command + Shift + 0 für Mac oder Strg + Shift + F10 für Windows verwenden.
Danach können wir entweder…
- unseren Code im Skript Schritt für Schritt manuell neu ausführen oder
- mit der Tastenkombination command + Shift + Enter für Mac oder Strg + Shift + Enter für Windows das komplette aktuell geöffnete Skript ausführen.
Erstellen Sie ein neues R Skript das nur die folgenden drei Zeilen enthält:
<- 1 x <- 2 y + y x
Führen Sie die drei Befehle im Skript der Reihe nach aus.
Geben Sie direkt in der Console den folgenden Befehl ein:
y <- x
Führen Sie die 3. Zeile des Skripts erneut aus und vergleichen Sie das Ergebnis mit dem Ergebnis, dass jemand erwarten würde der nur das Skript kennt.
Starten Sie R im Hintergrund neu, indem Sie die beschriebene Tastenkombination verwenden.
Führen Sie das komplette Skript neu aus, indem Sie die beschriebene Tastenkombination verwenden. Überprüfen Sie das Ergebnis.
3 Arbeiten mit Daten
3.1 Funktionen
Argumente
Funktionen führen Operationen für uns durch, indem wir ihnen bestimmte Eingabewerte, sogenannte Argumente, übergeben. Vergleichbar ist das mit den mathematischen Funktionen, die angeben, welche Berechnungen mit dem Argument \(x\) angestellt werden sollen, um zu einem Ergebnis \(y\) zu gelangen, z.B.
\[ f(x) = x^2 + 5 \] Funktionen in R können ähnlich dazu ein oder mehrere Argumente verarbeiten und uns Ergebnisse wie Mittelwerte, Summen oder komplexere Berechnungen zurück liefern.
Ein Beispiel
Eine einfachere Funktion ist die Exponential-Funktion \(e^x\). Ihr einziges Argument ist der Exponent.
Verwendung der Exponentialfunktion in R für \(x = 1\):
exp(1)
[1] 2.718282
Oft ist es zweckmäßig, ein Ergebnis von Funktionen gleich wieder als Argument einer weiteren Funktion zu verwenden. Diese Funktionen sind dann in einer bestimmten Reihenfolge ineinander verschachtelt.
Ein Beispiel
Um \(e^{\sqrt{x}}\) zu berechnen würden wir zunächst die Quadratwurzel von \(x\) mit der Funktion sqrt(x)
berechnen und das Ergebnis dann als Argument in die Exponentialfunktion exp()
einsetzen:
Die Reihenfolge der Verschachtelung spielt eine Rolle, z.B.:
\(e^{\sqrt{1}} \neq \sqrt{e^{1}}\)
exp(sqrt(1))
[1] 2.718282
sqrt(exp(1))
[1] 1.648721
Auch in der Mathematik ist es möglich, in einer Funktion mehr als ein Argument zu verarbeiten, wie z.B. in der Gleichung für einer Ebene im dreidimensionalen Raum:
\[ f(x, y) = 2x + 3y \]
Genauso gibt es in R viele Funktionen, die mehrere Argumente benötigen. Diese sind dann innerhalb eines Befehls mit Kommata voneinander getrennt und haben eindeutige Bezeichnungen um sie voneinander zu unterscheiden. Für manche Argumente gibt es default-Einstellungen, also Voreinstellungen, die R verwendet, wenn wir für ein Argument keine Angabe machen.
Ein Beispiel
Dies wird deutlich am Beispiel der round(x, digits)
Funktion, die eine Zahl auf beliebig viele Nachkommastellen rundet. Als erstes Argument übergeben wir der Funktion die zu rundende Zahl, als zweites Argument die Anzahl der Nachkommastellen. Der Name des Arguments, das die Anzahl der Nachkommastellen bestimmt, lautet digits
. Der Default (die Voreinstellung, wenn man kein Argument für digits
übergibt) ist Null. Es wird also auf null Nachkommastellen gerundet.
Die Funktion round(4.12345, digits = 2)
rundet die Zahl 4.12345 auf zwei Nachkommastellen, also auf 4.12.
Sie werden im weiteren Verlauf feststellen, dass Argumente auf zwei Arten angegeben werden. Im Beispiel oben round(4.12345, digits = 2)
ist das erste Argument, die zu rundende Zahl 4.12345
unbenannt angegeben worden und das zweite Argument, die Anzahl der gewünschten Nachkommastellen 2
wurde mit der Bezeichnung digits =
benannt.
Grundsätzlich sind bei jedem Argument beide Varianten möglich, führen aber nur dann zum gleichen Ergebnis, wenn die von einem Befehl erwartete Reihenfolge der Argumente eingehalten wurde. Werden die Argumente grundsätzlich nicht benannt, weiß ein Befehl ja nicht, ob die 2
die zu rundende Zahl sein soll oder die Nachkommastellen. Wir können das dem Befehl klar machen, in dem wir die Reihenfolge der Argumente einhalten, die auf der jeweiligen Hilfeseite (siehe Abschnitt 3.1.2) angegeben ist.
Weniger fehleranfällig und deutlich übersichtlicher wird es, wenn wir die folgende Konvention einhalten:
- Das erste Argument eines Befehls (das Hauptargument mit dem der Befehl arbeitet) wird nicht benannt.
- Alle weiteren Argumente die wir angeben wollen, werden mit der zugehörigen Benennung (z.B.
digits =
) angegeben.
round(4.12345, 2)
[1] 4.12
führt zum gleichen Argebnis wie
round(x = 4.12345, digits = 2)
[1] 4.12
Wohingegen
round(2, 4.12345)
[1] 2
Nicht zum gewünschten Ergebnis führt. Der Befehl denkt, die Ziffer 2 soll auf 4.12345 Nachkommastellen gerundet werden. Die Angabe von Nachkommastellen bei einer Anzahl ist zwar blödsinnig, der Befehl löst das jedoch dadurch, indem er die Nachkommastellen einfach ignoriert und versucht, die 2
einfach auf vier Nachkommastellen zu runden.
Durch die Benennung der Argumente könnten wir auf die richtige Reihenfolge verzichten:
round(digits = 2, x = 4.12345)
[1] 4.12
Obwohl das durchaus funktionieren würde ist diese Umkehrung der Reihenfolge eher unüblich. Eine weit verbreitete Style-Konvention schlägt vor, dass das Hauptargument des Befehls, das auch an erster Stelle erwartet wird unbenannt bleibt und alle weiteren Argumente in beliebiger Reihenfolge aber dafür benannt werden:
round(4.12345, digits = 2)
[1] 4.12
In R gibt es auch Funktionen ganz ohne Argument, wie zum Beispiel:
Sys.time() # der Zeitpunkt, zu dem diese Funktion ausgeführt wurde
[1] "2025-01-27 14:41:25 CET"
Auf der technischen Ebene wird immer wenn in R irgendetwas passiert (etwas berechnen, anzeigen, oder sonst irgendwelche Informationen verarbeiten) eine Funktion ausgeführt.
Hilfe
Wenn wir wissen möchten, wie eine Funktion arbeitet, also z.B. wie die einzelnen Argumente heißen, brauchen wir die Hilfe. Die Hilfe finden wir im „Multifunktionsfenster“ rechts unten beim Reiter Help.
Noch schneller können wir die Hilfeseite öffnen, indem wir in der Console ein Fragezeichen vor den Namen der Funktion schreiben (z.B. ?log
) und den Befehl ausführen.
In der Hilfeseite oben sehen wir zum Beispiel unter Description oder Usage, dass der Befehl log()
per default den natürlichen Logarithmus berechnet (in der Statistik braucht man fast immer nur den), wir aber auch eine andere Basis mit dem Argument base
einstellen könnten.
Finden Sie mit der Hilfefunktion heraus, warum die folgende Berechnung als Ergebnis 0
anzeigt:
round(0.5, digits = 0)
[1] 0
Lösung
In der Hilfeseite von ?round
steht unter Details:
Note that for rounding off a 5, the IEC 60559 standard (see also ‘IEEE 754’) is expected to be used, ‘go to the even digit’. Therefore round(0.5) is 0 and round(-1.5) is -2.
Die Hilfe in R ist nur dann nützlich, wenn wir den Namen einer Funktion bereits kennen. Was aber machen wir, wenn wir den Namen einer Funktion nicht kennen (oder ihn gerade vergessen haben)? Oder anders ausgedrückt, wie finden wir in der Praxis heraus, welche Befehle oder Funktionen in R mir bei einer bestimmten Aufgabe weiterhelfen können?
Typischerweise geben wir eine möglichst präzise formulierte Frage in die Suchmaschine unserer Wahl ein.
Häufig finden wir bei einer solchen Suche heraus, dass eine für uns hilfreiche Funktion in einem bestimmten R Paket enthalten ist.
Pakete
Wenn wir R installieren ist eine ganze Menge an Funktionen schon in der Basisvariante verfügbar. Es ist jedoch möglich, den Funktionsumfang durch so genannte Pakete deutlich zu erweitern. Die meisten dieser Pakete werden kontinuierlich von einer großen Gruppe von Entwicklerinnen stetig gepflegt und erweitert und sind für jede R-Nutzerin kostenfrei verfügbar.
Häufig wurden Pakete von Wissenschaftlerinnen für einen bestimmten Zweck erstellt und enthalten dann eine Reihe von Befehlen, die aufeinander aufbauen und dabei helfen sollen, ein typisches Problem zu lösen.
Wollen wir Befehle aus einem Paket nutzen, müssen wir das Paket zunächst herunterladen (“installieren”). Das können wir entweder mit dem Befehl install.packages("PAKETNAME")
machen, oder wir nutzen dazu in RStudio rechts unten den Reiter Packages.
Paket installieren

In beiden Fällen müssen wir genau wissen, wie das Paket heißt. Geben wir beispielsweise im Befehl install.packages("PAKETNAME")
den Namen falsch an (oder vergessen die Anführungszeichen), schlägt der Befehl fehl:
install.packages("Psych") # das Paket heißt "psych" mit kleinem p
Installing package into '/Users/florianpargent/Library/R/arm64/4.4/library'
(as 'lib' is unspecified)
Warning: package 'Psych' is not available for this version of R
A version of this package for your version of R might be available elsewhere,
see the ideas at
https://cran.r-project.org/doc/manuals/r-patched/R-admin.html#Installing-packages
Warning: Perhaps you meant 'psych' ?
Die Fehlermeldung…
Warning: package 'Psych' is not available for this version of R
…bedeutet hier nicht, dass unsere Version von R zu alt ist!
In diesem Fall haben wir uns nur verschrieben (R hat recht: Es gibt für unsere Version von R kein Paket namens ‘Psych’, aber es gäbe eines namens ‘psych’).
So wie wir Programme auf unserem Computer nur einmal installieren, müssen auch Pakete in der Regel nur einmal installiert werden, um sie danach immer wieder nutzen zu können. Lediglich nach einem Update von R (nicht von RStudio) ist es häufig notwendig, einmal installierte Pakete erneut zu installieren.
Wollen wir die Befehle des Pakets dann nutzen, müssen wir es für R zunächst mal verfügbar machen. Diesen Prozess nennt man das Paket zu laden. Am besten geht das mit dem Befehl…
library(PAKETNAME)
…den wir häufig ganz oben in unser Skript schreiben, damit wir das Laden nicht vergessen.
Natürlich muss der Befehl nicht nur im Skript stehen, sondern auch ausgeführt werden!
Ein Paket muss in der Regel nur einmal installiert, aber nach jedem Neustart von R oder RStudio erneut geladen werden, damit wir die Befehle darin nutzen können.
Ein Beispiel
Für unser Beispiel möchten wir die sogenannte logistische Funktion anwenden: \[
f(x) = \frac{1}{1 + e^{-x}}
\] Da wir im Internet gelesen haben, dass es z.B. im Paket psych
den Befehl logistic()
gibt, der diese Funktion berechnen kann, installieren und laden wir dieses Paket. Bevor wir das Paket installiert und auch geladen haben, können wir den Befehl daraus noch nicht nutzen:
logistic(0)
Error in logistic(0): could not find function "logistic"
Deshalb installieren wir das Paket einmalig wie oben beschrieben über den Reiter Packages oder mit dem folgenden Code:
# einmalig installieren:
install.packages("psych")
Sofern die Installation geklappt hat können wir das Paket nun laden
# laden
library(psych)
und den Befehl logistic()
nutzen
logistic(0)
[1] 0.5
Sofern Sie die oben beschriebenen Schritte nicht ohnehin schon ausgeführt haben, versuchen Sie mal, die Funktion
logistic()
zu verwenden, bevor Sie das Paketpsych
installiert und geladen haben.Installieren Sie dann das Paket wie oben beschrieben.
Laden Sie das Paket wie oben beschrieben.
Führen Sie die folgenden Befehle aus:
logistic(0) logit(0.5) # das ist die Umkehrfunktion
Schließen Sie RStudio und versuchen Sie, erneut die Befehle in Schritt 4 auszuführen.
Lösung
Ohne das Paket zu laden funktionert es nicht:
logistic(0)
Error in logistic(0): could not find function "logistic"
logit(0.5) # das ist die Umkehrfunktion
Error in logit(0.5): could not find function "logit"
Erst wenn wir davor im Skript das Paket laden, klappt es wieder:
library(psych) logistic(0)
[1] 0.5
logit(0.5) # das ist die Umkehrfunktion
[1] 0
Beim Installieren mit der Funktion install.packages("PAKETNAME")
muss der Name des Pakets in Anführungszeichen stehen, beim Laden mit der Funktion library(PAKETNAME)
nicht.
Wenn wir ein Skript öffnen, in dem ein Paket geladen werden soll, das wir noch nicht installiert haben, weist uns RStudio darauf hin. Am oberen Rand des Skripts erscheint die Nachricht “Package PAKETNAME required but is not installed. Install Don’t Show Again”. Hier können wir nun auf Install klicken und das Paket direkt installieren.
Sollten wir eine Funktion benötigen, die in R bisher nicht umgesetzt wurde und die auch in keinem Paket enthalten ist, ist es auch möglich, Funktionen selbst zu schreiben. Dadurch können wir einen bestimmten Code immer wieder ausführen, ohne den gesamten Code immer wieder zu schreiben (oder zu kopieren).
Auch Funktionen sind Objekte und können in Variablen gespeichert werden. Über diese Variablen rufen wir die Funktion dann auf. Eine Funktion ist wie folgt aufgebaut:
<- function(<function parameters>) {
function_name # Code
}
Um eine Funktion aufzurufen, schreibt man ()
nach dem Funktionsnamen.
Jetzt können wir eine einfache Funktion schreiben, die oben beschriebene logistische Funktion ausführt, wenn man sie aufruft:
<- function(zahl) {
logistic_function 1 / (1 + exp(-zahl))
}
Dieser Code liefert uns noch keinen Output, da wir die Funktion zwar geschrieben, aber noch nicht aufgerufen haben. Die Ausführung des Befehls machen wir über den Namen der Funktion, hinter den wir mit ()
das Argument schreiben, mit dem die Funktion arbeiten soll (so wie bei den bisher bekannten Funktionen auch).
Beim Verfassen der Funktion haben wir in den ()
hinter function
angegeben, dass die Funktion mit einem Objekt zahl
arbeiten soll. In der nächsten Zeile innerhalb der {}
haben wir dann mit diesem Objekt zahl
die Operation vorgenommen (\(\frac{1}{1 + e^{-x}}\)), die unsere Funktion letztlich durchführen soll.
Ein kurzer Test zeigt, dass die Funktion das macht, was sie soll:
logistic_function(zahl = 0)
[1] 0.5
Die meisten Funktionen arbeiten mit mehreren Argumenten. Wir können uns also auch eine Funktion schreiben, die uns die Summe aus zwei Zahlen zurückgibt (Wir schreiben also die existierende Funktion sum()
selber). Dabei verwenden wir als Argumente die beiden Platzhalter x
und y
, die wir dann beim späteren Funktionsaufruf durch die Zahlen ersetzen, die wir addieren möchten:
<- function(x, y) {
my_sum + y
x
}
my_sum (x = 3, y = 5)
[1] 8
Schreiben Sie eine Funktion square(), die eine Zahl als Argument übernimmt und ihre Quadratzahl zurückgibt
Lösung
<- function(x) { square * x x } square(x = 3)
[1] 9
Schreiben Sie eine Funktion logit_function(), die die Umkehrfunktion der logistischen Funktion berechnet: \[ f(y) = ln(\frac{y}{1 - y}) \]
Lösung
<- function(zahl){ logit_function log(zahl / (1 - zahl)) }logit_function(zahl = 0.5)
[1] 0
3.2 Datenstruktur
Einfache Datenstruktur: Vektoren
Bisher haben wir bei der Zuweisung eines Objekts immer nur einen einzelnen Wert gespeichert. Häufig wollen wir jedoch mit einer ganzen Reihe von Werten arbeiten. Um eine Reihe von Werten des gleichen Datentyps zu speichern, verwenden wir Vektoren. Der Begriff “Vektor” haben Sie vermutlich schon einmal im Matheunterricht gehört.
Wenn wir in R mehrere Komponenten (z.B. Zahlen) zu einem Vektor kombinieren wollen, verwenden wir die Funktion c()
. Wie wir oben bei den Argumenten einer Funktion gelernt haben, werden die einzelnen Werte innerhalb der Funktion durch Kommas getrennt.
Wie wir es aus dem Matheunterricht kennen, können wir mit Vektoren auch rechnen. Wir können beispielsweise zwei Vektoren der gleichen Länge voneinander abziehen
\[ \vec{v} = \begin{pmatrix} 3 \\ 8 \\ 5 \end{pmatrix} - \begin{pmatrix} 1 \\ 5 \\ 2 \end{pmatrix} = \begin{pmatrix} 3 - 1 \\ 8 - 5\\ 5 - 2 \end{pmatrix} = \begin{pmatrix} 2 \\ 3 \\ 3 \end{pmatrix} \] oder von jedem Element eines Vektors eine bestimmte Zahl abziehen
\[ \vec{v} = \begin{pmatrix} 3 \\ 8 \\ 5 \end{pmatrix} - 2 = \begin{pmatrix} 3 - 2 \\ 8 - 2\\ 5 - 2 \end{pmatrix} = \begin{pmatrix} 1 \\ 6 \\ 3 \end{pmatrix} \]
In R müssen wir mit c()
erstmal den gewünschten Vektor erstellen und können dann ganz normal damit rechnen:
c(3, 8, 5) - 2
[1] 1 6 3
Wie wir sehen, werden Vektoren in R immer als Zeilen dargestellt, das macht aber für unsere Anwendungen keinen Unterschied.
Bei längeren Vektoren kann es sinnvoll sein, den Vektor zunächst in einem Objekt zu speichern und danach die Operation mit dem Objekt auszuführen:
# Abspeichern eines Vektors in einem Objekt
<- c(3, 8, 5)
mein_Vektor - 2 mein_Vektor
[1] 1 6 3
Beides führt zum selben Ergebnis - es ist also uns überlassen, welche Variante wir wählen.
Im Matheunterricht haben Sie vermutlich nur Vektoren mit Zahlen kennen gelernt, mit denen man dann auch rechnen kann. Die Struktur eines Vektors ist jedoch für uns an vielen Stellen nützlich. Ein Vektor ist – ganz allgemein formuliert – ein Objekt, das beliebig viele Elemente des gleichen Typs in fester Reihenfolge enthält. Wir werden im Folgenden noch sehen, dass es auch für andere Datentypen (logische Werte, character) viele Situationen gibt, in denen es sehr nützlich ist mehrere Elemente in einen Vektor zusammenzufassen.
Ein Vektor hat dabei aber immer genau einen Datentyp. Einen Vektor vom Typ logical können wir ganz ähnlich wie schon bei den Zahlen mit dem Befehl c()
erstellen:
c(TRUE, FALSE, TRUE)
[1] TRUE FALSE TRUE
“Erkennungszeichen” für logische Werte ist hier, dass alle TRUE
und FALSE
-Werte richtig geschrieben (also alles groß und keine Schreibfehler) sind.
Die Erstellung eines Vektors vom Typ character funktioniert ganz genauso. Hier verwenden wir als “Erkennungszeichen” der character-Werte die ""
vor und nach jedem Element:
c("Homer", "Marge", "Bart", "Lisa", "Maggie")
[1] "Homer" "Marge" "Bart" "Lisa" "Maggie"
Verschiedene Datentypen können nicht gemischt werden. Geben wir verschiedene Datentypen in einen Vektor, so versucht R einen gemeinsamen Nenner zu finden, was üblicherweise den Typ character ergibt.
c(3, "wort", TRUE)
[1] "3" "wort" "TRUE"
Wenn wir diesen Code ausführen und damit den “gemischten” Vektor anzeigen, sehen wir, dass alle Elemente mit ""
versehen und angegeben werden. Daran erkennen wir, dass auch die Zahl 3
und der logische Wert TRUE
nun character-Werte sind und ihre eigentlichen Eigenschafen verloren haben.
Die Umwandlung von Datentypen erfolgt häufig ohne dass R eine Warnung ausgibt. Als Anwenderin können wir diesen Vorgang also leicht übersehen. Durch die Umwandlung in character gehen jedoch möglicherweise bestimmte Eigenschaften der Daten verloren. Wir können beispielsweise mit dem character-Wert "3"
keine mathematischen Operationen wie Addition mehr vornehmen!
Weisen Sie dem Vektor Geburtsjahr das Alter von drei (ausgedachten) Personen zu
Wie alt sind alle drei Personen 2023 geworden?
Weisen Sie dem Vektor Namen die Namen der Personen in (1) in gleicher Reihenfolge zu.
Lösung
Lösung
<- c(1998, 2002, 1988) Geburtsjahr 2023 - Geburtsjahr
[1] 25 21 35
<- c("Markus", "Philipp", "Moritz") Namen Namen
[1] "Markus" "Philipp" "Moritz"
Komplexere Datenstrukturen: Data Frames und Listen
data.frame
Bisher haben wir gesehen, dass wir Daten zu eindimensionalen Objekten zusammenfassen können, z.B. in Form von Vektoren. Wir können aber auch mehrdimensionale Strukturen erstellen, wie z.B. ein Objekt, das aus mehreren Vektoren besteht. Eine für uns besonders wichtigte Struktur heißt Data Frame (oder data.frame) und ähnelt einer Matrix (Matrizen gibt es in R auch, da wir diese aber so gut wie nie brauchen, werden wir sie nicht behandeln). Ein data.frame besteht aus Zeilen und Spalten. Die Spalten sind alle gleich lang, können aber Daten unterschiedlichen Typs beinhalten. Zum Beispiel eine Spalte Namen, die character-Werte beinhaltet und eine Spalte Alter, die Zahlen beinhaltet. Damit ist ein data.frame die für uns nützlichste und wichtigste Art von Datenstruktur. Hier können wir z.B. für mehrere Personen (Zeile entspricht einer Person) unterschiedliche Informationen (Name, Alter, Schulnote, Ausprägung psychischer Symptome etc.) in Spalten verschieden Typs zusammenfassen. Der data.frame sorgt dafür, dass die Zuordnung unterschiedlicher Informationen zu den Personen immer eindeutig ist. Der dritte Wert in der ersten Spalte (z.B. Name) gehört zur gleichen Person wie der dritte Wert in der dritten Spalte (z.B. Schulnote) usw.
Wir können nun selber mit dem Befehl data.frame()
einen data.frame erstellen. Der Befehl hat für jede gewünschte Spalte im Datensatz ein Argument. Die Benennung der Argumente (z.B. Alter =
) sorgt dafür, dass eine Spalte eine für uns inhaltlich sinnvolle Überschrift erhält:
<- data.frame(
df Name = c("Tom", "Paula", "Mia", "Jonas"),
Alter = c(21, 22, 21, 20) # Wichtig: Reihenfolge der Namen einhalten!
)
# das Ausführen des Objekts zeigt den data.frame an df
Name Alter
1 Tom 21
2 Paula 22
3 Mia 21
4 Jonas 20
Unserem data.frame können wir nun neue Variablen hinzufügen, indem wir das $
-Symbol nutzen. Folgender Code fügt eine neue Spalte hinzu, die das Lieblingsessen unserer Personen beinhaltet. Dabei müssen wir darauf achten, dass der neue Vektor so viele Einträge enthält, wie wir Zeilen haben (in diesem Fall 4). Der erste Vektoreintrag beinhaltet den Wert der ersten Person, der zweite Eintrag den der zweiten Person usw.
$Lieblingsessen <- c("Pizza", "Döner", "Eis", "Pizza")
df
df
Name Alter Lieblingsessen
1 Tom 21 Pizza
2 Paula 22 Döner
3 Mia 21 Eis
4 Jonas 20 Pizza
Wir haben die Daten in df
hier manuell eingetippt, um an einem einfachen Beispiel zeigen zu können, was ein data.frame ist. In der Praxis gibt niemand einen echten Datensatz direkt in R ein! Stattdessen werden Datensätze typischerweise entweder automatisiert erstellt (z.B. von einer Software für Onlineumfragen), oder manuell in einem Tabellenkalkulationsprogramm (z.B. Excel oder LibreOffice) eingegeben. Diese fertigen Datensätze (manchmal auch “Rohdaten” genannt) werden dann in R “eingelesen” und dort statistisch analysiert oder weiter verarbeitet. Das Einlesen von Datensätzen lernen wir später in Teil 2 des Tutorials.
list
Eine Liste (oder list) ist eine flexible Datenstruktur und kann Objekte unterschiedlichen Typs (z.B. Zahlen, Character) oder auch unterschiedlicher Struktur (z.B. Vektoren, data.frames) beinhalten. Einfache Benennungen der Listenelemente lassen sich wie beim data.frame auch gleich im list()
-Befehl umsetzen.
<- list(number = 1256, name = "Tomas", vector = c(1, 2, 5, 6))
my_list
my_list
$number
[1] 1256
$name
[1] "Tomas"
$vector
[1] 1 2 5 6
Ein wichtiger Unterschied zu data.frames ist, dass Listenelemente unterschiedlich “lang” sein können. Die Ergebnisse komplexerer Analysen sind häufig in Listen gespeichert, auf deren einzelne Elemente wir eventuell zugreifen wollen.
Indizierung: Zugriff auf Elemente eines Objekts
Indizierung von Vektoren
Bisher haben wir gesehen, wie wir bei der Vektorerstellung Daten zusammenfügen. Wir können aber auch auf einzelne Elemente des Vektors zugreifen (Fachbegriff: indizieren), falls uns z.B. nur der Eintrag interessiert, der an zweiter Stelle steht. Das erfolgt in R über die sogenannte Vektorindizierung. Dabei wird mit eckigen Klammern []
auf die Stelle zugegriffen, die uns interessiert. Dabei geben wir in den Klammern an, das wievielte Elemente des Vektors (also mit 1
das erste Element, mit 2
das zweite Element usw.) wir auswählen möchten.
# Beispielvektor erstellen
<- c(3, 8, 5, 7)
mein_Vektor
# Zugriff auf die zweite Ziffer
2] mein_Vektor[
[1] 8
Wenn wir uns von R einen langen Vektor anzeigen lassen, passt der Output nicht mehr in eine Zeile.
<- 100:200 # 100:200 erzeugt alle ganze Zahlen von 100 bis 200
langer_Vektor langer_Vektor
[1] 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
[19] 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
[37] 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
[55] 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171
[73] 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
[91] 190 191 192 193 194 195 196 197 198 199 200
Jetzt wo wir die []
Schreibweise kennengelernt haben, können wir zum ersten mal verstehen, was die Zahlen in eckigen Klammern (z.b. [1]
, [19]
, …) im Output bedeuten. Diese Zahlen zeigen an, das wievielte Element des Vektors zu Beginn einer Zeile des Outputs angezeigt wird. Das ist sehr hilfreich, um sich in langen Outputs schneller zurecht zu finden.
Bei unserem Beispiel langer_Vektor
ist das 1. Element die Zahl 100 ([1] 100
), das 19. Element die Zahl 118 ([19] 118
) und so weiter. Wir können das mit der gerade gelernten Indizierung überprüfen:
19] langer_Vektor[
[1] 118
Eine einzelne Zahl wird von R intern wie ein Vektor mit nur einem Element behandelt. Daher wird auch bei der Ausgabe einer einzelnen Zahl immer [1]
angezeigt, obwohl das nicht besonders hilfreich ist…
Um auf mehrere Einträge eines Vektors zuzugreifen, erstellen wir in den eckigen Klammern []
einen Vektor und übergeben als Elemente des Vektors die Stellen der Einträge, die wir auswählen wollen.
<- c(3, 8, 5, 7)
mein_Vektor
# Zugriff auf die zweite und vierte Ziffer
c(2, 4)] mein_Vektor[
[1] 8 7
Wenn wir auf mehrere Argumente des Vektors zugreifen wollen, dürfen wir den Vektor in der eckigen Klammer [c(x, y)]
nicht vergessen. Es ist nicht möglich, innerhalb der eckigen Klammern ohne den Zwischenschritt des mit c()
erstellten Vektors auf mehrere Argumente zuzugreifen: [2,3,4]
. Später werden wir sehen, warum.
Wir können mit den eckigen Klammern nicht nur einzelne Werte anschauen sondern diese auch ändern. Der folgende Code weist unserem Vektor an zweiter Stelle den Wert 4 zu und überschreibt dabei den Wert 8.
<- c(3, 8, 5, 7)
mein_Vektor
2] <- 4
mein_Vektor[
mein_Vektor
[1] 3 4 5 7
Indizierung von Data Frames
Bei den Vektoren haben wir bereits gesehen, wie man mit eckigen Klammern []
auf einzelne Werte zugreift. Auch bei data.frames können wir auf einzelne Werte zugreifen. Dabei können wir eine einzelne Zeile auswählen, eine einzelne Spalte oder einen einzelnen Wert (= Kombination aus Spalte und Zeile). Natürlich können wir auch hier wieder mehrere Zeilen/Spalten/Werte auswählen.
Die eckigen Klammern bekommen dabei zwei Argumente, da wir zwei Dimensionen haben. Die Argumente werden (wie wir bereits bei den anderen Befehlen gesehen haben) durch ein Komma getrennt. Mit dem ersten Argument wählen wir die Zeile aus, mit dem zweiten Argument die Spalte:
df[Zeile, Spalte]
Eine Eselsbrücke um sich zu merken, dass das erste Argument die Zeilen auswählt und das zweite Argument die Spalten:
Zeilen Zuerst, Spalten Später
Zur Erinnerung: Wir haben in Abschnitt 3.2.2.1 bereits folgenden data.frame erstellt:
df
Name Alter Lieblingsessen
1 Tom 21 Pizza
2 Paula 22 Döner
3 Mia 21 Eis
4 Jonas 20 Pizza
Hier können wir nun z.B. alle Spalten der ersten Person (also die erste Zeile) auswählen, indem wir in eckigen Klammern als erstes Argument die Zeile 1 übergeben und das zweite Argument hinter dem Komma leer lassen. Das Leerlassen bedeutet, dass alle Spalten ausgewählt werden:
1, ] df[
Name Alter Lieblingsessen
1 Tom 21 Pizza
Oder wir interessieren uns nur für das Alter aller Personen und wählen die zweite Spalte aus. Dabei lassen wir das erste Argument frei (wir wollen alle Zeilen auswählen) und übergeben als zweites Argument die Spalte 2:
2] df[ ,
[1] 21 22 21 20
Wenn wir uns speziell für das Alter der ersten Person in unserem data.frame interessieren, können wir diesen einzelnen Wert auswählen, indem wir als erstes Argument die Zeile 1 übergeben und als zweites Argument die Spalte 2:
1, 2] df[
[1] 21
Ähnlich wie bei Vektoren können wir auch hier mehrere Zeilen oder Spalten auswählen, indem wir diese in einem Vektor zusammenfassen:
c(1, 2), c(1, 2)] df[
Name Alter
1 Tom 21
2 Paula 22
Vor dem Komma und nach dem Komma [ , ]
darf jeweils nur eine Information stehen. Wir müssen also alle Infos bezüglich der Zeilen und der Spalten jeweils in ein Objekt (hier einen Vektor) zusammenfassen.
Für den Fall, dass wir zwar den Namen der Spalten kennen, aber nicht wissen, an welcher Stelle sich diese befinden, können wir auch über den Namen der Spalte auf diese zugreifen:
c("Alter", "Lieblingsessen")] df[ ,
Alter Lieblingsessen
1 21 Pizza
2 22 Döner
3 21 Eis
4 20 Pizza
Wenn wir uns zurückerinnern, haben wir gesehen, dass es nicht möglich ist auf die Weise mein_Vektor[1, 2, 3]
auf die ersten drei Einträge eines Vektors zuzugreifen. Nachdem wir uns nun die Indizierung von data.frames angeschaut haben, verstehen wir, dass sich die Argumente in eckigen Klammern auf die Dimensionen beziehen.
Indizierung von Data Frames und Listen mit $
Neben der Indizierung über eckige Klammern [ , ]
können wir auch die Spaltennamen nutzen, um ganze Spalten herauszugreifen. Hierfür nutzen wir das Dollar-Zeichen $
:
$Name df
[1] "Tom" "Paula" "Mia" "Jonas"
Sobald wir das $
Zeichen eingeben, schlägt uns die Autovervollständigung von RStudio alle Spaltennamen des Datensatzes zur Auswahl vor.
Autovervollständigung

Die $
-Indizierung funktioniert auch mit Listen. Zum Beispiel können wir aus unserer weiter oben erstellten Liste…
my_list
$number
[1] 1256
$name
[1] "Tomas"
$vector
[1] 1 2 5 6
… das Element mit dem Namen vector folgendermaßen herausgreifen:
$vector my_list
[1] 1 2 5 6
Bedingte Indizierung von Data Frames
Bisher haben wir uns vor allem angeschaut, wie wir bestimmte Spalten auswählen. Nun wollen wir uns ansehen, wie wir Personen aus unserem data.frame auswählen, die bestimmte Bedingungen erfüllen.
Im folgenden Beispiel wollen wir alle Personen aus unserem data.frame auswählen, deren Lieblingsessen Pizza ist. Bei einem großen Datensatz währe es sehr aufwendig, herauszufinden an welchen Stellen diese Personen stehen und die entsprechenden Stellen in einen Vektor zu schreiben.
Wir können die Stellen der Personen mit Pizza als Lieblingsessen über einen logischen Vergleich ermitteln:
$Lieblingsessen == "Pizza" df
[1] TRUE FALSE FALSE TRUE
Dabei fragen wir für jede Zeile ab, ob im data.frame df
die Spalte Lieblingsessen
den Eintrag “Pizza” enthält. Der Rückgabewert eines logischen Vergleich ist wie in Abschnitt 1.3 beschrieben TRUE
oder FALSE
. Wir erhalten also für jede Zeile des data.frame die Information, ob die dort angegebene Person als Lieblingsessen “Pizza” angegeben hat. Die Zeilen, für die ein TRUE
als Antwort kommt, möchten wir auswählen, alle mit der Information FALSE
nicht.
Die nun gewonnene Information, an welcher Stelle TRUE
steht können wir nun direkt nutzen und in unsere Indizierung einbauen. Wir fügen dafür den Code der den logischen Vergleich vornimmt direkt in den Code ein, der für die Auswahl bestimmter Zeilen zuständig ist. Also innerhalb der Auswahl df[ , ]
vor dem Komma:
$Lieblingsessen == "Pizza", ] df[df
Name Alter Lieblingsessen
1 Tom 21 Pizza
4 Jonas 20 Pizza
Durch welchen Code erhalte ich die Daten der Spalte Lieblingsessen nur bei den 21-Jährigen?
Lösung
$Alter == 21, "Lieblingsessen"] df[df
[1] "Pizza" "Eis"
Die bedingte Indizierung wird noch nützlicher, wenn wir berücksichtigen, dass wir mehrere logische Vergleiche mit dem logischen UND (in R das Symbol &
) bzw. logischen ODER (in R das Symbol |
) kombinieren können.
Hier nochmal unser Beispiel data.frame zur Erinnerung:
df
Name Alter Lieblingsessen
1 Tom 21 Pizza
2 Paula 22 Döner
3 Mia 21 Eis
4 Jonas 20 Pizza
Beispiel 1:
Zeige die Namen aller Personen an, deren Alter größer als 20 UND gleichzeitig kleiner als 22 ist.
$Alter > 20 & df$Alter < 22, "Name"] df[df
[1] "Tom" "Mia"
Beispiel 2:
Zeige die Namen aller Personen an, deren Lieblingsessen Pizza ODER deren Alter 21 Jahre ist (oder beides).
$Lieblingsessen == "Pizza" | df$Alter == 21, "Name"] df[df
[1] "Tom" "Mia" "Jonas"
3.3 Praktische Funktionen für Data Frames
Wir haben bereits gesehen, was Funktionen und Argumente sind. Dabei haben wir mathematischen Funktionen wie exp()
kennengelernt, sowie die Funktion round()
oder die Funktion c()
zur Erstellung von Vektoren.
In unserer praktischen Arbeit werden wir fast immer mit Daten arbeiten, die in R als data.frame
vorliegen. Da data.frames uns also sehr häufig begegnen, wollen wir dazu einige praktische Funktionen kennenlernen. Später sind unsere Datensätze oft sehr umfangreich mit hunderten Zeilen und Spalten, so dass wir nicht mehr einfach so “per Hand” feststellen können, was in einem data.frame enthalten ist oder ob es irgendwelche Auffälligkeiten gibt. Deshalb gibt es einige Funktionen, die wir direkt mit einem data.frame als Argument anwenden können, um allgemeine Informationen darüber zu erhalten.
str()
beschreibt die Struktur eines Objekts, also z.B. welchen Datentyp es hat und wie viele Elemente darin enthalten sind. Diese Funktion ist bei der Arbeit mit allen Objekten extrem nützlich (nicht nur bei data.frames)nrow()
gibt uns die Anzahl an Zeilen in einem data.frame aus undncol()
die Anzahl an Spaltenhead()
zeigt die ersten sechs Zeilen eines data.frames an (natürlich nur sinnvoll, wenn es mehr als sechs Zeilen gibt) undtail()
die letzten sechs Zeilensummary
fasst die Information die ein Objekt enthält zusammen (nicht nur bei data.frames).
Bei data.frames versucht der Befehl die einzelnen Spalten auf sinnvolle Weise zu beschreiben.
Am Anfang bekommt man eventuell den Eindruck, “R lernen” bedeute ganz viele Befehle und Funktionsnamen auswendig zu lernen. So sieht programmieren in der Praxis aber nicht aus. Tatsächlich ist es das Wichtigste, die Funktionsweise von R zu lernen (z.B. was sind data.frames und wie funktioniert die [ , ]
Syntax). Auch erfahrene R-Nutzerinnen kennen nicht die Namen aller verfügbaren Funktionen und es ist ganz normal, beim programmieren immer wieder die notwendigen Informationen nachzuschlagen (wie man das effizient macht, siehe z.B. Abschnitt 3.1.2). Befehle und Funktionen, die man häufig benötigt, prägen sich dann mit der Zeit ganz automatisch ein.
In den folgenden Beispielen wenden wir die oben aufgelisteten Funktionen auf den vorhin erstellten data.frame df
an, um uns allgemeine Informationen über dessen Struktur ausgeben zu lassen:
str(df)
'data.frame': 4 obs. of 3 variables:
$ Name : chr "Tom" "Paula" "Mia" "Jonas"
$ Alter : num 21 22 21 20
$ Lieblingsessen: chr "Pizza" "Döner" "Eis" "Pizza"
Wir sehen im Output von str()
, dass unser data.frame 4 Zeilen (obs. steht für observations) und 3 Spalten (variables). Die erste Spalte heißt Name und besteht aus character-Werten (chr). Die zweite Spalte heißt Alter und besteht aus Zahlen (num für numeric). Die dritte Spalte heißt Lieblingsessen und besteht wieder aus character-Werten.
nrow(df)
[1] 4
ncol(df)
[1] 3
Wenn wir einen größeren Datensatz haben als unser Beispiel und nur die ersten oder letzten sechs Zeilen ansehen wollen, können wir das mit head()
oder tail()
. Da df
in unserem Beispiel nur vier Zeilen hat, ist das in diesem Fall sinnfrei.
head(df)
Name Alter Lieblingsessen
1 Tom 21 Pizza
2 Paula 22 Döner
3 Mia 21 Eis
4 Jonas 20 Pizza
tail(df)
Name Alter Lieblingsessen
1 Tom 21 Pizza
2 Paula 22 Döner
3 Mia 21 Eis
4 Jonas 20 Pizza
Eine Zusammenfassung für jede Spalte im Datensatz bekommen wir mit dem Befehl summary()
. Dieser Befehl kann auch auf andere Objekte als data.frames angewandt werden und wird uns in Statistik noch häufig begegnen.
summary(df)
Name Alter Lieblingsessen
Length:4 Min. :20.00 Length:4
Class :character 1st Qu.:20.75 Class :character
Mode :character Median :21.00 Mode :character
Mean :21.00
3rd Qu.:21.25
Max. :22.00
Je nachdem, welchen Datentyp eine Spalte hat, sieht die Zusammenfassung unterschiedlich aus. Für numerische Spalten wie Alter bekommen wir eine Reihe von Lagemaßen wie z.B. den Mittelwert (Mean). Für Textspalten wie Name und Lieblingsessen ist die Zusammenfassung erst einmal nicht besonders hilfreich, da summary()
mit character-Werten nicht so gut umgehen kann. Sinnvoller wäre es, wenn die beiden Spalten als factor gespeichert wäre.
3.4 Datentypen Teil 2
Faktoren
Wir haben oben in Abschnitt 1.4 die drei Datentypen numeric, logical und character kennen gelernt. Der Typ logical mit den TRUE
und FALSE
-Werten ist dann für uns ganz praktisch, wenn Daten nur zwei Ausprägungen annehmen können (z.B. “ist das Alter einer Person > 18 oder nicht?” oder “hat eine Person eine bestimmte Erkrankung oder nicht?”). Sind mehr als zwei Ausprägungen möglich, benötigen wir eine andere Lösung: Den Datentyp factor.
Ein Faktor kann eine festgelegte Anzahl von Ausprägungen (Levels) haben, die die möglichen Datenkategorien darstellen. Dabei kann es auch vorkommen, dass eine Ausprägung des Faktors zwar definiert wird, in unserem Datensatz tatsächlich jedoch gar nicht vorkommt.
Ein Beispiel
Angenommen wir haben eine Umfrage durchgeführt, in der Teilnehmer gefragt wurden, welchen Psychologie-Studiengang sie studieren. Wir wissen, dass es an der LMU nur eine begrenze Auswahl an Psychologie-Studiengängen gibt (z.B. “Bachelor Hauptfach”, “Bachelor Nebenfach”, “Master”) ohne dass alle diese Ausprägungen auch tatsächlich in unserer Umfrage als Daten auftauchen.
Nehmen wir an, von unseren drei befragten Personen studieren zwei im Bachelor Hauptfach und eine Person im Master:
<- factor(c("Bachelor Hauptfach", "Bachelor Hauptfach", "Master"), # Vorsicht, das c() nicht vergessen!
studienfach levels = c("Bachelor Hauptfach", "Bachelor Nebenfach", "Master"))
studienfach
[1] Bachelor Hauptfach Bachelor Hauptfach Master
Levels: Bachelor Hauptfach Bachelor Nebenfach Master
Das erstellte Objekt studienfach
ist durch den Befehl factor()
nun vom Typ factor. Als erstes Argument dieses Befehls haben wir die Antworten unserer drei Personen als Vektor vom Typ character angegeben. Als zweites Argument levels =
haben wir angegeben, welche Ausprägungen es theoretisch geben kann.
Welchen Nutzen hat es nun, Ausprägungen anzugeben, obwohl sie nicht beobachtet wurden? Dadurch, dass die Ausprägung “Bachelor Nebenfach” zwar als level
angegeben wurde, jedoch in den Daten gar nicht auftaucht “weiß” R nun, dass es eine Ausprägung gibt, die nicht in den Daten beobachtet wurde. Bei einem Befehl wie dem Erstellen einer Häufigkeitstabelle wird R uns nun die Information geben, dass die erste Ausprägung “Bachelor Hauptfach” zwei Mal, die dritte Ausprägung “Master” ein Mal, und die zweite Ausprägung “Bachelor Nebenfach” überhaupt nicht beobachtet wurde:
table(studienfach) # So kann eine einfache Häufigkeitstabelle angezeigt werden
studienfach
Bachelor Hauptfach Bachelor Nebenfach Master
2 0 1
Wenn wir später statistische Analysen mit Daten durchführen wollen, die in Form von Text vorliegen, müssen wir manchmal überlegen, ob der Datentyp character ausreichend ist, oder ob wir die Textdaten als factor speichern müssen.
Später wird es für einige Funktionen in R notwendig sein, dass Spalten in unseren data.frames die Textinformation enthalten als Faktor gespeichert sind. Wir wollen dies hier schon einmal an einem kleinen Beispiel demonstrieren:
Mit der häufig verwendeten Funktion summary()
kann für viele verschiedene Arten von Objekten hilfreiche Zusammenfassungen anzeigen. Wenn wir jedoch die Funktion auf unseren zuvor erstellten data.frame df
anwenden, haben wir oben gesehen, dass die Zusammenfassung der beiden character-Spalten Name und Lieblingsessen für uns nicht besonders nützlich ist…
summary(df)
Name Alter Lieblingsessen
Length:4 Min. :20.00 Length:4
Class :character 1st Qu.:20.75 Class :character
Mode :character Median :21.00 Mode :character
Mean :21.00
3rd Qu.:21.25
Max. :22.00
Nützlicher wird die Zusammenfassung, wenn wir die beiden Spalten mit dem factor()
Befehl in einen Faktor umwandeln und neu abspeichern:
$Name <- factor(df$Name)
df$Lieblingsessen <- factor(df$Lieblingsessen)
dfsummary(df)
Name Alter Lieblingsessen
Jonas:1 Min. :20.00 Döner:1
Mia :1 1st Qu.:20.75 Eis :1
Paula:1 Median :21.00 Pizza:2
Tom :1 Mean :21.00
3rd Qu.:21.25
Max. :22.00
Wie wir sehen, zeigt der summary()
Befehl für Faktorspalten in einem data.frame eine nützliche Häufigkeitstabelle an.
Fehlende Werte
Bisher sind wir in unseren Beispielen immer davon ausgegangen, dass uns alle Personen die wir in einer Datenerhebung befragen, auch vollständige Antworten geben. Im Beispiel oben haben wir von allen drei befragten Personen beispielsweise auch eine Antwort bekommen, in welchen Studiengang sie eingeschrieben sind. In Abschnitt 3.2.2.1 haben alle vier Personen in unserem Beispiel ihren Namen, ihr Alter und ihr Lieblingsgericht verraten. Das ist jedoch häufig nicht realistisch, denn Befragte geben oft nur unvollständige Antworten.
Ein Beispiel
Nehmen wir an, dass wir für die Erstellung unseres data.frames df
oben zwar von Tom, Paula und Mia ihr Alter erfahren haben, Jonas uns jedoch sein Alter nicht verraten möchte? Wir können Jonas Alter ja nicht einfach weglassen, da sonst nur noch drei Werte vorhanden sind, die dann auch möglicherweise in den Zeilen den falschen Personen zugeordet werden. Wir müssten also bei der Erstellung des data.frames irgendwie die Information geben, dass hier eine Zahl stehen sollte, diese jedoch unbekannt ist.
Das geht mit einem so genannten Fehlenden Wert, der in R durch die Buchstabenkombination NA
gekennzeichnet ist. Ein solches NA
könnten wir jetzt an der Stelle von Jonas in unserer Spalte Alter einfügen:
<- data.frame(
df Name = c("Tom", "Paula", "Mia", "Jonas"),
Alter = c(21, 20, 21, NA) # Wichtig: Reihenfolge der Namen einhalten!
)
# das Ausführen des Objekts zeigt den data.frame an df
Name Alter
1 Tom 21
2 Paula 20
3 Mia 21
4 Jonas NA
Sind NA
s in Daten vorhanden, kann es vorkommen, dass Befehle nicht mehr so funktionieren, wie von uns erwartet. Oft gibt es aber bestimmte Argumente, die dem Befehl sagen wie er mit NA
s umgehen soll.
Ein Beispiel
Mit dem Befehl sum()
könnten wir mehrere Werte addieren. Übergeben wir die Spalte Alter df$Alter
diesem Befehl, würde der Befehl versuchen, alle Werte dieser Spalte zu addieren:
sum(df$Alter)
[1] NA
Als Ergebnis kommt nun auch ein NA
heraus?! Das liegt daran, dass der Befehl nicht weiß wie eine Summe von drei Zahlen und einer unbekannten Zahl gebildet werden soll.
Möchten wir jedoch, dass der Befehl den NA
einfach ignoriert und die drei verbleibenden Werte addiert, können wir dies mit dem Argument na.rm = TRUE
erreichen:
sum(df$Alter, na.rm = TRUE)
[1] 62
Wie das Argument heißt, dass bei einem Befehl den Umgang mit fehlenden Werten definiert, können Sie in der Hilfeseite zum jeweiligen Befehl (z.B. hier ?sum
, siehe Abschnitt 3.1.2) herausfinden.
Manchmal möchte man in einem Datensatz alle Zeilen entfernen, die nicht vollständig sind (d.h. mindestens einen mit NA
kodierten fehlenden Wert enthalten). Dafür kann die Funktion na.omit()
verwendet werden. Wenn die Funktion einen data.frame als Input bekommt, gibt sie einen data.frame aus, der nur noch die vollständigen Zeilen enthält, z.B.:
<- na.omit(df)
df_ohneNA df_ohneNA
Name Alter
1 Tom 21
2 Paula 20
3 Mia 21
df
Name Alter
1 Tom 21
2 Paula 20
3 Mia 21
4 Jonas NA
Vorsicht: In der Praxis müssen Sie sich immer genau überlegen, ob es wirklich sinvoll ist, die Zeilen mit fehlenden Werten für alle Analysen pauschal zu entfernen! Der richtige Umgang mit fehlenden Werten ist in der Statistik ein kompliziertes Problem, auf das wir hier nicht im Detail eingehen können.
4 Häufige Flüchtigkeitsfehler
Im Folgenden möchten wir die häufigsten Flüchtigkeitsfehler auflisten, die uns allen bei der Arbeit mit R ständig passieren (das ist ganz normal!). Versuchen Sie sich an diese Fehler zu erinnern, wenn mal etwas in R nicht so funktioniert wie erwartet.
Verschreiben
c("Lieblingsesen")] df[ ,
Error in `[.data.frame`(df, , c("Lieblingsesen")): undefined columns selected
Spaltenname falsch geschrieben
Wenn wir uns bei der Spaltenauswahl verschreiben, findet R die Spalte nicht.
<- c("Tom", "Pia", "Nelly") Name <- c(21, 24, 33) Alter <- data.frame(name, Alter) Data
Error in eval(expr, envir, enclos): object 'name' not found
Spaltenname bei der Auswahl falsch geschrieben
Komma vergessen
<- data.frame(Name Alter) Data
Error: <text>:1:25: unexpected symbol 1: Data <- data.frame(Name Alter ^
Ein unerwartetes Symbol heißt oft, dass innerhalb einer Funktion ein Komma zwischen Argumenten vergessen wurde.
Komma vergessen
Anführungszeichen bei Strings vergessen
<- Tom Name
Error in eval(expr, envir, enclos): object 'Tom' not found
statt
<- "Tom" Name
Anführungszeichen bei Strings vergessen
Schließendes Anführungszeichen vergessen
<- "Tom Name
> Name <- "Tom +
Dieser Fehler ist besonders verwirrend, da R den Befehl erst dann ausführt, wenn die Anführungszeichen wieder geschlossen wurden (R denkt es fehlt noch etwas und “wartet”). Die Console zeigt dann statt
>
immer+
an, und reagiert nicht mehr normal auf neue Befehle. In diesem Fall ist es am einfachsten, mit der Maus in die Console zu klicken und die Esc-Taste zu drücken. Danach können Sie den Befehl nochmal korrekt eingeben.Anführungszeichen vergessen
Klammer vergessen
<- c("Tom", "Pia" Name
> Name <- c("Tom", "Pia" +
Auch bei diesem Fehler zeigt die Console solange
+
an, bis Sie die Klammer geschlossen haben. In diesem Fall ist es wieder am einfachsten, mit der Maus in die Console zu klicken und die Esc-Taste zu drücken.schließende Klammer vergessen
Funktion falsch geschrieben
<- dataframe(Name, Alter) Data
Error in dataframe(Name, Alter): could not find function "dataframe"
Funktion falsch geschrieben
Hier könnte jetzt zweierlei passiert sein:
- Die Funktion ist falsch geschrieben (so wie in diesem Fall).
- Die Funktion ist richtig geschrieben, das Paket in dem sich die Funktion befindet, wurde aber noch nicht mittels library(PAKETNAME) geladen.