Datenanalyse mit R

Online-Tutorial für Anfänger

3.1. Vorbemerkung

In diesem Kapitel werden zunächst Operatoren und Funktionen für grundlegende Rechenoperationen vorgestellt. In nächsten Schritt wird deren Gebrauch von Operatoren und Funktionen im Hinblick auf Vektoren thematisiert. Schließlich erfolgt ein Einblick in Programmabläufe, insb. Definition eigener Funktionen, Schleifen bzw. deren Vermeidung sowie bedingte Anweisungen. Ziel von Programmabläufen ist vor allem, dass Rechenoperationen beschleunigt werden und nachträgliche Änderungen der Programmierung mit weniger Anpassungsaufwand verbunden sind.

3.2. Operatoren

Um Rechenoperationen durchzuführen und R als eine Art "einfachen" Taschenrechner zu nutzen, benötigt man arithmetische Operatoren. Wenn R als eine Art "fortgeschrittener" Taschenrechner genutzt werden soll, werden i. d. R. logische Operatoren benötigt.


Arithmetische Operatoren:

  • + → Addition

  • - → Subtraktion

  • * → Multiplikation

  • / → Division

  • ^ oder ** → Potenzierung


Beispiel 1: R als "einfacher" Taschenrechner

# Division
4/2
# [Ergebnis:
2]

Um logische Operatoren einzusetzen, braucht man Variablen, denen ein bestimmter Wert zugewiesen wird (oder einen Datensatz, der bereits Variablen enthält, vgl. Kapitel 4 zur Erstellung und Import von Datensätzen). Hierzu dient folgender Operator:

  • <- → Übergabe eines Werts an eine Variable


Beispiel 2: Übergabe eines Werts an eine Variable

# Zuweisung
x <- 2

# Test Zuweisung
x
# [Ergebnis: 2]


Logische Operatoren:

  • <Kleiner

  • <=Kleiner gleich

  • > Grösser

  • >=Grösser gleich

  • == Gleich (testet auf Äquivalenz)

  • !=Ungleich

  • !x → Nicht x

  • x | y → x oder y

  • x & y → x und y


Beispiel 3: R als "fortgeschrittener" Taschenrechner

# Logische Prüfung, ob x gleich 2 ist
x==2
# [Ergebnis: TRUE]

# Logische Prüfung, ob x ungleich 2 ist
x!=2
# [Ergebnis: FALSE]

3.3. Funktionen

Im Folgendem werden mathematische Funktionen aufgelistet, die bei der Programmierung verschiedenen Zwecken dienen können. Vorab sind zwei Hinweise wichtig:

  1. Falls sich fehlende Werte (NA) im Datensatz befinden, sollte das Argument na.rm = FALSE angegeben werden, um sie zu entfernen. Beispiel zur Berechnung des Mittelwertes:
    mean(x, na.rm = FALSE) → Berechnung des Mittelwertes; fehlende Werte von x wurden entfernt

  2. Funktion können ineinander verschachtelt werden, d. h. der Output einer Funktion kann einer weiteren Funktion als Input übergeben werden. Beispiel zur Verschachtelung der Funktionen round() und mean():
    round(mean(x), digits = 2) → Berechnung des Mittelwertes von x und Rundung auf zwei Nachkommastellen

Hier folgt eine Auswahl mathematischer Funktionen, die sich in numerische und statistische Funktionen unterteilen lassen:


Numerische Funktionen:

  • abs(x)Betrag

  • sqrt(x) Quadratwurzel

  • ceiling(x) Aufrunden

  • floor(x)Abrunden

  • round(x, digits = 2)Runden von x mit z. B. zwei Nachkommastellen

  • log(x)Natürlicher Logarithmus

  • log(x, base = 2) Logarithmus z. B. zur Basis 2

  • exp(x)Exponentialfunktion (e ^ x)


Statistische Funktionen:

  • mean(x) Mittelwert

  • sd(x) Standardabweichung

  • var(x) Varianz

  • median(x)Median

  • sum(x)Summe

  • min(x)Minimalwert

  • max(x)Maximalwert

  • range(x) → Differenz zwischen Minimal- und Maximalwert

3.4. Vektoren und Matrizen

Die bereits vorgestellten arithmetischen und logischen Operatoren sowie mathematische Funktionen können auf Vektoren und Matrizen angewandt werden. Für Matrizen erfolgt in diesem Kapitel nur ein kurz gehaltener Exkurs.


Arithmetische Operatoren:

Die arithmetischen Operatoren (+, -, *, usw.) können auf zwei Vektoren angewandt werden. Hierbei könne zwei Fälle unterschieden werden:

  • Falls beide Vektoren die gleiche Länge haben, werden die jeweiligen Elemente an der gleichen Position entsprechend dem Operator verknüpft (vgl. Kapitel 2 zu Datenobjekten, insb. auch zu den Themen Länge und Modus).

  • Sind die Vektoren unterschiedliche Länge wird der kürzere Vektor solange wiederholt bis er die Länge des längeren Vektors hat. Anschließend erfolgt die Berechnung. Weil die Berechnung leicht zu Fehlern führen kann, gibt R eine entsprechende Warnmeldung aus.


Beispiel 1: Addition zweier Vektoren

# Zwei Vektoren gleicher Länge werden generiert
x <- c(1,2,3,4)
y <- c(5,6,7,8)

# Addition
x + y
# [Ergebnis: 6 8 10 12]

# Zwei Vektoren unterschiedlicher Länge werden generiert
x <- c(1,2,3,4)
y <- c(5,6,7)

# Addition
x + y
# [Ergebnis: 6 8 10 9

Warning message:
In x + y : longer object length is not a multiple of shorter object length]


Logische Operatoren:

Grundsätzlich können auch die logischen Operatoren (>=, x!, usw.) auf Vektoren angewandt werden.


Beispiel 2: Logische Prüfung elementweise

# Drei Vektoren werden generiert
x <- c(1,2,3,4)
y <- c(5,6,7,8)
z <- 3

# Prüfung, ob Elemente von x größer bzw. gleich y sind
x >= y
# [Ergebnis: FALSE FALSE FALSE FALSE]

# Prüfung, ob Elemente von x kleiner bzw. gleich y sind
x <= y
# [Ergebnis: TRUE TRUE TRUE TRUE]

Prüfung, ob Elemente von x gleich z sind
x!=z
# [Ergebnis: TRUE TRUE FALSE TRUE]


Funktionen:

Sowohl numerische als auch statistische Funktion können naturgemäß auf Vektoren angewandt werden. Darüber hinaus gibt es auch spezielle Vektorfunktionen wie cumsum() oder cumprod(), die im nachfolgendem Beispiel 3 erläutert werden.


Beispiel 3: Anwendung von Funktionen auf Vektoren

# Vektor wird generiert
x <- c(1,2,3,4)

# Mittelwert von x
mean(x)
# [Ergebnis 2.5]

# Varianz von x
var(x)
# [Ergebnis 1.666667]

# Quadratwurzel aller Elemente von x (mit Abrundung auf zwei Nachkommastellen)
round(sqrt(x), digits = 2)
# [Ergebnis 1.00 1.41 1.73 2.00]

# Cumsum-Funktion generiert Ergebnisvektor mit kumulierter Summe (bis zum entsprechender Vektoreintrag)
cumsum(x)
# [Ergebnis: 1 3 6 10]

# Cumprod-Funktion analog mit kumuliertem Produkt
cumprod(x)
# [Ergebnis: 1 2 6 24]


Exkurs: Matrizen

Für Matrizen erfolgt in diesem Kapitel nur ein kurz gehaltener Exkurs, da es eine Vielzahl an Besonderheiten gibt. Matrizen werden mit dem Befehl matrix() erzeugt. Hierbei ist neben den Elementen auch die Dimension der Matrix anzugeben:

  • nrow → Anzahl der Zeilen

  • ncol → Anzahl der Spalten

  • byrow=TRUE → Durch diese Angabe werden die Elemente der Matrix zeilenweise aufgefüllt.


Beispiel 4: Anwendungen von Operatoren und Funktionen auf Matrizen

# Matrizen erzeugen
A <- matrix(c(1,2,
3,6,
5,10), nrow=3, ncol=2, byrow=TRUE)

B <- matrix(c(1,2,3,
1,2,3), nrow=2, ncol=3, byrow=TRUE)

# Matrizen anzeigen lassen
A
B

# Addition von 3
A+3

# Multiplikation A mit B
# Achtung: %-Zeichen bei Matrizenmultiplikation beachten
A%*%B

# Elementweise Prüfung ob Matrix A den Wert 2 hat
A == 2

Anbei findet sich ein Auszug zur besseren Veranschaulichung der Ergebnisse von Beispiel 4:

3.5. Eigene Funktionen

Neben den bereits vorhandenen Funktionen ist es in R möglich, eigene Funktionen zu definieren. Eine Funktion besteht aus drei Teilen:

  1. Name der Funktion
    (vgl. Beispiel 1: "mal2")

  2. Angabe des Arguments bzw. der Argumente
    (vgl. Beispiel 1: "(x)" in runden Klammern)

  3. Funktionsdefinition mit function ()
    (vgl. Beispiel 1: "{x*2}" in geschweiften Klammern)


Beispiel 1: Eigene Funktion mit einem Argument definieren

# Multiplikation mit 2
mal2 <- function(x){x*2}

# Wertzuweisung Argument
z <- c(1,2,3)

# Aufruf der Funktion
mal2(z)
# [Ergebnis: 2 4 6]


Beispiel 2: Eigene Funktion mit zwei Argumenten definieren

# Multiplikation mit a
mala <- function(x, a){x*a}

# Wertzuweisung Argumente
z <- c(1,2,3)
a <- c(2,4,6)

# Aufruf der Funktion
mala(z,a)
# [Ergebnis: 2 8 18]

3.6. Schleifen bzw. deren Vermeidung

for-Schleifen

In einer for-Schleife wird jeden angenommenen Wert ein angegebener Befehl ausgeführt. Sie besteht aus drei Teilen:

  1. Vorangestellt steht der Schleifen-Befehl for

  2. Name der Indexvariablen und die zu durchlaufende Wertemenge
    (vgl. Beispiel 1: "(x in 1:10)" in runden Klammern)

  3. Ein oder mehrere Befehle, die bei jedem Schleifendurchlauf ausgeführt werden
    (vgl. Beispiel 1: "{print(paste(x*2))}" in geschweiften Klammern)


Beispiel 1: for-Schleife

# Wertemenge x (1 bis 3) wird mit 2 multipliziert und als Ergebnis angezeigt
for (x in 1:3) {print(paste(x^2))}
# [Ergebnis: 2 4 6]


while-Schleifen

Die while-Schleife wiederholt Anweisungen solange eine Bedingung erfüllt ist. Sie besteht ebenfalls aus drei Teilen, jedoch ist vorab die Konstruktion einer Unter- und Obergrenze (für die Bedingung) nötig:

  1. Vorangestellt steht der Schleifen-Befehl while

  2. Bedingung, die erfüllt sein muss, damit Anweisung ausgeführt wird
    (vgl. Beispiel 2: "(x<n)" in runden Klammern)

  3. Befehle, die bei jedem Schleifendurchlauf ausgeführt werden;
    im Gegensatz zur for-Schleife wird hier zunächst der Durchlauf initiiert ("x <- x+1")
    (vgl. Beispiel 2: "{x <- x+1; print(paste(x*2))}" in geschweiften Klammern)


Beispiel 2: while-Schleife

# Konstruktion einer Unter- und Obergrenze
x <- 0
n <- 3

# while-Schleife
while (x<n){x <- x+1;
print(paste(x*2))}
# [Ergebnis: 2 4 6]


Vermeidung von Schleifen

In R stehen neben Lösungen mit Schleifen auch einfache und effiziente Methoden zur Verfügung, die speziell für die Bedürfnisse der Datenanalyse entwickelt wurden.

  1. Mittels der Befehle apply(), lapply(), mapply() und sapply() können verschiedene Statistiken für Variablen eines Objekts, bspw. einer Matrix, berechnet werden.

  2. Mittels der Befehle tapply() und by() können Statistiken auch für Teilgruppen eines Datensatzes berechnet werden.

Im folgendem Beispiel 3 wird exemplarisch die "Mutter dieser Befehlsfamilie" apply() veranschaulicht.


Beispiel 3: Anwendung des Befehls apply()

# Konstruktion einer Matrix
x <- matrix(1:9,ncol = 3)
# [Ergebnis:
1 4 7
2 5 8
3 6 9]

# Ermittlung der Spaltensummen
apply(X=x, MARGIN=2, FUN = sum)

# Ergänzende Hinweise:
# x wird dem Funktionsparameter X übergeben
# MARGIN legt fest, ob Funktion auf die Zeilen (1) oder Spalten (2) angewendet wird
# FUN legt fest, dass bspw. die Summenfunktion sum angewendet wird

# Kurzform des Befehls
apply(x, 2, sum)
# [Ergebnis: 6 15 24]

# Weiteres Beispiel: Ermittlung des Durchschnitts (zeilenweise)
apply(x, 1, mean)
# [Ergebnis: 2 5 8]

3.7. Bedingte Anweisungen

Bedingte oder konditionale Anweisungen können eingesetzt werden, wenn die Ausführung von Befehlen von Bedingungen abhängt.

Bedingte Anweisung als if-else-Konstruktion

Eine if-else-Konstruktion besteht aus drei Teilen:

  1. Vorangestellt steht der Befehl if

  2. Bedingung, die erfüllt sein muss, damit Befehl ausgeführt wird
    (vgl. Beispiel 1: "(sum(x)<10)" in runden Klammern)

  3. Befehle, die ausgeführt werden sollen, falls Bedingung erfüllt ist, finden sich in der ersten geschweiften Klammer.
    Falls die Bedingung nicht erfüllt ist, wird die Anweisung hinter dem else ausgeführt.
    (vgl. Beispiel 1: "{x*10} else {x-x}" in geschweiften Klammern)


Beispiel 1: Bedingte Anweisung mit if-else-Konstruktion

# Konstruktion eines Vektors
x <- 0:4
# [Ergebnis: 0 1 2 3 4]

# Falls die Summe von x < 10 ist,
# multipliziere jedes Vektorelement mit 10,
# sonst setze x = 0
if(sum(x)<10){x*10} else {x-x}
# [Ergebnis: 0 0 0 0 0]

# Falls die Summe von x < 11 ist,
# s.o.
if(sum(x)<11){x*10} else {x-x}
# [Ergebnis: 10 20 30 40 50]


Bedingte Anweisung mit Befehl ifelse()

Falls man Variablen umkodieren möchte (vgl. Kapitel 4 zur Erstellung eigener Datensätze), besteht oft die Notwendigkeit dies in Abhängigkeit von anderen Werte zu tun. Hierfür kann man den Befehl ifelse() nutzen.


Beispiel 2: Bedingte Anweisung mit ifelse()

# Konstruktion eines Vektors
x <- 0:4
# [Ergebnis: 0 1 2 3 4]

# Falls x<3 ist, multipliziere Vektorelement mit 10, sonst x = 0
ifelse(x<3, x*10, x-x)
# [Ergebnis: 0 10 20 0 0]