1 R Basics
1.1 Installation
In diesem Kurs werden wir mit der Sprache R in Kombination mit der Entwicklungsumgebung RStudio arbeiten. Bevor wir mit der Einführung in die grundlegende Bedienung beginnen, zunächst einige Worte zur Installation der kostenlos zugänglichen Software.
1.1.1 R
R ist eine Programmiersprache, die vor allem für statistische Analysen angewandt wird. Generelle Informationen zu R und die ausführliche Dokumentation finden sie unter: https://www.r-project.org/.
Die aktuellste Version von R für alle gängigen Betriebssysteme findet sich stets im CRAN, dem Comprehensive R Archive Network unter: https://cran.r-project.org/. Die Links zu den Installationsdateien finden sich im oberen Bereich der Website. Falls Sie Windows nutzen, wählen Sie bitte die “base” Version. Im Falle von MacOS, hängt die Wahl des Installers von der Version Ihres Betriebssystems ab. In beiden Fällen führen Sie bitte die passende Datei aus und Installieren Sie R in ein Verzeichnis Ihrer Wahl. Für Linux Systeme stellt CRAN Installationsanweisungen für einige der populären Distribution bereit.
Die Code Beispiele auf dieser Website wurden mit der R Version 4.1.1 “Kick Things” erstellt und getestet.
1.1.2 RStudio
R kann nun bereits ausgeführt werden, erlaubt aber nur die Nutzung einer einfachen Konsole. Um die Arbeit mit R angenehmer zu gestalten, empfiehlt sich dringend die zusätzliche Installation einer IDE – Integrated Development Environment – also einer graphischen Benutzeroberfläche. Die populärste IDE ist RStudio, zu finden unter: https://www.rstudio.com/. Unter “Download” wählen Sie bitte die kostenlose Version von “RStudio Desktop” und den passenden Installer für Ihr Betriebssystem.
Installieren Sie bitte zuerst R und erst danach RStudio. Starten brauchen Sie dann in Zukunft nur noch RStudio.
1.2 Erste Schritte
1.2.1 Übersicht RStudio
Das RStudio Interface besteht aus vier Unterbereichen. Links-unten finden Sie die “Console” sowie weitere Tabs, die Sie zu Beginn selten bis nie brauchen werden. Die Konsole kann genutzt werden, um R code einzugeben und auszuführen, mehr dazu in Kürze. Links-oben werden geöffnete R scripts angezeigt. Aktuell haben Sie noch kein script geöffnet, ab Kapitel 2 wird dort aber der überwiegende Teil unserer Arbeit stattfinden. Rechts-oben finden sich mehrere Tabs, von denen für uns vor allem das “Environment” Tab von Interesse ist. Hier werden alle Objekte gelistet die Sie in ihrem code erstellen. Auch hierzu in Kürze mehr. Rechts-unten finden Sie erneute eine Anzahl Tabs. “Files” zeigt uns die Dateistruktur unseres Rechners, “Plots” den graphischen output (siehe Kapitel 3) und “Help” die Hilfedateien zu Funktionen und packages (mehr in Kapitel 2).
1.2.2 Hello World!
Nun können wir endlich damit beginnen unseren ersten R Befehl auszuführen. In
diesem Kapitel werden wir Kommandos noch ausschließlich in der Konsole
schreiben. In der untersten Zeile der Konsole sehen Sie ein >
Symbol. Hinter
dieser Eingabeaufforderung können wir unsere Befehle schreiben und mit “Enter”
ausführen. Versuchen Sie des mit folgender Zeile:
print("Hello World!")
## [1] "Hello World!"
Sie haben gerade ihren ersten R Befehl ausgeführt, Ihren ersten Output erhalten
und gleichzeitig auch Ihre erste Funktion genutzt. Mehr zu Funktionen folgt am
Ende dieses Kapitels, fürs Erste genügt es aber zu wissen, dass print()
alles
innerhalb der Klammern als Output druckt. Der Output selbst beginnt mit [1]
,
was anzeigt, dass dies das erste und hier das einzige Element des Outputs ist.
Bitte beachten Sie, dass R die auf dieser Website vor dem Output dargestellten
##
nicht abdruckt.
1.2.3 Rechnen mit R
R versteht die arithmethischen Operatoren + - * /
. Sie können R also auch als
übergroßen Taschenrechner nutzen. Für fortgeschrittenere Rechenoperationen steht
eine Vielzahl von Funktionen zur Verfügung. Beispielsweise gibt Ihnen sqrt()
die Quadratwurzel der von den Klammern umfassten Zahl als Output zurück. Oben
mussten wir den Text "Hello World!"
in Anführungszeichen einfassen. Zahlen
müssen hingegen ohne Anführungszeichen geschrieben werden. Potenzen bekommen wir
mit der Notation x^y
. Im folgenden Codeblock finden Sie einige Beispiele, die
Sie Zeile für Zeile in die console tippen und mit “Enter” ausführen können:
17 + 25
## [1] 42
99 - 57
## [1] 42
4 * 10.5
## [1] 42
84 / 2
## [1] 42
sqrt(1764)
## [1] 42
6.480741 ^ 2
## [1] 42
1.2.4 Vergleichsoperatoren
Vergleichsoperatoren können genutzt werden um zwei Werte miteinander zu
vergleichen und das Testergebnis als TRUE
oder FALSE
Output zu erhalten. Um
zu überprüfen, ob zwei Werte gleich sind, schreiben wir ==
. Dabei ist zu
beachten, dass ein Vergleich zweier Werte stets zwei Gleichheitszeichen
voraussetzt. =
hat eine andere Bedeutung! Um zu testen ob zwei Werte nicht
gleich sind, können wir !=
nutzen, wobei das !
generell für nicht steht.
42 == 42
## [1] TRUE
42 != 42
## [1] FALSE
Weitere mögliche Vergleiche sind kleiner <
, kleiner gleich <=
, größer
>
und größer gleich >=
.
10 < 42
## [1] TRUE
42 <= 42
## [1] TRUE
10 > 42
## [1] FALSE
90 >= 42
## [1] TRUE
1.3 Objekte
In R können wir Daten und Ergebnisse unserer Analysen in Objekten speichern. So
bleiben diese im Arbeitsspeicher erhalten und können später erneut aufgerufen
und weiterverwendet werden. Ein Objekt ist dabei ein frei gewählter Name dem wir
Daten zuweisen. Namen müssen dabei mit einem Buchstaben beginnen und sollten nur
weitere Buchstaben, Ziffern oder _
beinhalten. Verbreitete Konventionen für
längere Objektnamen sind snake case – the_answer
– und camel case –
theAnswer
. Dies ist letztlich Geschmackssache, es empfielt sich aber eine
einheitliche Schreibweise sowie kurze aber klar verständliche Namen zu
verwenden. Daten weisen wir einem Objekt mit dem assignment operator <-
zu.
<- 42 the_answer
Um sich Fingerakrobatik zu ersparen, ist es sinnvoll sich frühzeitig die
Tastenkombination “Alt” + “-” anzugewöhnen, die <-
an der aktuellen Cursor
Position einfügt.
Die so in einem Objekt gespeicherten Daten können wir aufrufen, indem wir den Objektnamen als Befehl schreiben.
the_answer## [1] 42
Wir können Werte in Objekten auch direkt in Berechnungen oder in Funktionen verwenden. Beachten Sie dabei, dass die Daten eines Objekts überschrieben werden, wenn wir diesem neue Daten zuweisen.
<- the_answer / 2
the_answer
the_answer## [1] 21
<- 17
a <- 4
b <- (a + b) * 2
the_answer
the_answer## [1] 42
So erstellte Objekte werden in dem “Environment” Tab (rechts-oben) gelistet.
Möchten wir erstellte Objekte entfernen, können wir dazu die rm()
Funktion
nutzen. Dies ist zwar in der Regel nicht notwendig, kann aber hilfreich sein um
versehentlich oder nur zum Test erstellte Objekte zu löschen und so den Tab
etwas aufzuräumen.
rm(the_answer)
1.4 Vektoren
Als wir weiter oben eine Zahl einem Objekt zugewiesen haben, haben wir ohne es
zu wissen bereits unseren ersten Vektor erstellt. Vektoren sind eindimensionale
Datenstrukturen, die mehrere Elemente enthalten können. Die Länge eines Vektors
bestimmt sich dabei anhand der Anzahl seiner Elemente. So erstellt auch
the_answer <- 42
einen Vektor, jedoch einen Vektor der Länge 1.
Möchten wir einen Vektor mit mehreren Elementen erstellen, nutzen wir dazu die
Funktion c()
, wobei “c” für “combine” steht. So werden alle durch Kommata
getrennten Werte innerhalb der Klammern zu einem Vektor kombiniert.
<- c(7, 8, 9, 10)
v
v## [1] 7 8 9 10
1.4.1 Subsetting
Möchten wir bestimme Elemente eines Vektors abrufen, nutzen wir subsetting.
Dazu schreiben wir die Position des gewünschten Elements innerhalb des Vektors
als Zahl in []
direkt nach dem Objektnamen. Um beispielsweise das erste oder
das dritte Element unseres Vektors abzurufen:
1]
v[## [1] 7
3]
v[## [1] 9
Mehrere Elemente gleichzeitig rufen wir ab indem wir mehrere Positionen mit
c()
kombinieren oder wir definieren mit :
eine Spannweite von Positionen.
c(1, 3)]
v[## [1] 7 9
2:4]
v[## [1] 8 9 10
1.4.2 Typen von Vektoren
Betrachten wir den Vektor v
im Environment, fällt auf, dass RStudio
num [1:4]
vor den gespeicherten Werten abduckt. Dies drückt zum einen aus,
dass der Vektor die Länge 4 hat, zum anderen zeigt es den Typ des Vektors an.
Hier handelt es sich um einen numerischen Vektor – numeric, ausgedrückt durch
“num” – also einen Vektor der Zahlen enthält.
Um Imformationen zu Typ, Länge und Inhalt von Objekten zu erhalten können wir
auch die Funktion str()
– structure – nutzen. Dies ist vor allem bei
komplexeren Objekten wie Listen oder Dataframes (mehr dazu später) hilfreich, um
einen ersten Überblick zu erhalten, ohne das komplette Objekt abzudrucken.
str(v)
## num [1:4] 7 8 9 10
R kennt noch weitere Typen von Vektoren, wobei für uns vor allem die Typen logical und character von Bedeutung sind.
Logische Vektoren können nur die Werte TRUE
und FALSE
enthalten. Diese
entstehen beispielsweise, wenn wir Vergleichsoperatoren für einen Test nutzen.
<- c(1, 7, 3, 5)
x >= 5
x ## [1] FALSE TRUE FALSE TRUE
Wir können logische Vektoren aber auch selbst erstellen.
<- c(TRUE, FALSE, TRUE)
z
z## [1] TRUE FALSE TRUE
Character Vektoren beinhalten Zeichenfolgen, sogenannte strings. Strings müssen stets von Anführungszeichen umschlossen sein.
<- c("This", "is", "a", "character", "vector!")
char_v
char_v## [1] "This" "is" "a" "character" "vector!"
Auch Character Vektoren können miteinander verglichen werden.
"same" == "same"
## [1] TRUE
"same" == "not the same"
## [1] FALSE
"same" != "not the same"
## [1] TRUE
Da wir mit Character Vektoren natürlich nicht rechnen können, kann es zu Problemen kommen, wenn wir Zahlenwerte – beispielsweise als Strings aus einem Text ausgelesen – als Character Vektor gespeichert haben.
<- c(1, 2, 3)
a <- c("7", "8", "9")
b
str(a)
## num [1:3] 1 2 3
str(b)
## chr [1:3] "7" "8" "9"
+ b
a ## Error in a + b: non-numeric argument to binary operator
Wir können R aber anweisen einen Character Vektor in einen numerischen Vektor umzuwandeln.
+ as.numeric(b)
a ## [1] 8 10 12
Alle Typen von Vektoren können neben ihren nativen Inhalten auch NA
enthalten,
die Repräsentation von fehlenden Werten in R.
<- c(1, 2, NA, 4)
c
c## [1] 1 2 NA 4
1.5 Weitere Datentypen
1.5.1 Dataframes
Dataframes sind zweidimensionale Datenobjekte aus Spalten und Zeilen, also das
was wir uns im Allgemeinen unter einer Tabelle vorstellen. Spalten enthalten
benannte Variablen, Zeilen enthalten Beobachtungen. Um einen Dataframe zu
erstellen nutzen wir die Funktion data.frame()
und definieren innerhalb der
Klammern benannte Spalten und ihre Inhalte, getrennt durch Kommata.
<- data.frame(Name = c("Peter", "Mary"), Alter = c(42, 24), Weiblich = c(FALSE, TRUE))
df
df## Name Alter Weiblich
## 1 Peter 42 FALSE
## 2 Mary 24 TRUE
R erkennt dabei automatisch, welche Datentypen die Spalten enthalten.
str(df)
## 'data.frame': 2 obs. of 3 variables:
## $ Name : chr "Peter" "Mary"
## $ Alter : num 42 24
## $ Weiblich: logi FALSE TRUE
Wir können Dataframes auch aus zuvor definierte Vektoren zusammensetzen.
<- c("Peter", "Mary")
name <- c(42, 24)
age <- c(FALSE, TRUE)
female
<- data.frame(Name = name, Alter = age, Weiblich = female)
df_2
df_2## Name Alter Weiblich
## 1 Peter 42 FALSE
## 2 Mary 24 TRUE
Da Dataframes zweidimensional sind, müssen wir beim Subsetting auch eine
Position für die Zeilen und Spalten angeben. Diese werden ebenfalls in []
nach
dem Objektnamen eingefasst und sind durch ein Komma getrennt. Vor dem Komma
steht die Position der Zeilen, nach dem Komma die Position der Spalten. Für
Spalten können wir statt der Position auch den Namen der Spalte nutzen.
1, 2]
df[## [1] 42
1, "Alter"]
df[## [1] 42
Extrahieren wir mehrere Zeilenelemente gleichzeitig, bekommen wir einen neuen Dataframe zurück. Um eine ganze Zeile zu extrahieren, können wir den Wert der Spaltenposition auch freilassen. Gleiches gilt für ganze Spalten, wobei wir beim Subsetting einer einzelnen Spalte einen Vektor als Output bekommen, bei mehreren erneut einen Dataframe.
1, 2:3]
df[## Alter Weiblich
## 1 42 FALSE
1, ]
df[## Name Alter Weiblich
## 1 Peter 42 FALSE
"Alter"]
df[, ## [1] 42 24
c("Alter", "Weiblich")]
df[, ## Alter Weiblich
## 1 42 FALSE
## 2 24 TRUE
1.5.2 Listen
Vektoren und Spalten von Dataframes können immer nur Daten eines Typs
enthalten. Mischen wir Datentypen, werden diese auf den kleinsten gemeinsamen
Nenner gebracht. Logische Werte können auch numerisch abgebildet werden, da
TRUE
dem Wert 1 entspricht, FALSE
dem Wert 0. In letzter Instanz können alle
Datentypen als Character Vektoren gespeichert werden.
<- c(24, TRUE)
log_vector str(log_vector)
## num [1:2] 24 1
<- c("Mary", 24, TRUE)
char_vector str(char_vector)
## chr [1:3] "Mary" "24" "TRUE"
Möchten wir Datentypen mischen, können wir stattdessen Listen nutzen, welche unterschiedliche Datentypen enthalten können.
<-list("Mary", 24, TRUE)
l str(l)
## List of 3
## $ : chr "Mary"
## $ : num 24
## $ : logi TRUE
Um Listen wieder aufzulösen, nutzen wir unlist()
.
unlist(l)
## [1] "Mary" "24" "TRUE"
Listen können sogar andere Listen enthalten und sind so das flexibelste Datenobjekt das R bereitstellt.
Beim Subsetting von Listen ist darauf zu achten, dass []
immer auch eine Liste
zurückgibt, selbst wenn diese nur noch ein Element enthält. Direkten Zugang zu
Elementen erhalten wir mit [[]]
.
str(l[1])
## List of 1
## $ : chr "Mary"
str(l[[1]])
## chr "Mary"
1.6 R Packages
Die R Welt ist offen und kollaborativ. Neben dem base R Package, das in der Grundinstallation bereits enthalten ist, steht eine stetig steigende Zahl von nutzergeschriebenen Packages zum Download zur Verfügung. Diese Packages haben stets einen thematischen Fokus – beispielsweise Datenbereinigung, graphische Analyse oder Textanalyse – und enthalten eine Reihe von Funktionen, die den Einsatzbereich von R über das hinaus erweitern, was von den Originalentwicklern geplant war, oder kompliziert gestaltete base R Ansätze durch neue anwenderfreundlichere Funktionen ersetzen.
Packages, ihre Dokumentation und weitere Informationen werden ebenfalls auf CRAN gehostet. Hier haben Sie auch bereits die Installationsdateien für R heruntergeladen. Wenn Sie gleich ein Package direkt aus RStudio installieren, greift die Software auf CRAN zu, um die erforderlichen Dateien herunterzuladen.
1.6.1 Installieren und Laden
Packages installieren wir mit der R Funktion install.packages()
, mit dem Namen
des packages in ""
zwischen den Klammern der Funktion. Wir werden im Laufe
des Seminars eine Reihe von Packages nutzen, darunter das tidyverse. Zur
Installation des core tidyverse packages schreiben wir in der Konsole:
install.packages("tidyverse")
R wird während der Installation eine lange Reihe von Informationen ausgeben, von
denen uns – solange alles gut geht – nur das DONE (tidyverse)
interessieren
muss. Nach erfolgreicher Installation können wir das Paket laden. Ein Package
laden wir mit library()
mit dem Namen des Packages innerhalb der Klammern,
hier ausnahmsweise ohne ""
.
library(tidyverse)
Manche Pakete, wie das tidyverse, geben uns auch beim Laden eine Reihe von Informationen, die wir gleich noch genauer betrachten werden. Andere Pakete laden aber auch still, ohne Informationen in die Konsole zu schreiben. Sollte beim Laden eines packages ein Problem auftauchen, wird R dies rückmelden.
1.7 Funktionen
Bis zu diesem Punkt haben wir bereits eine Reihe von Funktionen genutzt, ohne eigentlich zu wissen, was Funktionen sind. Die in base R und den diversen Packages enthaltenen Funktionen bieten einen einfachen Zugang zu komplexeren im Hintergrund ablaufenden Operationen. Statt beispielsweise eine komplizierte Datenanalysetechnik selbst zu implementieren, also jeden Rechenschritt Zeile für Zeile selbst zu schreiben, installieren wir ein Package mit einer passenden Funktion und sparen eventuell mehrere hundert Zeilen Code ein. Außerdem sind die Rechenoperationen in den Packages meist sehr viel effizienter geschrieben als Code, den wir als Laien schreiben würden.
Um eine Funktion aufzurufen, schreiben wir deren Namen gefolgt von
Klammern. Innerhalb der Klammern geben wir ein oder mehrere Argumente an die
Funktion weiter. In vielen Fällen wird als erstes oder eniziges Argument ein
Datenobjekt – oder rohe Daten – angegeben, auf das die Funktion angewandt
werden soll. So “druckt” beispielsweise die base R Funktion print()
die
angegebenen Daten in die Konsole, wie bereits bei print("Hello World!")
gesehen.
Weitere Beispiele für Funktionen sind einige der in base R enthaltenen Möglichkeiten, statistische Maßzahlen zu berechnen. Legen wir zunächst einen numerischen Vektor mit einigen Beispieldaten an:
<- c(4, 8, 15, 16, 23, 42) data
Unser Interesse sei es, das arithmetische Mittel, den Median sowie die
Standardabweichung der Daten zu berechnen. Dazu können wir die Funktionen
mean()
, median()
und sd()
aus base R nutzen. Allen drei Funktionen geben
wir als einziges Argument die zuvor in einem Objekt gespeicherten Daten weiter.
Weitere Argumente sind zwar möglich, für dieses Beispiel aber nicht notwendig.
mean(data)
## [1] 18
median(data)
## [1] 15.5
sd(data)
## [1] 13.49074
Funktionen erlauben häufig mehrere Argumente, von denen einige optional sein können und es beispielsweise ermöglichen bestimmte Optionen einer Funktion zu verändern. Dies wird uns im weiteren Verlauf regelmäßig begegenen.
1.7.1 Namesspaces
Betrachten wir nochmals den Output nach dem Laden von tidyverse weiter oben.
R gibt uns neben Namen und Versionen der geladenen packages – das core
tidyverse Package, welches wir geladen haben ist eigentlich eine Sammlung von
Packages – auch die Information über zwei Konflikte aus. Konflikte entstehen,
wenn zwei geladene packages Funktionen mit den selben Namen enthalten. Die
Funktion aus dem später geladenen package überschreibt dabei die zuvor geladene
Funktion. Hier überschreibt das tidyverse package dplyr die Funktionen
filter()
und lag()
aus dem base R package stats. Ohne dplyr
beziehungsweise tidyverse zu laden wäre beim aufruf von filter()
die
Funktion aus dem stats package genutzt worden. Nun wird die gleichnamige
Funktion aus dplyr angewandt.
Möchten wir zwar dplyr laden, aber die Funktion filter()
aus stats
nutzen, können wir den Namespace der Funktion explizit angeben. Der Namespace
gibt R an, in welchem Package es nach der Funktion suchen soll. Geben wir nur
den Funktionsnamen an, sucht R in den Funktionen die aktuell geladen sind. Da
filter()
aus dplyr die Funktion aus stats überschrieben hat, würde
erstere angewandt. Deklarieren wir den Namespace, können wir R genau angeben, in
welchem geladenen oder ungeladenen package die Funktion zu finden ist. Dazu
nutzen wir die Notation namespace::function
. Um also filter()
aus stats
zu nutzen, schreiben wir: stats::filter()
.
1.8 Hilfe?
1.8.1 Hilfe!
Wir haben nun bereits einige R Funktionen kennengelernt und eine ungefähre Idee davon, was diese machen. Wie bekommen wir aber weitere Informationen zu diesen und neuen Funktionen, zu deren Funktionsweise, den zugelassenen Argumenten oder den zurückgegebenen Ergebnissen?
Der einfachste Weg ist das Nutzen der eingebauten Hilfefunktionalitäten in R.
Dazu schreiben wir in der Konsole einfach ein ?
vor den Namen einer Funktion,
zu der wir Hilfe benötigen. Die zugehörige Hilfedatei öffnet sich dann im “Help”
Tab, rechts-unten. Versuchen wir dies für die Funktion rnorm()
.
rnorm() ?
Die Hilfedatei gibt uns eine ganze Reihe von Informationen. rnorm()
ist Teil
einer Familie von Funktionen, die sich auf die Normalverteilung beziehen. Dabei
ist es die Funktionalität von rnorm()
, Zufallszahlen aus der Normalverteilung zu
generieren. Wir sehen auch, dass wir der Funktion 3 Argumente geben können. Die
Anzahl der zu erzeugenden Zufallszahlen n
sowie Mittelwert mean
und
Standardabweichung sd
der zugrundeliegenden Normalverteilung. Dabei ist zu
erkennen, dass mean
und sd
die Standardwerte 0 beziehungsweise 1 haben.
Diese werden automatisch eingesetzt, wenn wir sie im Funktionsaufruf nicht durch
neue Werte ersetzen. n
hat keinen Standardwert, hier müssen wir also einen
Wert angeben wenn wir die Funktion aufrufen.
rnorm(n = 10)
## [1] -0.3058367 0.7187122 -0.4376060 -0.4125264 -0.6004963 0.4240317
## [7] 1.3075067 0.2435375 -0.1935374 -0.1808801
So bekommen wir 10 Zufallswerte aus der Normalverteilung mit dem Mittelwert 0 und der Standardabweichung 1. Da es sich um Zufallszahlen handelt, wird Ihr Output von dem auf der Website dargestellten abweichen.
Möchten wir Mittelwert und Standardabweichung anpassen, können wir die entsprechenden Argumente nutzen um die Standardwerte durch andere zu ersetzen.
rnorm(n = 10, mean = 10, sd = 0.5)
## [1] 10.782300 9.324677 10.421483 9.335728 11.104446 9.472333 10.257398
## [8] 10.001974 9.754984 9.268117
Die Hilfe gibt uns meist auch weitere detaillierte Informationen zur Funktionsweise und dem Output (unter" Value") der Funktion, sowie eine Reihe von Beispielsanwendungen. Diese Informationen richten sich oft aber an eher erfahrene Nutzer.
Weiter Möglichkeiten sich zur Funktionsweise von Packages sowie R generell zu informieren, finden Sie in Kapitel 2.