Kapitel 4 Grundlegende Befehle in R

Zu jedem R-Befehl lässt sich eine Hilfeseite anzeigen. Diese gibt grundlegende Informationen über Funktionsweisen des Befehls sowie die zugelassenen Befehlsoptionen. Die meisten Hilfeseiten enden mit ein paar Beispielen. Die Hilfeseiten erreicht man mit dem Befehl help() oder kurz ?, wobei der Befehl, dessen Hilfsseite wir aufrufen möchten, innerhalb der Befehlsklammern stehen muss.

# gib Hilfeseite für Funktion "mean" aus 
help(mean)
# oder einfach 
?mean

Wenn Sie den Befehl help(mean) z.B. mit [STRG] + [R] ausführen, oder direkt unten in die R-Konsole eingeben, zeigt RStudio die Hilfeseiten im unteren rechten Viertel an (siehe Abbildung 4.1).

Abbildung 4.1: Hilfeseite wird unten rechts angezeigt

In diesem Buch werden die R-Befehle nie vollständig mit all ihren Optionen und Einstellungsmöglichkeiten vorgestellt. Daher bietet es sich an, bei jedem “neuen” Befehl, den man lernt oder verwendet, per help() oder ? die Anleitungsseite zumindest zu überfliegen.

# bei help() steht die Funktion in Klammern 
# gib Hilfeseite für Funktion "c()" aus 
help(c)

# Bei ? wird sie ohne Klammern direkt drangeschrieben 
?c 
?mean 
?median

Mit quit() oder kurz q() wird die R-Sitzung beendet.

# Beende die R-Sitzung 
quit()
# Beende die R-Sitzung 
q()
# Rufe Hilfeseite auf 
?quit

Wenn Sie den Befehl quit() in der R-Konsole von RStudio ausführen, wird auch RStudio beendet.

4.1 Rechnen mit R

R funktioniert unter anderem wie ein mächtiger Taschenrechner. Folgende grundlegende mathematische Operationen können mit R ausgeführt werden:

Operation Symbol
Addition +
Subtraktion \(-\)
Multiplikation *
Division /
Potenzieren  ̂oder **
Wurzel sqrt(x)


Hier ein paar Beispiele:

# Addition 
2+8
## [1] 10
# Subtraktion 
9-7
## [1] 2
# Multiplikation 
4*4
## [1] 16
# Division 
6/2
## [1] 3
# Potenzieren 
2^3
## [1] 8
# Exponent anders notiert 
2**3
## [1] 8
# Quadratwurzel 
sqrt(25)
## [1] 5

Vielleicht haben Sie sich schon gefragt, wieso vor jeder Ausgabe die Zeichenkette ## [1] steht. Die Rauten ## sehen Sie in Ihrer R Konsole nicht. Sie wurden von RMardown (siehe Abschnitt 5) für diese Webseitenversion des Buches erzeugt um anzugeben, dass es sich um eine R-Ausgabe handelt, und nicht um R-Befehle. So kann auch nichts schief gehen, falls Sie Code-Chunks von dieser Seite markieren, kopieren und in Ihre Scriptdatei übertragen, denn dort kommentieren die ## die Zeile aus, so dass sie nicht ausgeführt werden.

Die [1] erklärt sich folgendermaßen. In R beginnt jede Ausgabezeile mit der Position des Wertes, der als nächstes ausgegeben wird. Da wir derzeit nur Rechenoperationen durchführen, die genau ein Ergebnis haben, ist die Position unseres Ergebniswertes immer [1]. Hat man längere Datenreihen, z.B. das Gewicht von 10 Probanden in kg, dann könnte die Ausgabe so aussehen:

## [1] 102.20  76.83  98.50  86.55  121.93
## [6]  89.21 123.22  78.23  98.33   83.37

Die zweite Ausgabezeile beginnt mit einer [6], was bedeutet, dass nachfolgend die 6. Position der Wertereihe angezeigt wird.

Das Ziehen einer Wurzel erfolgt über die Funktion sqrt(). Damit Funktionen arbeiten können, benötigen sie ein “Argument.” Das Argument ist in unserem Fall die Zahl 25, da wir die Wurzel aus 25 ziehen wollen.

# Wurzel ziehen 
sqrt(25)
## [1] 5

Argumente werden der Funktion in runden Klammern übergeben. So erklärt sich der Befehl sqrt(25).

# Lange Formel 
sqrt( (2*10) / (20/2) ) - 9
## [1] -7.585786

An der letzten Ausgabe zeigt sich ein wesentliches Merkmal von R:
Dezimalstellen werden mit einem Punkt UND NICHT mit einem Komma dargestellt.
Dies ist ein häufiger Anfängerfehler und meist der Grund, warum am Anfang etwas nicht funktioniert.

# Dezimalstellen mit . 
4.25 * 6.25
## [1] 26.5625
# nicht mit Komma!
# schlägt fehl
4,25 * 6,78 
## Fehler: Unerwartete(s) ',' in "4,"

4.1.1 Nachkommastellen

R zeigt standardmäßig 6 Nachkommastellen an. Intern rechnet R mit “doppelter Genauigkeit.” Damit sind Nummern mit ca. 17 Stellen (1 Ziffer + 16 Nachkommastellen oder eben eine 17 stellige Zahl ohne Nachkommastellen) repräsentierbar. Möchte man die Nachkommastellen entsprechend angezeigt bekommen, so kann man dies mit der options-Funktion einstellen:

# gib ab jetzt 16 Nachkommastellen aus 
options(digits=17)
# Wurzel aus 3 
sqrt(3)
## [1] 1.7320508075688772

Nach dieser Eingabe liefert R Ergebnisse mit bis zu 16 Nachkommastellen.

Wir stellen den Wert wieder zurück auf 6 Nachkommastellen.

# gib ab jetzt wieder "nur" 6 Nachkommastellen aus
options(digits=7)

4.1.2 Runden

Ziehen wir die Wurzel aus 3, erhalten wir ein Ergebnis mit 6 Nachkommastellen.

# Wurzel aus 3 
sqrt(3)
## [1] 1.732051

Dieses Ergebnis kann mit der Funktion round() gerundet werden.

# Runde auf 2 Nachkommastellen 
round(sqrt(3), digits=2)
## [1] 1.73
# Runde auf ganze Zahl 
round(sqrt(3))
## [1] 2

Neben round() existieren noch die Spezialfunktionen ceiling() und floor(). Die Funktion ceiling() rundet immer zur nächsten ganzen Zahl auf, und die Funktion floor() rundet immer zur nächsten ganzen Zahl ab.

# ceiling rundet immer auf 
ceiling(sqrt(3))
## [1] 2
# ceiling rundet immer auf 
ceiling(1.0008)
## [1] 2
# floor rundet immer ab 
floor(sqrt(3))
## [1] 1
# floor rundet immer ab floor(1.9999)

4.2 Variablen

Variablen dienen der Speicherung von Werten oder komplexen Daten. Variablen bestehen aus einem Namen und dem zugewiesenen Wert (bzw. Werten). Der Name einer Variable in R darf nicht mit einer Zahl beginnen, das heisst Variablennamen wie 1stTry sind nicht erlaubt. Ein Wert kann einer Variable auf zwei Weisen zugewiesen werden:

# weise Variable "x" den Wert 8 zu 
x <- 8

Die in R gängige Variante ist das Zuweise mittels “Pfeil,” den man mit < und - nachahmt.

Die Zuweisung per Gleichheitszeichen funktioniert aber ebenso.

# weise Variable "x" den Wert 8 zu 
x <- 8

# funktioniert auch mit "=" 
x = 8

Wir haben nun eine Variable x mit dem Wert 8. Beachten Sie, dass R zwischen Groß- und Kleinschreibung unterscheidet. Unsere Variable heisst x und nicht X!

In RStudio wird uns nun im Datenfenster (oberes rechtes Viertel) die Variable x mit ihrem Wert 8 angezeigt (Abbildung 4.2).

Abbildung 4.2: Variablen werden oben rechts angezeigt

Den Wert einer Variable können wir ausgeben lassen, indem wir einfach ihren Namen in die R-Konsole schreiben

# gib Wert von x aus 
x
## [1] 8

Wie erwähnt unterscheidet R zwischen Groß- und Kleinschreibung, und so erhalten wir einen Fehler wenn wir eingeben:

# großes "X", kein kleines "x" 
X
## Fehler: Objekt 'X' nicht gefunden


Mit Variablen kann auch gerechnet werden:

# erzeuge Variable "y" mit Wert 10 
y <- 10 
# erzeuge Variable "z" mit Wert 5 
z <- 5 
# rechne ein bisschen 
x+y+z
## [1] 23
# noch ein bisschen rechnen 
x/(y+z)
## [1] 0.5333333
# speichere Ergebnis in weitere Variable "Dummy" 
Dummy <-x+(y^z)
# Gib Wert(e) von Dummy aus 
Dummy
## [1] 100008

4.2.1 Wertereihen

Wir können einer Variable auch eine Wertereihe (also mehrere Werte) zuweisen. Dies erfolgt für gewöhnlich mit der Funktion c() (für concatenate, “aneinanderreihen”), indem man die einzelnen Werte mit einem Komma getrennt der Funktion übergibt.

# weise Wertereihe 1 bis 10 mit c() zu 
a <- c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 
# Gib Werte von "a" aus 
a
##  [1]  1  2  3  4  5  6  7  8  9 10

Mit c() kann auch Text, also z.B. Wörter, übergeben werden.

# es müssen keine Zahlen sein 
b <- c("eins", "zwei", "drei", "vier", "fünf", "sechs", "sieben", "acht", "neun", "zehn")
# Gib Werte von "b" aus 
b
##  [1] "eins"   "zwei"   "drei"   "vier"   "fünf"   "sechs"  "sieben" "acht"  
##  [9] "neun"   "zehn"

Der Text muss in Anführungszeichen gesetzt werden, da R ansonsten nicht das Wort "fünf" versteht, sondern nach einer Variable namens fünf sucht. Denn Variablen können ebenfalls aneinandergereiht werden.

# Variablen aneinanderreihen 
c(x, y, z)
## [1]  8 10  5

Wichtig ist, dass innerhalb der c()-Kette nur Werte des selben Typs (entweder Zahlen oder Text) angegeben werden. Mischt man Text mit Zahlen, wandelt c() die Wertereihe auf den “kleinsten gemeinsamen Nenner” um, und das ist immer “Text.”

# c() fällt auf den "kleinsten gemeinsamen Nenner" zurück 
c(x, y, z, b)
##  [1] "8"      "10"     "5"      "eins"   "zwei"   "drei"   "vier"   "fünf"  
##  [9] "sechs"  "sieben" "acht"   "neun"   "zehn"

Aus den Zahlen 8, 10 und 5 sind die Wörter "8", "10" und "5" geworden, und mit denen kann man nun keine Rechenoperationen mehr durchführen.

Das Mischen der Wertetypen ist ein weiterer häufiger Anfängerfehler.

Mit der Funktion length() kann die länge der Wertereihe bestimmt werden

# länge von Variable "a" 
length(a)
## [1] 10

Variable a besteht aus 10 Werten.

# länge von Variable "Dummy" 
length(Dummy)
## [1] 1

Variable Dummy besteht aus 1 Wert.

4.2.2 Variablen löschen

Im Datenfenster von RStudio (rechtes oberes Viertel) werden alle Variablen angezeigt (Abbildung 4.3).

Abbildung 4.3: Variablen werden oben rechts angezeigt

Wir sehen dort unsere Variablen a, b, Dummy, x, y und z. Rechts daneben zeigt RStudio zusammenfassende Informationen zu den Variablen an. So sieht man direkt, dass der Wert von Dummy = 100008 ist, oder dass a zehn Werte enthält.

In der R-Konsole können alle vorhandenen Variablen mit der Funktion ls() angezeigt werden.

# zeige alle Variablen an 
ls()
##  [1] "a"               "Ausfall"         "b"               "c0"             
##  [5] "c0.ll"           "cd"              "confirmed"       "confirmedraw"   
##  [9] "country"         "crm"             "crm.aic"         "crm.ce"         
## [13] "crm.devi"        "crm.ll"          "crm.nagel"       "d"              
## [17] "deaths"          "deathsraw"       "df"              "Dummy"          
## [21] "epa"             "fehler95"        "fehler99"        "fit"            
## [25] "germany"         "Geschlecht"      "get.ci"          "haeufigkeiten"  
## [29] "k"               "kategorie"       "Lesetest"        "mma"            
## [33] "mx"              "mydata"          "n"               "N"              
## [37] "n1"              "n2"              "na"              "nb"             
## [41] "ncrm"            "neu"             "npom"            "nw"             
## [45] "nwbp"            "ordinalSample"   "p"               "p0"             
## [49] "p0.ll"           "p1"              "p2"              "pf8"            
## [53] "pf8sub"          "Pflegeberufe"    "Pflegeframe"     "Pflegetibble"   
## [57] "pom"             "pom.aic"         "pom.coef"        "pom.cox"        
## [61] "pom.devi"        "pom.ll"          "pom.mcfad"       "pom.nagel"      
## [65] "pom.odds"        "pom.pdevi"       "ppom"            "ppom.ce"        
## [69] "Punktwert"       "Punktwerte"      "Rechtschreibung" "recovered"      
## [73] "recoveredraw"    "s"               "s_pool"          "sa"             
## [77] "sb"              "shuttle"         "spss"            "t0"             
## [81] "t1"              "tbl"             "Temp"            "test"           
## [85] "untidy_df"       "world"           "x"               "xa"             
## [89] "xb"              "xquer"           "xsd1"            "xsd2"           
## [93] "xtabelle"        "y"               "ymx"             "ysd1"           
## [97] "ysd2"            "z"

Variablen lassen sich mit dem Befehl rm() löschen.

# lösche Variable "Dummy" 
rm(Dummy)
# zeige alle Variablen an 
ls()
##  [1] "a"               "Ausfall"         "b"               "c0"             
##  [5] "c0.ll"           "cd"              "confirmed"       "confirmedraw"   
##  [9] "country"         "crm"             "crm.aic"         "crm.ce"         
## [13] "crm.devi"        "crm.ll"          "crm.nagel"       "d"              
## [17] "deaths"          "deathsraw"       "df"              "epa"            
## [21] "fehler95"        "fehler99"        "fit"             "germany"        
## [25] "Geschlecht"      "get.ci"          "haeufigkeiten"   "k"              
## [29] "kategorie"       "Lesetest"        "mma"             "mx"             
## [33] "mydata"          "n"               "N"               "n1"             
## [37] "n2"              "na"              "nb"              "ncrm"           
## [41] "neu"             "npom"            "nw"              "nwbp"           
## [45] "ordinalSample"   "p"               "p0"              "p0.ll"          
## [49] "p1"              "p2"              "pf8"             "pf8sub"         
## [53] "Pflegeberufe"    "Pflegeframe"     "Pflegetibble"    "pom"            
## [57] "pom.aic"         "pom.coef"        "pom.cox"         "pom.devi"       
## [61] "pom.ll"          "pom.mcfad"       "pom.nagel"       "pom.odds"       
## [65] "pom.pdevi"       "ppom"            "ppom.ce"         "Punktwert"      
## [69] "Punktwerte"      "Rechtschreibung" "recovered"       "recoveredraw"   
## [73] "s"               "s_pool"          "sa"              "sb"             
## [77] "shuttle"         "spss"            "t0"              "t1"             
## [81] "tbl"             "Temp"            "test"            "untidy_df"      
## [85] "world"           "x"               "xa"              "xb"             
## [89] "xquer"           "xsd1"            "xsd2"            "xtabelle"       
## [93] "y"               "ymx"             "ysd1"            "ysd2"           
## [97] "z"

Um alle Variablen zu löschen, verknüpfen wir den ls()-Befehl mit rm(). So änder sich der Befehl in:

# lösche ALLE Variablen 
rm(list=ls())

# zeige alle Variablen an 
ls()
## character(0)

In RStudio löschen Sie alle Objekte aus dem Arbeitsspeicher, indem Sie im Datenfenster auf den kleinen Besen klicken (Abbildung 4.4 ).

Abbildung 4.4: alle Variablen löschen

4.3 Wertesequenzen erzeugen

Bislang haben wir unsere Daten von Hand eingeben. Für die Zahlenreihe von 1 bis 10 sah das so aus:

# Zahlenreihe von 1 bis 10 
zahlen <- c(1, 2, 3, 4, 5, 6, 7, 8, 9 ,10)
# ausgeben 
zahlen
##  [1]  1  2  3  4  5  6  7  8  9 10

In R lassen sich solch kontinuierliche Reihen mit einem : erzeugen:

# auch Zahlenreihe von 1 bis 10 
zahlen <- 1:10

# ausgeben 
zahlen
##  [1]  1  2  3  4  5  6  7  8  9 10

In Kombination mit c() geht auch:

# neuer Vektor aus 2 Zahlenreihen 
zahlen2 <- c(1:10, 100:110)

# ausgeben 
zahlen2
##  [1]   1   2   3   4   5   6   7   8   9  10 100 101 102 103 104 105 106 107 108
## [20] 109 110

Mit der Funktion seq() lassen sich Sequenzen erstellen. Wir übergeben der Funktion Start- und Endpunkt, und in welchen Schritten gezählt werden soll. Eine Zahlenreihe von 1 bis 10 in den Schritten 0.5 erzeugt man so:

# eine Sequenz erstellen 
sequenz <- seq(from=1, to=10, by=0.5)

# ausgeben 
sequenz
##  [1]  1.0  1.5  2.0  2.5  3.0  3.5  4.0  4.5  5.0  5.5  6.0  6.5  7.0  7.5  8.0
## [16]  8.5  9.0  9.5 10.0

oder schlicht

# erstellt die selbe Sequenz 
sequenz <- seq(1, 10, 0.5)

# ausgeben 
sequenz
##  [1]  1.0  1.5  2.0  2.5  3.0  3.5  4.0  4.5  5.0  5.5  6.0  6.5  7.0  7.5  8.0
## [16]  8.5  9.0  9.5 10.0

Mit der Funktion rep() (für repeat) lassen sich wiederholte Werte erzeugen

# erzeuge 20 wiederholte Werte, 
# 20 mal "weiblich" 
geschlecht <- rep("weiblich", 20)

# ausgeben 
geschlecht
##  [1] "weiblich" "weiblich" "weiblich" "weiblich" "weiblich" "weiblich"
##  [7] "weiblich" "weiblich" "weiblich" "weiblich" "weiblich" "weiblich"
## [13] "weiblich" "weiblich" "weiblich" "weiblich" "weiblich" "weiblich"
## [19] "weiblich" "weiblich"

In Kombination mit c() geht auch:

# erzeuge 20 wiederholte Werte, 
# 10 mal "weiblich" und 10 mal "maennlich" 
geschlecht <- c(rep("weiblich", 10), rep("maennlich", 10))
# ausgeben 
geschlecht
##  [1] "weiblich"  "weiblich"  "weiblich"  "weiblich"  "weiblich"  "weiblich" 
##  [7] "weiblich"  "weiblich"  "weiblich"  "weiblich"  "maennlich" "maennlich"
## [13] "maennlich" "maennlich" "maennlich" "maennlich" "maennlich" "maennlich"
## [19] "maennlich" "maennlich"

Oder anders verschachtelt:

# erzeuge 20 wiederholte Werte, anders verschachtelt 
# 10 mal das Paar "weiblich" "maennlich" 
geschlecht <- rep(c("weiblich", "maennlich"), 10)
# ausgeben 
geschlecht
##  [1] "weiblich"  "maennlich" "weiblich"  "maennlich" "weiblich"  "maennlich"
##  [7] "weiblich"  "maennlich" "weiblich"  "maennlich" "weiblich"  "maennlich"
## [13] "weiblich"  "maennlich" "weiblich"  "maennlich" "weiblich"  "maennlich"
## [19] "weiblich"  "maennlich"

In R lassen sich auch Zufallszahlen generieren. Hierfür steht die Funktion sample() zur Verfügung.

# erzeuge 20 Zufallswerte 
sample(20)
##  [1] 19 10 14  7  4  1 11  5 16 15 12  2 17 13  3 18  9  8  6 20

Der Bereich, aus welchem die Zahlen gezogen werden sollen, kann ebenfalls angegeben werden.

# erzeuge 20 Zufallswerte zwischen 150 und 250 
sample(150:250, 20)
##  [1] 229 155 190 225 169 185 199 250 206 201 189 237 202 193 151 179 243 166 196
## [20] 214

Über die Option replace kann angegeben werden, ob Werte auch doppelt vorkommen können (so genanntes zurücklegen).

# erzeuge 20 Zufallswerte zwischen 150 und 250 # MIT zurücklegen
sample(150:250, 20, replace=TRUE)
##  [1] 184 197 246 235 203 190 246 212 248 231 235 161 210 231 205 236 152 239 174
## [20] 162

Zudem bieten die in R implementierten Wahrscheinlichkeitsverteilungen

über ihre r-Funktionen (für random, siehe Abschnitt 4.14) die Möglichkeit, zufällige Werte zu erzeugen.

Die Funktion runif() erzeugt Zufallswerte aus der “stetigen Gleichverteilung.” Standardmäßig liegen die Zufallswerte zwischen 0 und 1.

# erzeuge 20 Zufallswerte zwischen 0 und 1 
runif(20)
##  [1] 0.17324598 0.21153932 0.44238444 0.32209622 0.19281530 0.73139233
##  [7] 0.19460091 0.95348902 0.31724486 0.39824062 0.99718117 0.47798915
## [13] 0.59387327 0.32777325 0.82316858 0.95957473 0.91187734 0.08144214
## [19] 0.79907711 0.36198429

Man kann aber (ähnlich wie bei sample()) den Bereich festlegen, aus welchem die Werte gezogen werden sollen.

# erzeuge 20 Zufallswerte zwischen 30 und 150 
runif(20, min=30, max=150)
##  [1]  93.85357  84.08660  77.52172 104.66736  70.86767  32.71556 118.04124
##  [8] 149.15810  73.49057  37.45200  32.61373  34.33250 109.25542  76.06463
## [15] 129.48622  75.55526  86.72606  60.13439  93.03479  38.12881

Für ganzzahlige Werte können die Rundungsfunktionen round(), floor() und ceiling() eingeschoben werden.

# erzeuge 20 GANZZAHLIGE Zufallswerte zwischen 30 und 150
floor(runif(20, min=30, max=150))
##  [1]  32 147 141 104 143 136 142  82  51 144  56 148 116  90  35 100  30 114  32
## [20] 113

Um Zufallszahlen aus der Standardnormalverteilung zu generieren eignet sich die Funktion rnorm().

# erzeuge 40 zufällige Werte aus der \# Standardnormalverteilung
normal <- rnorm(40)

# ausgeben 
normal
##  [1] -0.887078138 -0.313154326  0.485444076 -1.316261798  0.271073614
##  [6]  1.058629365  1.148521679 -1.822594954 -0.701468973  0.315822015
## [11]  0.003943009 -1.526005408  0.797447057  1.533573510  0.198935030
## [16]  0.066904808  0.837167815 -1.210700971  1.540071696  1.298378718
## [21] -0.255912919  2.114902768 -0.658692314 -0.885611897 -0.439952370
## [26]  1.507837488 -1.393861660 -2.620136037 -0.689817487 -1.126456153
## [31] -0.108243384  0.832197537  1.107178422 -0.965748908  0.005995971
## [36] -0.619321014 -0.319934382  0.760284192  0.376822193  0.255532033

Somit erzeugt rt() zufällige Werte aus der t-Verteilung.

# erzeuge 40 zufällige Werte aus der \# t-Verteilung bei 10 Freiheitsgraden 
t <- rt(40, df=10)

# ausgeben 
t
##  [1]  1.50322755  0.97058871 -0.36462265  1.37514979  1.26949825  0.04358455
##  [7] -0.13666610 -2.16749441 -1.23350137 -0.13105293 -0.30593973 -0.70284114
## [13] -0.45766434 -2.06440205 -0.29643389 -1.11530257  0.91564976  0.29309522
## [19] -1.23045017 -1.99012805  1.58243245  0.56280342  0.49824190  2.13683675
## [25] -0.27519485 -0.52571825 -1.83178646  1.70090970 -1.55730595  1.53713065
## [31]  1.36435306  0.40459694  0.84180821  1.46713320 -0.26426910  1.05703098
## [37] -0.36701706  1.56110574  0.85996582 -0.21745359

4.4 Datentypen

R ist eine obkektorientierte Sprache und kann verschiedene Formen von Datenklassen und -typen verarbeiten. Die für uns wichtigsten Datentypen sind:

  • numerisch (Zahlen, mit denen man rechnen kann)

  • character (Zeichenkette, also Text und Wörter)

  • logisch (Wahr/Falsch, bzw. TRUE und FALSE)

Wir haben im oberen Abschnitt 4.2 schon zwei Datentypen kennengelernt, zum einen den Typ numerisch, denn wir haben den Variablen x, y und z jeweils Zahlenwerte zugeordnet, mit denen wir rechnen konnten.

# numerischer Datetyp 
v_num <- c(0, 8, 15)

# rechnen ist möglich 
v_num * 100
## [1]    0  800 1500

Zum anderen hatten wir der Variable b Wörter zugewiesen. Dies entspricht dem Datentyp “character.”

# Datetyp "Character" 
v_char <- c("Hallo", "ihr", "lieben", "Leute")

# rechnen ist nicht möglich 
v_char * 100
## Fehler in v_char * 100 : nicht-numerisches Argument für binären Operator

Variablen vom Typ logisch enthalten die logischen Aussagen TRUE und FALSE bzw. deren Abkürzungen T und F.

Eine logische Aussage kann zum Beispiel durch einen Vergleich erzeugt werden

# ist 50 = 100 
50==100
## [1] FALSE

Da 50 eben nicht gleich 100 ist, erhalten wir die logische Aussage FALSE zurück.

# ist 50 kleiner als 100 
50<100
## [1] TRUE

Die Zahl 50 ist kleiner als 100, darum erhalten wir die logische Antwort TRUE zurück.

Das kann man auch auf Wertereihen anwenden.

# erzeuge 20 werte 
reihe <- seq(1, 100, 5) 
# ausgeben 
reihe
##  [1]  1  6 11 16 21 26 31 36 41 46 51 56 61 66 71 76 81 86 91 96
# Prüfe jeden Wert in "reihe", ob er kleiner als 75 ist 
reihe<75
##  [1]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
## [13]  TRUE  TRUE  TRUE FALSE FALSE FALSE FALSE FALSE
# Prüfe jeden Wert in "reihe", ob er kleiner als 75 ist 
# und speichere das Ergebnis in Variable "logical" 
logical <- reihe<75

# zeige den 7. und 18. Wert von "logical" an 
logical[c(7,18)]
## [1]  TRUE FALSE

Mit der Funktion class() kann der Datentyp (und auch die Datenklasse, dazu später mehr) angezeigt werden.

# welcher Datentyp ist Variable "logical" 
class(logical)
## [1] "logical"
# welcher Datentyp ist Variable "v_char" 
class(v_char)
## [1] "character"
# welcher Datentyp ist Variable "v_num" 
class(v_num)
## [1] "numeric"

Mit den Funktionen is.numeric(), is.logical() und is.character() können wir den Datentyp ebenfalls überprüfen. Als Antwort erhalten wir ein logisches TRUE oder FALSE.

# ist Variable "v_num" numerisch? 
is.numeric(v_num)
## [1] TRUE
# ist Variable "v_num" logical? 
is.logical(v_num)
## [1] FALSE
# ist Variable "v_num" character? 
is.character(v_num)
## [1] FALSE
# ist Variable "logical" character? 
is.character(logical)
## [1] FALSE
# ist Variable "v_char" numerisch? 
is.numeric(v_char)
## [1] FALSE
# ist Variable "v_char" logical? 
is.logical(v_char)
## [1] FALSE
# ist Variable "v_char" character? 
is.character(v_char)
## [1] TRUE
# ist Variable "logical" logical? 
is.logical(logical)
## [1] TRUE

4.5 Datenklassen

Die Datentypen können wiederum in Datenklassen gespeichert werden. Für uns wichtige Datenklassen sind:

  • Vektoren

  • Matrizen

  • Faktoren (Gruppen, Rangfolge)

  • Datenframes

  • Listen

4.5.1 Vektoren

Vektoren haben wir schon kennengelernt. Ein Vektor ist eine einfache Wertereihe vom selben Datentyp. So erzeugt die Funktion c() einen Datenvektor. Alle Werte der Datenklasse Vektor müssen Werte des selben Wertetyps enthalen. Kombinieren wir numerische, character und logische Werte in einem Vektor, so wandeln sich alle Werte in den kleinsten gemeinsamen Datentyp (nämlich character) um.

# c() fällt auf den "kleinsten gemeinsamen Nenner" zurück 
c(1, 2, 3, 4, "fünf", "sechs", TRUE, TRUE, FALSE)
## [1] "1"     "2"     "3"     "4"     "fünf"  "sechs" "TRUE"  "TRUE"  "FALSE"

Alle Werte sind nun vom Datentyp character, erkennbar an den Anführungszeichen.

Auf die Werte kann man zugreifen, indem man den Variablennamen eingibt:

 # erzeuge einen Vektor 
vektor <- seq(1, 20, 1)

# anzeigen 
vektor
##  [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20

Auf die einzelnen Werte des Vektors kann man Zugreifen, indem man die gewünschte Position in eckigen Klammern an den Variablennamen anhgängt.

# Zeige den ersten Wert von "vektor" 
vektor[1]
## [1] 1

Auch hier können wir Positionsbereiche mit einem : angeben

# Zeige die Werte an Position 4 bis 15 
vektor[4:15]
##  [1]  4  5  6  7  8  9 10 11 12 13 14 15

Mit einem Minuszeichen können auch bestimmte Werte oder Wertbereiche ausgelassen werden.

# Zeige "vektor" OHNE den ersten Wert 
vektor[-1]
##  [1]  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20
# Zeige "vektor" OHNE die Werte 10 bis 14 
vektor[-(10:14)]
##  [1]  1  2  3  4  5  6  7  8  9 15 16 17 18 19 20

Wieviele Werte ein Vektor enthält erfährt man mit der Funktion lenght().

# wieviele Werte hat "vektor"? 
length(vektor)
## [1] 20

Der Vektor vektor beinhaltet 20 Werte.

Mit der Funktion is.vector() kann geprüft werden, ob ein Objekt ein Vektor ist.

# ist "vektor" ein Vektor? 
is.vector(vektor)
## [1] TRUE

4.5.2 Matrizen

Matrizen sind zweidimensionale Strukturen (Tabellen) und werden von R-intern durch Vektoren dargestellt. Dies impliziert, dass alle Werte der Matrix vom selben Datentyp (z.B. numerisch) sein müssen, genau so wie bei Vektoren.

Um besser zu erklären, wie Matrizen funktionieren, erzeugen wir zunächst ein paar Beispielvektoren.

# Erzeuge Testwertereihen 
a <- c(11, 12, 13, 14, 15) 
b <- c(21, 22, 23, 24, 25) 
c <- c(31, 32, 33, 34, 35) 
d <- c(41, 42, 43, 44, 45) 
e <- c(51, 52, 53, 54, 55) 
f <- c("eins", "zwei", "drei", "vier", "fünf")

# Füge alle Zahlen zu einem Vektor zusammen 
alle <- c(a, b, c, d, e)

# anzeigen 
alle
##  [1] 11 12 13 14 15 21 22 23 24 25 31 32 33 34 35 41 42 43 44 45 51 52 53 54 55

Die Funktoin martix() setzt aus einem Vektor eine Matrix zusammen. Lässt man alle Parameter im Funktionsaufruf matrix() leer, wird eine Matrix mit 1 Spalte erzeugt.

# Erzeuge eine Matrix aus Vektor "a" 
matrix(a)
##      [,1]
## [1,]   11
## [2,]   12
## [3,]   13
## [4,]   14
## [5,]   15

Mit dem Parameter ncol kann die gewünschte Anzahl an Spalten übergeben werden:

# Erzeuge eine Matrix aus Vektoren "a" und "b" 
# mit 2 Spalten
matrix(c(a,b), ncol=2)
##      [,1] [,2]
## [1,]   11   21
## [2,]   12   22
## [3,]   13   23
## [4,]   14   24
## [5,]   15   25

Mit dem Parameter nrow kann die gewünschte Anzahl an Zeilen übergeben werden:

# Erzeuge eine Matrix aus Vektoren "a" und "b" 
# mit 2 Zeilen
matrix(c(a,b), nrow=2)
##      [,1] [,2] [,3] [,4] [,5]
## [1,]   11   13   15   22   24
## [2,]   12   14   21   23   25

Achten Sie auf die Reihenfolge, in der die Werte in der Matrix angelegt wurden. Das ist wahrscheinlich nicht das Ergebnis, das Sie erwartet haben. Die Funktion matrix() arbeitet standardmäßig die Werte pro Spalte (spaltenorientiert) ab. Wir können das mit dem Parameter byrow ändern:

# Erzeuge eine Matrix aus Vektoren "a" und "b" 
# mit 2 Zeilen, diesmal zeilenorientiert 
matrix(c(a,b), nrow=2, byrow=TRUE)
##      [,1] [,2] [,3] [,4] [,5]
## [1,]   11   12   13   14   15
## [2,]   21   22   23   24   25

Sobald eine Matrix mit 2 oder mehr Spalten angelegt werden soll, muss der Datenvektor so viele Werte enthalten, dass die gewünschte Matrix vollständig erstellt werden kann. Sollten zu wenige Werte vorhanden sein, gibt R eine Warnmeldung aus. Für eine Matrix mit 2 Spalten muss also eine gerade Anzahl an Werten vorhanden sein.

# Matrix mit 2 Spalten benötigt gerade Anzahl an Werten 
# daher gibt R (mit nur 9 Werten) eine Warnmeldung aus 
matrix(1:9, nrow=2)
## Warning in matrix(1:9, nrow = 2): Datenlänge [9] ist kein Teiler oder Vielfaches
## der Anzahl der Zeilen [2]
##      [,1] [,2] [,3] [,4] [,5]
## [1,]    1    3    5    7    9
## [2,]    2    4    6    8    1

Wie Sie sehen versucht R selbstständig die Matrix zu vervollständigen. Hierfür wiederholt R die angegebenen Werte so lange, bis die Matrix “voll” ist. Im obigen Beispiel wurde nach der 9 wieder eine 1 eingetragen.

Wie bereits erwähnt müssen die Werte vom selben Datentyp sein. Mischt man numeric mit character, fällt auch Matrix auf den kleinsten gemeinsamen Datentyp (character) zurück.

# Erzeuge eine Matrix aus Vektoren "a" und "f" 
# fällt auch Typ "char" zurück 
matrix(c(a,f), nrow=2, byrow=TRUE)
##      [,1]   [,2]   [,3]   [,4]   [,5]  
## [1,] "11"   "12"   "13"   "14"   "15"  
## [2,] "eins" "zwei" "drei" "vier" "fünf"

Neben matrix() können auch die Befehle rbind() (für rowbind) und cbind() (für columnbind) verwendet werden, um eine Matrix zu erzeugen.

Der Befehl cbind() fügt die übergebenen Vektoren spaltenorientiert zu einer Matrix zusammen.

# Erzeuge eine Matrix aus Vektoren "c" und "d" 
# spaltenorientiert 
cbind(c, d)
##       c  d
## [1,] 31 41
## [2,] 32 42
## [3,] 33 43
## [4,] 34 44
## [5,] 35 45

Der Befehl rbind() fügt die übergebenen Vektoren zeilenorientiert zu einer Matrix zusammen.

# Erzeuge eine Matrix aus Vektoren "c" und "d" 
# zeilenorientiert 
rbind(c, d)
##   [,1] [,2] [,3] [,4] [,5]
## c   31   32   33   34   35
## d   41   42   43   44   45

Wir speichern eine Matrix in einer Variable:

# Erzeuge eine Matrix aus Vektor "alle" 
# mit 5 Spalten 
mymatrix <- matrix(alle, ncol=5)

# ausgeben 
mymatrix
##      [,1] [,2] [,3] [,4] [,5]
## [1,]   11   21   31   41   51
## [2,]   12   22   32   42   52
## [3,]   13   23   33   43   53
## [4,]   14   24   34   44   54
## [5,]   15   25   35   45   55

An der Ausgabe der Spalten- und Zeilentitel lässt sich erahnen, wie die einzelnen Werte einer Matrix refenziert werden können. Bei Vektoren können die einzelnen Werte abgerufen werden, indem in eckigen Klammern die gewünschte Position angegeben wird. Dies funktioniert bei Matrizen ähnlich, jedoch muss innerhalb der eckigen Klammer zwischen Zeilen und Spalten unterschieden werden. Dies geschieht mit einem Komma, wobei vor dem Komma die Zeilen, und nach dem Komma die Spalten referenziert werden.

# zeige die 1. Zeile der Matrix 
# die Zahl vor dem Komma repräsentiert die Zeilen 
mymatrix[1,]
## [1] 11 21 31 41 51
# zeige die 1. Spalte der Matrix 
# die Zahl nach dem Komma repräsentiert die Spalten 
mymatrix[,1]
## [1] 11 12 13 14 15

Wie in einem Koordinatensystem können nun gezielt einzelne Werte oder Wertbereiche referenziert werden.

# zeige den Wert in Zeile 3 und Spalte 2 
mymatrix[3,2]
## [1] 23
# zeige die Werte aus Zeile 2 bis 4 
# und Spalte 1 bis 3
mymatrix[2:4,1:3]
##      [,1] [,2] [,3]
## [1,]   12   22   32
## [2,]   13   23   33
## [3,]   14   24   34

Mit der Funktion t() kann die Matrix transponiert werden, das beduetet, es werden Zeilen und Spalten diagonal gespiegelt.

# zeige meine Matrix 
mymatrix
##      [,1] [,2] [,3] [,4] [,5]
## [1,]   11   21   31   41   51
## [2,]   12   22   32   42   52
## [3,]   13   23   33   43   53
## [4,]   14   24   34   44   54
## [5,]   15   25   35   45   55
# transponiere meine Matrix 
t(mymatrix)
##      [,1] [,2] [,3] [,4] [,5]
## [1,]   11   12   13   14   15
## [2,]   21   22   23   24   25
## [3,]   31   32   33   34   35
## [4,]   41   42   43   44   45
## [5,]   51   52   53   54   55

Mit den Funktionen colnames() und rownames() können Spalten und Zeilen noch betitelt werden.

Wir benennen unsere Spalten von “a” bis “e”:

# benenne Spalten der Matrix 
colnames(mymatrix) <- c("a", "b", "c", "d", "e")

# anzeigen 
mymatrix
##       a  b  c  d  e
## [1,] 11 21 31 41 51
## [2,] 12 22 32 42 52
## [3,] 13 23 33 43 53
## [4,] 14 24 34 44 54
## [5,] 15 25 35 45 55

Wir benennen unsere Zeilen von römisch I bis V:

# benenne Spalten der Matrix 
rownames(mymatrix) <- c("I", "II", "III", "IV", "V")

# anzeigen 
mymatrix
##      a  b  c  d  e
## I   11 21 31 41 51
## II  12 22 32 42 52
## III 13 23 33 43 53
## IV  14 24 34 44 54
## V   15 25 35 45 55

Mit der Funktion class() kann die Datenklasse angezeigt werden.

# welcher Datentyp ist Variable "mymatrix" 
class(mymatrix)
## [1] "matrix" "array"

Mit der Funktion is.matrix() kann zudem geprüft werden, ob ein Objekt eine Matrix ist.

# ist "mymatrix" eine Matrix? 
is.matrix(mymatrix)
## [1] TRUE
# ist "vector" eine Matrix? 
is.matrix(vector)
## [1] FALSE

Als Übung können wir nun beispielsweise die Anzahl der Beschäftigten in Pflegeberufen aus dem “Pflegethermometer 2018”2 (siehe Abbildung 4.5), als Matrix in R übertragen.

Abbildung 4.5: Anzahl Beschäftigter in Pflegeberufen (Isfort et al. 2018)

# Schreibe die Zahlen reihenweise aus der Grafik ab 
Pflegeberufe <- c(16624, 19061, 19478, 21537, 27731, 36481, 46517, 54371, 64127, 
                  55770,52710, 49727, 45776, 48326, 47903, 47978, 48363, 49507, 
                  47779, 48203, 48822, 48519, 49080, 49307, 48291, 48937, 48913, 
                  430983, 436767, 444783, 449355, 457322, 465446, 468192, 472580, 476416, 
                  109161, 124879, 141965, 158817, 178902, 194195, 208304, 227154, 246412 ) 
# überführe in Matrix mit 9 Spalten 
# Die Werte kommen reihenweise 
Pflegeberufe <- matrix(Pflegeberufe, byrow=T,ncol=9)

# benenne die Spalten 
colnames(Pflegeberufe) <- c(1999, 2001, 2003, 2005, 2007, 2009, 2011, 2013, 2015)

# benenne die Reihen 
rownames(Pflegeberufe) <- c("Krankenpflegeassistenz", "Altenpflegehilfe", "Kinderkrankenpflege", "Krankenpflege", "Altenpflege")

# zeige Tabelle 
Pflegeberufe
##                          1999   2001   2003   2005   2007   2009   2011   2013
## Krankenpflegeassistenz  16624  19061  19478  21537  27731  36481  46517  54371
## Altenpflegehilfe        55770  52710  49727  45776  48326  47903  47978  48363
## Kinderkrankenpflege     47779  48203  48822  48519  49080  49307  48291  48937
## Krankenpflege          430983 436767 444783 449355 457322 465446 468192 472580
## Altenpflege            109161 124879 141965 158817 178902 194195 208304 227154
##                          2015
## Krankenpflegeassistenz  64127
## Altenpflegehilfe        49507
## Kinderkrankenpflege     48913
## Krankenpflege          476416
## Altenpflege            246412

Wir werden auf diese Matrix später noch zurückkommen.

4.5.3 Faktoren

Die Datenklasse factor beschreibt gruppierte (nominale) oder ranggeordnete (ordinale) Werte. Gruppierte Werte sind beispielsweise “Beruf,” “Konfession,” “Familienstand” oder “Geschlecht.” Es liegt keine Reihenfolge unter den Gruppen vor. Sie werden mit der Funktion factor() erstellt.

# nominalen Faktoren erstellen 
v_fac1 <- factor(c("maennlich", "weiblich", "divers"))
# ausgeben 
v_fac1
## [1] maennlich weiblich  divers   
## Levels: divers maennlich weiblich

Unsere Variable v_fac1 besteht aus 3 Gruppen, nämlich divers, maennlich und weiblich mit je einem Wert. Erzeugen wir die Daten erneut, diesmal mit mehr Werten und einer abgekürzten Schreibweise für das Geschlecht.

# Faktoren neu erstellen, mit mehr Werten 
v_fac1 <- factor(c("m", "w", "d","m", "w", "d","m", "w", "d","m", "w", "d"))

# ausgeben 
v_fac1
##  [1] m w d m w d m w d m w d
## Levels: d m w

In der ersten Zeile sehen wir unsere Datenreihe, in der zweiten Zeile alle Gruppen (Levels), in diesem Falle d, m und w.

Für ordninale (also ranggeordnete) Werte nehmen wir ebenfalls die factor()-Funktion. Versuchen wir also, klassiche Schulnoten abzubilden. Wir stellen uns eine virtuelle Liste mit Schulnoten von 100 SchülerInnen vor. Wir übertragen die Noten von der virtuellen Liste in R, und zwar in der Reihenfolge, wie sie auf unserer virtuellen Notenliste stehen könnten (sprich: unsortiert).

# Faktoren aus Notenliste erstellen 
v_fac2 <- factor(c("gut", "ausreichend", "sehr gut", "ausreichend", "befriedigend", "magelhaft", "ungenügend", "gut", "gut", "sehr gut"))

# ausgeben 
v_fac2
##  [1] gut          ausreichend  sehr gut     ausreichend  befriedigend
##  [6] magelhaft    ungenügend   gut          gut          sehr gut    
## Levels: ausreichend befriedigend gut magelhaft sehr gut ungenügend

In der ersten Zeile sehen wir unsere Datenreihe, in der letzten Zeile alle Ränge (Levels). Ein Blick auf die Levels zeigt aber auch, dass diese in einer falschen Reihehnfolge angelegt wurden. Der erste Rang ist hier ausreichend, und der zweite befriedigend (es sollte ja eigentlich so sein, dass sehr gut der erste Rang ist, und gut der zweite, usw). Das liegt daran, dass wir die Noten unsortiert aneinandergereiht haben. R erstellt die Reihenfolge der Levels anhand der Reihenfolge, in der sie eintreffen.

Dies ist ein häufiger Anfängerfehler bei der Erstellung von Faktoren!

Um unsere Schulnoten in der richtigen Levelreihenfolge anzulegen, müssen wir dem Befehl factor() eben diese Reihenfolge über die Option levels mitgeben (mehr Informationen erhalten Sie über die Hilfeseite ?factor). Konkret übergeben wir per levels=c() die Levelnamen von sehr gut bis ungenügend.

# Faktoren aus Notenliste erstellen # diesmal Levelreihenfolge mit "levels=" vorgeben 
v_fac2 <- factor(c("gut", "ausreichend", "sehr gut", "ausreichend", "befriedigend", "mangelhaft", "ungenügend", "gut", "gut", "sehr gut"), 
                 levels=c("sehr gut", "gut", "befriedigend", "ausreichend","mangelhaft", "ungenügend"))

# ausgeben 
v_fac2
##  [1] gut          ausreichend  sehr gut     ausreichend  befriedigend
##  [6] mangelhaft   ungenügend   gut          gut          sehr gut    
## Levels: sehr gut gut befriedigend ausreichend mangelhaft ungenügend

Die Levels sind nun in der korrekten Reihenfolge.

Wir hätten die Daten aber gar nicht neu eingeben müssen. Der Befehl lässt sich verkürzen, indem man einfach die bestehende Variable als Input nutzt und neu überschreibt:

# Levelreihenfolge in "v_fac2" reparieren und überschreiben 
v_fac2 <- factor(v_fac2, levels=c("sehr gut", "gut", "befriedigend", "ausreichend","mangelhaft", "ungenügend"))

# ausgeben 
v_fac2
##  [1] gut          ausreichend  sehr gut     ausreichend  befriedigend
##  [6] mangelhaft   ungenügend   gut          gut          sehr gut    
## Levels: sehr gut gut befriedigend ausreichend mangelhaft ungenügend

So kann man auch nachträglich die Levelreihenfolge korrigieren.

Mit dem Befehl revalue() aus dem plyr-Zusatzpaket[^1] lassen sich die Werte und Levels von Faktoren umändern. Wir ändern unsere Schulnoten von den ausgeschriebenen Noten hin zu Zahlenwerten. Hierfür erzeugen wir eine neue Variable v_fac3.

# Lade Zusatzpaket "plyr" 
library(plyr)
# Ändere Levelnamen 
v_fac3 <- revalue(v_fac2, c("sehr gut"="1", "gut"="2","befriedigend"="3","ausreichend"="4","mangelhaft"="5","ungenügend"="6"))

# Werte ausgeben 
v_fac3
##  [1] 2 4 1 4 3 5 6 2 2 1
## Levels: 1 2 3 4 5 6

Beachten Sie, dass die “Zahlen”werte nur nominaler Natur sind. Wir können mit ihnen nicht rechnen!

# rechnen ist mit factor nicht möglich! 
v_fac3 * 100
## Warning in Ops.factor(v_fac3, 100): '*' not meaningful for factors
##  [1] NA NA NA NA NA NA NA NA NA NA

Die Werte innerhalb einer Faktorenreihe refenziert man so wie bei Vektoren, indem man die gewünschte Position in eckigen Klammern an den Variablennamen anhgängt.

# zeige die Werte von 3 bis 7 von "v_fac3" 
v_fac3[3:7]
## [1] 1 4 3 5 6
## Levels: 1 2 3 4 5 6

Welche Levels in einem Faktor existieren erfährt man mit der Funktion levels().

# welche Levels hat "v_fac3"? 
levels(v_fac3)
## [1] "1" "2" "3" "4" "5" "6"

Durch Kombimation mit der Funktion length() können wir die Anzahl der Levels erfahren.

# wieviele Levels hat "v_fac3"? 
length(levels(v_fac3))
## [1] 6

Die Variable hat 6 Levels.

Welche Level welche Häufigkeit hat erfahren wir mit der Funktion table().

# welche Level hat welche Häufigkeit?
table(v_fac2)
## v_fac2
##     sehr gut          gut befriedigend  ausreichend   mangelhaft   ungenügend 
##            2            3            1            2            1            1

Mit der Funktion class() kann die Datenklasse angezeigt werden.

# welcher Datentyp ist Variable "v_fac2" 
class(v_fac2)
## [1] "factor"

Mit der Funktion is.factor() kann zudem geprüft werden, ob ein Objekt ein Faktor ist.

# ist "v_fac2" ein Faktor? 
is.factor(v_fac2)
## [1] TRUE
# ist "mymatrix" ein Faktor? 
is.factor(mymatrix)
## [1] FALSE

4.5.4 Datenframes

Die Datenklasse Datenframe (Datensatz) ist wohl die wichtigste in . Datenframes sind ebenso wir Matrizen zweidimensional. Im Unterschied zu einer Matrix können in einem Datenframe unterschiedliche Datentypen, also z.B. numeric, character und factor, zusammengeführt werden. Das Datenframe folgt dabei der Logik “ein Fall pro Zeile” (so genanntes tidy data Format, siehe Kapitel 6). Das bedeutet, dass jeder Beobachtung (auch Wiederholungen) in einer eigenen Zeile steht und die jeweiligen Variablen durch die Spalten repräsentiert werden.

Erzeugen wir uns ein paar Beispielvektoren unterschiedlichen Typs mit je 12 Werten.

# erzeuge Testvektoren "factor", "char", "numeric", "logical"
geschlecht <- factor(rep(c("m", "w", "d"), 4)) 
spitzname <- c("Hasi", "Ide", "Momsi", "Ryu", "Dave", "Zoid", "Adu", "Efi", "Ole", "Ray", "Sam", "Emi") 
hausnummer <- 1:12
angemeldet <- c(TRUE, TRUE, FALSE, T, F, F, F, T, T, T, F, T)

Aus den Variablen setzen wir nun mit der Funktion data.frame() ein Datenframe zusammen.

# erzeuge ein Datenframe aus den Testvektoren 
data.frame(geschlecht, spitzname, hausnummer, angemeldet)
##    geschlecht spitzname hausnummer angemeldet
## 1           m      Hasi          1       TRUE
## 2           w       Ide          2       TRUE
## 3           d     Momsi          3      FALSE
## 4           m       Ryu          4       TRUE
## 5           w      Dave          5      FALSE
## 6           d      Zoid          6      FALSE
## 7           m       Adu          7      FALSE
## 8           w       Efi          8       TRUE
## 9           d       Ole          9       TRUE
## 10          m       Ray         10       TRUE
## 11          w       Sam         11      FALSE
## 12          d       Emi         12       TRUE

Das Datenframe speichern wir in die Variable MeinDatenframe.

# speicher Datenframe in Variable 
MeinDatenframe <- data.frame(geschlecht, spitzname, hausnummer, angemeldet)

# zeige Datenklasse an 
class(MeinDatenframe)
## [1] "data.frame"

Die Funktion class() weist unsere Variable als Datenframe aus.

Ähnlich wie bei Matrizen müssen die Vektoren jeweils die selbe Anzahl an Werten (die selbe Länge) besitzen, damit das Datenframe vollständig aufgebaut werden kann. Entfernen wir z.B. einen Wert aus der Reihe hausnummer, schlägt der Befehl fehl.

# Datenframe, "hausnummer" ist einen Wert kürzer
data.frame(geschlecht, spitzname, hausnummer[-1], angemeldet)
Fehler in data.frame(geschlecht, spitzname, hausnummer[-1], angemeldet) : 
  Argumente implizieren unterschiedliche Anzahl Zeilen: 12, 11


Wenn zwei Datenframes mit den selben Spaltennamen exisiteren, können diese per rbind() zusammengefasst werden. In unserem Beispiel verdoppeln wir einfach unser Datenframe.

# füge 2 Datenframes mittels rbind() zusammen 
rbind(MeinDatenframe, MeinDatenframe)
##    geschlecht spitzname hausnummer angemeldet
## 1           m      Hasi          1       TRUE
## 2           w       Ide          2       TRUE
## 3           d     Momsi          3      FALSE
## 4           m       Ryu          4       TRUE
## 5           w      Dave          5      FALSE
## 6           d      Zoid          6      FALSE
## 7           m       Adu          7      FALSE
## 8           w       Efi          8       TRUE
## 9           d       Ole          9       TRUE
## 10          m       Ray         10       TRUE
## 11          w       Sam         11      FALSE
## 12          d       Emi         12       TRUE
## 13          m      Hasi          1       TRUE
## 14          w       Ide          2       TRUE
## 15          d     Momsi          3      FALSE
## 16          m       Ryu          4       TRUE
## 17          w      Dave          5      FALSE
## 18          d      Zoid          6      FALSE
## 19          m       Adu          7      FALSE
## 20          w       Efi          8       TRUE
## 21          d       Ole          9       TRUE
## 22          m       Ray         10       TRUE
## 23          w       Sam         11      FALSE
## 24          d       Emi         12       TRUE

Es funktioniert nicht, wenn eine neue Zeile mit einem Datenvektor übergeben wird, denn in einem Vektor können nur Werte des selben Datentyps vorkommen.

# füge einzelne Zeile mit rbind() hinzu 
rbind(MeinDatenframe, c("m", "Joe", 99, TRUE))
##    geschlecht spitzname hausnummer angemeldet
## 1           m      Hasi          1       TRUE
## 2           w       Ide          2       TRUE
## 3           d     Momsi          3      FALSE
## 4           m       Ryu          4       TRUE
## 5           w      Dave          5      FALSE
## 6           d      Zoid          6      FALSE
## 7           m       Adu          7      FALSE
## 8           w       Efi          8       TRUE
## 9           d       Ole          9       TRUE
## 10          m       Ray         10       TRUE
## 11          w       Sam         11      FALSE
## 12          d       Emi         12       TRUE
## 13          m       Joe         99       TRUE

Zwar sieht es so aus, als sei die neue Zeile korrekt eingetragen worden, wenn wir jedoch das neue Datenframe in einer Variable abspeichern und die Datenklassen überprüfen, stellen wir fest, was falsch gelaufen ist.

# füge einzelne Zeile mit rbind() hinzu 
new <- rbind(MeinDatenframe, c("m", "Joe", 99, TRUE))

# überprüfe Datentyp für Spalte "hausnummer" 
class(new$hausnummer)
## [1] "character"

Der Datentyp in Spalte hausnummer ist auf den “kleinsten gemeinsamen Nenner” (character) zurückgefallen. Das liegt daran, dass zunächst der Vektor in c() auf character zurückfällt. Somit sind alle Werte in der c()-Funktion vom Typ texttt{character}. Bei hausnummer zieht nun dieser neue Wert die gesamte Spalte auf den Typ character zurück. Ebenso verhält es sich bei Variable angemeldet, die eigentlich mal vom Typ logical war.

# überprüfe Datentyp für Spalte "geschlecht"
class(new$angemeldet)
## [1] "character"

Wenn wir mit der Spalte hausnummer rechnen wollen, schlägt dies fehl.

# multipliziere Spalte "hausnummer" mit 2 
new$hausnummer * 2
Fehler in new$hausnummer * 2 : nicht-numerisches Argument für binären Operator


Ein falscher rbind()-Befehl kann Ihnen also das gesamte Datenframe “zerschießen.” Dies ist ein häufiger Anfängerfehler, seien Sie sorgsam, wenn Sie einem Datenframe neue Zeilen hinzufügen!

Um also eine neue Zeile korrekt dem Datenframe hinzuzufügen, muss diese neue Zeile ebenfalls als Datenframe in der selben Struktur (also mit den selben Variablen (Spalten) vorliegen. Die

# neue Zeile 
neuezeile <- data.frame( factor("m"), "Joe", 99, TRUE)

# übergebe die Spaltennamen an die neue Zeile 
colnames(neuezeile) <- colnames(MeinDatenframe)

# füge zu Datenframe hinzu 
new <- rbind(MeinDatenframe, neuezeile)

# anzeigen 
new
##    geschlecht spitzname hausnummer angemeldet
## 1           m      Hasi          1       TRUE
## 2           w       Ide          2       TRUE
## 3           d     Momsi          3      FALSE
## 4           m       Ryu          4       TRUE
## 5           w      Dave          5      FALSE
## 6           d      Zoid          6      FALSE
## 7           m       Adu          7      FALSE
## 8           w       Efi          8       TRUE
## 9           d       Ole          9       TRUE
## 10          m       Ray         10       TRUE
## 11          w       Sam         11      FALSE
## 12          d       Emi         12       TRUE
## 13          m       Joe         99       TRUE

Mit dem Befehl cbind() können dem Datenframe neue Spalten hinzugefügt werden. Hierbei ist wichtig, dass die neue Spalte die selbe Anzahl an Werten aufweist wie die anderen Spalten des Datenframes. Wir erzeugen eine neue Variable und fügen diese als neue Spalte dem Datenframe hinzu.

# neue Variable mit 12 Werten 
kinder <- c(1, 4, 3, 1, 2, 3, 2, 1, 4, 2, 3, 4)

# neues Datenframe mit dieser Spalte 
new <- cbind(MeinDatenframe, kinder)

# anzeigen 
new
##    geschlecht spitzname hausnummer angemeldet kinder
## 1           m      Hasi          1       TRUE      1
## 2           w       Ide          2       TRUE      4
## 3           d     Momsi          3      FALSE      3
## 4           m       Ryu          4       TRUE      1
## 5           w      Dave          5      FALSE      2
## 6           d      Zoid          6      FALSE      3
## 7           m       Adu          7      FALSE      2
## 8           w       Efi          8       TRUE      1
## 9           d       Ole          9       TRUE      4
## 10          m       Ray         10       TRUE      2
## 11          w       Sam         11      FALSE      3
## 12          d       Emi         12       TRUE      4

Wir könnten aber auch einfach schreiben:

MeinDatenframe$kinder <- kinder

Ebenso wie bei der Matrix lassen sich die einzelnen Spalten und Zeilen referenzieren, indem wir in eckigen Klammern die gewünschte Position angeben.

# Zeige nur die erste Spalte 
MeinDatenframe[,1]
##  [1] m w d m w d m w d m w d
## Levels: d m w

Die einzelnen Spalten des Datenframes lassen sich auch über ihren Namen referenzieren. Hierfür schreiben wir ein Dollarzeichen $ und hängen den Spaltennamen daran.

# Zeige nur Spalte "geschlecht" 
MeinDatenframe$geschlecht
##  [1] m w d m w d m w d m w d
## Levels: d m w
# Zeige nur Spalte "angemeldet"
MeinDatenframe$angemeldet
##  [1]  TRUE  TRUE FALSE  TRUE FALSE FALSE FALSE  TRUE  TRUE  TRUE FALSE  TRUE

So können wir auch die jeweiligen Datentypen der Spaltenwerte überprüfen.

# welcher Datentyp liegt in Spalte "angemeldet" vor?
class(MeinDatenframe$angemeldet)
## [1] "logical"
# welcher Datentyp liegt in Spalte "spitzname" vor?
class(MeinDatenframe$spitzname)
## [1] "character"
# welcher Datentyp liegt in der 1. Spalte vor?
class(MeinDatenframe[, 1])
## [1] "factor"

Möchten wir uns die Fälle (also die Zeilen) ausgeben lassen, erfolgt dies mit

# Zeige Fall Nummer 4 
MeinDatenframe[4,]
##   geschlecht spitzname hausnummer angemeldet
## 4          m       Ryu          4       TRUE

oder für Fallserien per

# Zeige Fälle Nummer 2 bis 5 
MeinDatenframe[2:5,]
##   geschlecht spitzname hausnummer angemeldet
## 2          w       Ide          2       TRUE
## 3          d     Momsi          3      FALSE
## 4          m       Ryu          4       TRUE
## 5          w      Dave          5      FALSE

Wir können auch bedingte Ausgaben erzeugen.

# Zeige nur die Fälle mit "hausnummer" kleiner als 5
MeinDatenframe[MeinDatenframe$hausnummer<5, ]
##   geschlecht spitzname hausnummer angemeldet
## 1          m      Hasi          1       TRUE
## 2          w       Ide          2       TRUE
## 3          d     Momsi          3      FALSE
## 4          m       Ryu          4       TRUE
# Zeige nur die Fälle mit "angemeldet" = TRUE
MeinDatenframe[MeinDatenframe$angemeldet==T, ]
##    geschlecht spitzname hausnummer angemeldet
## 1           m      Hasi          1       TRUE
## 2           w       Ide          2       TRUE
## 4           m       Ryu          4       TRUE
## 8           w       Efi          8       TRUE
## 9           d       Ole          9       TRUE
## 10          m       Ray         10       TRUE
## 12          d       Emi         12       TRUE

Dies kann auch verknüpft werden:

# Zeige nur die Fälle mit "angemeldet" = TRUE # und "hausnummer" größer 6
MeinDatenframe[(MeinDatenframe$angemeldet==T) & (MeinDatenframe$hausnummer>6),]
##    geschlecht spitzname hausnummer angemeldet
## 8           w       Efi          8       TRUE
## 9           d       Ole          9       TRUE
## 10          m       Ray         10       TRUE
## 12          d       Emi         12       TRUE

Beachten Sie, dass wir jedes Mal, wenn wir auf eine Spalte des Datenframes referenzieren möchten, den Datenframe-Namen mit einem Dollarzeichen $ schreiben müssen. Tun wir das nicht, sucht R nach einer Variable im Workspace, und nutzt dann deren Werte. Dies ist ein häufiger Anfängerfehler!

Die ständige Angabe des Datenframes macht die Befehle recht lang.

Mit der Funktion with() können wir uns die Referenzierung mit $ sparen. Wir übergeben der Funktion with() unser Datenframe, und sagen dann, was damit getan werden soll.

# mit Funktion with() wird es leichter 
with(MeinDatenframe, MeinDatenframe[hausnummer>4 & angemeldet==F, ])
##    geschlecht spitzname hausnummer angemeldet
## 5           w      Dave          5      FALSE
## 6           d      Zoid          6      FALSE
## 7           m       Adu          7      FALSE
## 11          w       Sam         11      FALSE
# mit Funktion with() wird es leichter 
with(MeinDatenframe, spitzname[hausnummer>4 & angemeldet==F])
## [1] "Dave" "Zoid" "Adu"  "Sam"

Das funktioniert in Kombination mit jeder anderen Funktion.

# Summe der Hausnummern 
with(MeinDatenframe, sum(hausnummer))
## [1] 78
# Häufigkeit von geschlecht 
with(MeinDatenframe, table(geschlecht))
## geschlecht
## d m w 
## 4 4 4

Ähnlich wie bei Matrizen können wir die Zeilen- und Spaltentitel anpassen. Mit colnames() können wir die Spalten umbenennen.

# benenne Spalten des Datenframes 
colnames(MeinDatenframe) <- c("Sex", "Nickname", "House", "confirmed")

# anzeigen 
MeinDatenframe
##    Sex Nickname House confirmed
## 1    m     Hasi     1      TRUE
## 2    w      Ide     2      TRUE
## 3    d    Momsi     3     FALSE
## 4    m      Ryu     4      TRUE
## 5    w     Dave     5     FALSE
## 6    d     Zoid     6     FALSE
## 7    m      Adu     7     FALSE
## 8    w      Efi     8      TRUE
## 9    d      Ole     9      TRUE
## 10   m      Ray    10      TRUE
## 11   w      Sam    11     FALSE
## 12   d      Emi    12      TRUE

Dementsprechend können mit rownames() die Zeilen umbenannt werden.

# benenne Spalten des Datenframes 
rownames(MeinDatenframe) <- c("Eins", "Zwei", "Drei", "Vier", "Fünf", "Sechs", "Sieben", "Acht", "Neun", "Zehn", "Elf", "Zwölf")

# anzeigen 
MeinDatenframe
##        Sex Nickname House confirmed
## Eins     m     Hasi     1      TRUE
## Zwei     w      Ide     2      TRUE
## Drei     d    Momsi     3     FALSE
## Vier     m      Ryu     4      TRUE
## Fünf     w     Dave     5     FALSE
## Sechs    d     Zoid     6     FALSE
## Sieben   m      Adu     7     FALSE
## Acht     w      Efi     8      TRUE
## Neun     d      Ole     9      TRUE
## Zehn     m      Ray    10      TRUE
## Elf      w      Sam    11     FALSE
## Zwölf    d      Emi    12      TRUE

Das sollte bei einem Datenframe nach dem Tidy Data Prinzip (siehe Kapitel 6)) aber niemals notwendig sein.

Mit der Funktion class() kann die Datenklasse angezeigt werden.

# welcher Datentyp ist "MeinDatenframe" 
class(MeinDatenframe)
## [1] "data.frame"

Mit der Funktion is.data.frame() kann zudem geprüft werden, ob ein Objekt ein Faktor ist.

# ist "MeinDatenframe" ein Datenframe?
is.data.frame(MeinDatenframe)
## [1] TRUE
# ist "mymatrix" ein Datenframe? 
is.data.frame(mymatrix)
## [1] FALSE

In RStudio werden die Variablen und Datensätze im Datenfenster oben rechts angezeigt (Abbildung 4.6).

Abbildung 4.6: Datenfenster rechts oben

Wenn Sie hier auf einen Datensatz klicken, z.B. auf MeinDatenframe, so werden Ihnen die Inhalte (also die Werte) des Datensatzes im Scriptfenster angezeigt (Abbildung 4.7).

Abbildung 4.7: Datensatz ansehen

Wir können mit der Funktion as.data.frame() Objekte in ein Datenframe umwandeln. Schauen wir uns erneut die auf Seite erzeugte Matrix der Beschäftigten in den Pflegeberufen an.

# zeige Matrix 
Pflegeberufe
##                          1999   2001   2003   2005   2007   2009   2011   2013
## Krankenpflegeassistenz  16624  19061  19478  21537  27731  36481  46517  54371
## Altenpflegehilfe        55770  52710  49727  45776  48326  47903  47978  48363
## Kinderkrankenpflege     47779  48203  48822  48519  49080  49307  48291  48937
## Krankenpflege          430983 436767 444783 449355 457322 465446 468192 472580
## Altenpflege            109161 124879 141965 158817 178902 194195 208304 227154
##                          2015
## Krankenpflegeassistenz  64127
## Altenpflegehilfe        49507
## Kinderkrankenpflege     48913
## Krankenpflege          476416
## Altenpflege            246412

Mit der Funktion as.data.frame() wandeln wir die Matrix in ein Datenframe um.

# wandle Matrix in Datenframe um 
Pflegeframe <- as.data.frame(Pflegeberufe)

# anzeigen 
Pflegeframe
##                          1999   2001   2003   2005   2007   2009   2011   2013
## Krankenpflegeassistenz  16624  19061  19478  21537  27731  36481  46517  54371
## Altenpflegehilfe        55770  52710  49727  45776  48326  47903  47978  48363
## Kinderkrankenpflege     47779  48203  48822  48519  49080  49307  48291  48937
## Krankenpflege          430983 436767 444783 449355 457322 465446 468192 472580
## Altenpflege            109161 124879 141965 158817 178902 194195 208304 227154
##                          2015
## Krankenpflegeassistenz  64127
## Altenpflegehilfe        49507
## Kinderkrankenpflege     48913
## Krankenpflege          476416
## Altenpflege            246412

Kommen wir noch einmal auf das Konzept Tidy Data zurück (siehe Kapitel 6). Ein Datenframe sollte möglichst so aufgebaut sein, dass jeweils ein Fall pro Zeile abgebildet wird. Das ist bei unserem Datenframe Pflegeframe aber nicht der Fall.

Ein Datenframe würde sich aus der Matrix jede Beschäftigtenzahl einzeln vornehmen, um dann zu fragen “aus welchem Jahr stammt diese Zahl?” und “aus welcher Berufsgruppe stammt diese Zahl?” Das heisst, es würde hinterher dieser Struktur folgen:

    Jahr    Berufsgruppe     Wert
1   1999    Krankenpflege    430983
2   2001    Krankenpflege    436767
3   2001    Altenpflege      124879
4   2003    Altenpflegehilfe 49727
            ( . . . )

Man spricht in diesem Zusammenhang von long table und wide table. Die Matrix der Pflegeberufe stellt dabei die wide table, die breite Tabelle dar. “Breit” bedeutet, dass die Tabelle, wenn wir ihr nun 10 weitere Jahrgänge hinzufügen würden, immer breiter und breiter werden würde.

Unser angestrebtes Tidy-Data-Datenframe ist vom Typ long table, da die Tabelle, wenn wir ihr Daten hinzufügen würden, immer länger und länger werden würde.

Wie formen wir unsere Matrix in ein Tidy Data-Datenframe, also in eine long table, um?

Mit der Funktion expand.grid() kann ein Datenframe mit Wertepaaren erzeugt werden. Für unser Beispiel mit den Pflegeberufen brauchen wir im Datenframe je eine Zeile für alle möglichen Kombinationen aus Jahr und Berufsgruppe. Die Funktion expand.grid() erzeugt genau solche Paarungen. Idealerweise sind die benötigten Werte (alle Jahre und alle Berufsgruppen) als Zeilen- und Spaltennamen in der Matrix Pflegeberufe vorhanden.

# erzeuge ein Tidy-Data-Dataframe 
# mit allen möglichen Kombinationen 
# aus Jahren und Berufsgruppen 
new <- expand.grid( colnames(Pflegeberufe), rownames(Pflegeberufe))

# anzeigen 
new
##    Var1                   Var2
## 1  1999 Krankenpflegeassistenz
## 2  2001 Krankenpflegeassistenz
## 3  2003 Krankenpflegeassistenz
## 4  2005 Krankenpflegeassistenz
## 5  2007 Krankenpflegeassistenz
## 6  2009 Krankenpflegeassistenz
## 7  2011 Krankenpflegeassistenz
## 8  2013 Krankenpflegeassistenz
## 9  2015 Krankenpflegeassistenz
## 10 1999       Altenpflegehilfe
## 11 2001       Altenpflegehilfe
## 12 2003       Altenpflegehilfe
## 13 2005       Altenpflegehilfe
## 14 2007       Altenpflegehilfe
## 15 2009       Altenpflegehilfe
## 16 2011       Altenpflegehilfe
## 17 2013       Altenpflegehilfe
## 18 2015       Altenpflegehilfe
## 19 1999    Kinderkrankenpflege
## 20 2001    Kinderkrankenpflege
## 21 2003    Kinderkrankenpflege
## 22 2005    Kinderkrankenpflege
## 23 2007    Kinderkrankenpflege
## 24 2009    Kinderkrankenpflege
## 25 2011    Kinderkrankenpflege
## 26 2013    Kinderkrankenpflege
## 27 2015    Kinderkrankenpflege
## 28 1999          Krankenpflege
## 29 2001          Krankenpflege
## 30 2003          Krankenpflege
## 31 2005          Krankenpflege
## 32 2007          Krankenpflege
## 33 2009          Krankenpflege
## 34 2011          Krankenpflege
## 35 2013          Krankenpflege
## 36 2015          Krankenpflege
## 37 1999            Altenpflege
## 38 2001            Altenpflege
## 39 2003            Altenpflege
## 40 2005            Altenpflege
## 41 2007            Altenpflege
## 42 2009            Altenpflege
## 43 2011            Altenpflege
## 44 2013            Altenpflege
## 45 2015            Altenpflege

Mit der Funktion cbind() können wir nun die Zahlenwerte aus der Matrix als neue Spalte an das Datenframe anhängen. Dafür müssen die Werte in Form eines Vektors vorliegen.

Um die Matrix als Vektor auszugeben nutzen wir die Funktion as.vector()

# stelle die Matrix als Vektor dar 
as.vector(Pflegeberufe)
##  [1]  16624  55770  47779 430983 109161  19061  52710  48203 436767 124879
## [11]  19478  49727  48822 444783 141965  21537  45776  48519 449355 158817
## [21]  27731  48326  49080 457322 178902  36481  47903  49307 465446 194195
## [31]  46517  47978  48291 468192 208304  54371  48363  48937 472580 227154
## [41]  64127  49507  48913 476416 246412

Wie Sie sehen, überführt R die Matrix spaltenweise in den Vektor. Für unser neues Datenframe bräuchten wir aber einen zeilenorientierten Vektor, damit er mit der Reihenfolge der Einträge (Paarung aus Jahr und Berufsgruppe) übereinstimmt. Um einen reihenorientierten Vektor zu erzeugen muss die Matrix mit der Funktion t() transpoiniert werden.

# stelle die Matrix als Vektor dar 
# zeilenorientiert
as.vector(t(Pflegeberufe))
##  [1]  16624  19061  19478  21537  27731  36481  46517  54371  64127  55770
## [11]  52710  49727  45776  48326  47903  47978  48363  49507  47779  48203
## [21]  48822  48519  49080  49307  48291  48937  48913 430983 436767 444783
## [31] 449355 457322 465446 468192 472580 476416 109161 124879 141965 158817
## [41] 178902 194195 208304 227154 246412

Diesen Vektor fügen wir nun per cbind() dem Datenframe als neue Spalte hinzu

# füge Spalte hinzu 
Pflegeframe <- cbind(new, as.vector(t(Pflegeberufe)))

# benenne die Spalten neu
colnames(Pflegeframe) <- c("Jahr", "Berufsgruppe", "Anzahl") 
# zeige an 
Pflegeframe
##    Jahr           Berufsgruppe Anzahl
## 1  1999 Krankenpflegeassistenz  16624
## 2  2001 Krankenpflegeassistenz  19061
## 3  2003 Krankenpflegeassistenz  19478
## 4  2005 Krankenpflegeassistenz  21537
## 5  2007 Krankenpflegeassistenz  27731
## 6  2009 Krankenpflegeassistenz  36481
## 7  2011 Krankenpflegeassistenz  46517
## 8  2013 Krankenpflegeassistenz  54371
## 9  2015 Krankenpflegeassistenz  64127
## 10 1999       Altenpflegehilfe  55770
## 11 2001       Altenpflegehilfe  52710
## 12 2003       Altenpflegehilfe  49727
## 13 2005       Altenpflegehilfe  45776
## 14 2007       Altenpflegehilfe  48326
## 15 2009       Altenpflegehilfe  47903
## 16 2011       Altenpflegehilfe  47978
## 17 2013       Altenpflegehilfe  48363
## 18 2015       Altenpflegehilfe  49507
## 19 1999    Kinderkrankenpflege  47779
## 20 2001    Kinderkrankenpflege  48203
## 21 2003    Kinderkrankenpflege  48822
## 22 2005    Kinderkrankenpflege  48519
## 23 2007    Kinderkrankenpflege  49080
## 24 2009    Kinderkrankenpflege  49307
## 25 2011    Kinderkrankenpflege  48291
## 26 2013    Kinderkrankenpflege  48937
## 27 2015    Kinderkrankenpflege  48913
## 28 1999          Krankenpflege 430983
## 29 2001          Krankenpflege 436767
## 30 2003          Krankenpflege 444783
## 31 2005          Krankenpflege 449355
## 32 2007          Krankenpflege 457322
## 33 2009          Krankenpflege 465446
## 34 2011          Krankenpflege 468192
## 35 2013          Krankenpflege 472580
## 36 2015          Krankenpflege 476416
## 37 1999            Altenpflege 109161
## 38 2001            Altenpflege 124879
## 39 2003            Altenpflege 141965
## 40 2005            Altenpflege 158817
## 41 2007            Altenpflege 178902
## 42 2009            Altenpflege 194195
## 43 2011            Altenpflege 208304
## 44 2013            Altenpflege 227154
## 45 2015            Altenpflege 246412

Der vollständige Code, ohne Hilfsdatenframe new, zur Überführung der Matrix Pflegeberufe in das Tidy-Data-Datenframe Pflegeframe sieht also so aus:

# füge Spalte hinzu 
Pflegeframe <- cbind(expand.grid( colnames(Pflegeberufe), rownames(Pflegeberufe)), as.vector(t(Pflegeberufe)))

# benenne die Spalten neu 
colnames(Pflegeframe) <- c("Jahr", "Berufsgruppe", "Anzahl") 
# zeige erste 12 Fälle an
head(Pflegeframe, 12)
##    Jahr           Berufsgruppe Anzahl
## 1  1999 Krankenpflegeassistenz  16624
## 2  2001 Krankenpflegeassistenz  19061
## 3  2003 Krankenpflegeassistenz  19478
## 4  2005 Krankenpflegeassistenz  21537
## 5  2007 Krankenpflegeassistenz  27731
## 6  2009 Krankenpflegeassistenz  36481
## 7  2011 Krankenpflegeassistenz  46517
## 8  2013 Krankenpflegeassistenz  54371
## 9  2015 Krankenpflegeassistenz  64127
## 10 1999       Altenpflegehilfe  55770
## 11 2001       Altenpflegehilfe  52710
## 12 2003       Altenpflegehilfe  49727

4.5.5 Listen

In der Datenklasse Listen können beliebige Datenobjekte (Vektor, Faktor, Datenframe, Matrizen) zusammengefasst werden. Listen sind also eine Ansammlung an Datenobjekten, ähnlich wie ein Schrank oder ein Koffer, in welchem man “sein Zeug” ablegt. Wir generieren testweise eine Liste aus den Datenobjekten, die wir bislang erzeugt haben. Dies erfolgt in  mit der Funktion list().

# erzeuge eine Liste aus den Datenobjekten 
# "MeinDatenframe", "mymatrix", "geschlecht" und "logical" 
MeineListe <- list(MeinDatenframe, mymatrix, geschlecht, logical)

# anzeigen 
MeineListe
## [[1]]
##        geschlecht spitzname hausnummer angemeldet
## Eins            m      Hasi          1       TRUE
## Zwei            w       Ide          2       TRUE
## Drei            d     Momsi          3      FALSE
## Vier            m       Ryu          4       TRUE
## Fünf            w      Dave          5      FALSE
## Sechs           d      Zoid          6      FALSE
## Sieben          m       Adu          7      FALSE
## Acht            w       Efi          8       TRUE
## Neun            d       Ole          9       TRUE
## Zehn            m       Ray         10       TRUE
## Elf             w       Sam         11      FALSE
## Zwölf           d       Emi         12       TRUE
## 
## [[2]]
##      a  b  c  d  e
## I   11 21 31 41 51
## II  12 22 32 42 52
## III 13 23 33 43 53
## IV  14 24 34 44 54
## V   15 25 35 45 55
## 
## [[3]]
##  [1] m w d m w d m w d m w d
## Levels: d m w
## 
## [[4]]
##  [1]  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE  TRUE
## [13]  TRUE  TRUE  TRUE FALSE FALSE FALSE FALSE FALSE

Wie Sie sehen, werden die einzelnen Positionen der Datenobjekte durch doppelte eckige Klammer angezeigt ([[1]] ist unser Datenframe, [[2]] unsere Matrix, usw.) und können über diese auch referenziert werden.

# zeige Objekt 1 (= unser Datenframe) 
MeineListe[[1]]
##        geschlecht spitzname hausnummer angemeldet
## Eins            m      Hasi          1       TRUE
## Zwei            w       Ide          2       TRUE
## Drei            d     Momsi          3      FALSE
## Vier            m       Ryu          4       TRUE
## Fünf            w      Dave          5      FALSE
## Sechs           d      Zoid          6      FALSE
## Sieben          m       Adu          7      FALSE
## Acht            w       Efi          8       TRUE
## Neun            d       Ole          9       TRUE
## Zehn            m       Ray         10       TRUE
## Elf             w       Sam         11      FALSE
## Zwölf           d       Emi         12       TRUE
# zeige Objekt 3 (= variable "geschlecht") 
MeineListe[[3]]
##  [1] m w d m w d m w d m w d
## Levels: d m w

Die Werte der jeweiligen Objekte können anschließend wie gewohnt referenziert werden.

# zeige Objekt 3, aber nur den 5. Wert 
MeineListe[[3]][5]
## [1] w
## Levels: d m w
# zeige Objekt 2, aber nur die 3. Spalte 
MeineListe[[2]][, 3]
##   I  II III  IV   V 
##  31  32  33  34  35

4.6 Fehlende Daten

Fehlende Daten werden in R mit dem Ausdruck NA dargestellt. Angenommen Sie erfragen von zehn Personen das Alter, und zwei Personen geben keine Auskunft, dann könnten man das wie folgt in einem Vektor darstellen.

# Alter von 10 Personen 
alter <- c(28, 30, NA, 21, 27, 43, NA, 35, 22, 18) 
# anzeigen 
alter
##  [1] 28 30 NA 21 27 43 NA 35 22 18

Möchten wir nun die Summe der Alterswerte bestimmen, meldet R uns NA zurück

# Summe der Altersangaben 
sum(alter)
## [1] NA

Die Berechnung wird nicht durchgeführt, da fehlende Werte in der Reihe vorkommen. Möchte man die Berechnung erzwingen, kann (bei fast jeder -Funktion) der Parameter na.rm (für NA remove; entferne NA) auf TRUE gesetzt werden. So werden alle fehlenden Daten ignoriert und die Berechnungen nur mit der Restmenge durchgeführt.

# Summe der Altersangaben OHNE NA 
sum(alter, na.rm=TRUE)
## [1] 224

Mit der Funktion is.na() kann geprüft werden, ob fehlende Werte enthalten sind

# sind Werte in "alter" NA? 
is.na(alter)
##  [1] FALSE FALSE  TRUE FALSE FALSE FALSE  TRUE FALSE FALSE FALSE

Möchten wir wissen, an welcher Position sich die NA-Einträge befinden können wir die Funktion which() mit is.na() kombinieren

# welche Position haben die NAs in "alter" 
which(is.na(alter))
## [1] 3 7

Sind keine NAs enthalten, meldet R ein integer(0) zurück

# NAs in "Pflegeframe" 
which(is.na(Pflegeframe))
## integer(0)

4.7 Umgang mit Datensätzen

Mit der Funktion str() (für structure) erhalten wir eine erste Beschreibung des Datensatzes.

# Übersicht von "MeinDatenframe" 
str(MeinDatenframe)
## 'data.frame':    12 obs. of  4 variables:
##  $ geschlecht: Factor w/ 3 levels "d","m","w": 2 3 1 2 3 1 2 3 1 2 ...
##  $ spitzname : chr  "Hasi" "Ide" "Momsi" "Ryu" ...
##  $ hausnummer: int  1 2 3 4 5 6 7 8 9 10 ...
##  $ angemeldet: logi  TRUE TRUE FALSE TRUE FALSE FALSE ...

Das Datenframe MeinDatenframe enthält 12 Beobachtungen von 4 Variablen. Varibale geschlecht ist ein Faktor mit 3 Ausprägungen, usw.

In RStudio werden diese Informationen im Datenfenster angezeigt (Abbildung 4.8).

Abbildung 4.8: str() im Datenfenster

Mit der Funktion head() können Sie sich einen weiteren Überblick über den Datensatz verschaffen. Die Funktion head() gibt die ersten 6 Zeilen des Datensatzes aus.

# zeige die ersten 6 Reihen von "MeinDatenframe"
head(MeinDatenframe)
##       geschlecht spitzname hausnummer angemeldet
## Eins           m      Hasi          1       TRUE
## Zwei           w       Ide          2       TRUE
## Drei           d     Momsi          3      FALSE
## Vier           m       Ryu          4       TRUE
## Fünf           w      Dave          5      FALSE
## Sechs          d      Zoid          6      FALSE

Möchten wir mehr als 6 Einträge sehen, können wir dies an head() übergeben:

# zeige die ersten 10 Reihen von "MeinDatenframe"
head(MeinDatenframe, 10)
##        geschlecht spitzname hausnummer angemeldet
## Eins            m      Hasi          1       TRUE
## Zwei            w       Ide          2       TRUE
## Drei            d     Momsi          3      FALSE
## Vier            m       Ryu          4       TRUE
## Fünf            w      Dave          5      FALSE
## Sechs           d      Zoid          6      FALSE
## Sieben          m       Adu          7      FALSE
## Acht            w       Efi          8       TRUE
## Neun            d       Ole          9       TRUE
## Zehn            m       Ray         10       TRUE

Im Gegensatz dazu zeigt tail() die letzten Reihen des Datenframes an.

# zeige die letzten 5 Reihen von "MeinDatenframe"
tail(MeinDatenframe, 5)
##       geschlecht spitzname hausnummer angemeldet
## Acht           w       Efi          8       TRUE
## Neun           d       Ole          9       TRUE
## Zehn           m       Ray         10       TRUE
## Elf            w       Sam         11      FALSE
## Zwölf          d       Emi         12       TRUE

4.7.1 Sortieren

Mit der Funktion sort() können Datenreihen auf- und absteigend sortiert werden. Standardmäßig wird aufsteigend sortiert

# sortiere "hausnummer" von "MeinDatenframe" 
# aufsteigend
sort(MeinDatenframe$hausnummer)
##  [1]  1  2  3  4  5  6  7  8  9 10 11 12

Um absteigend zu sortieren, muss der Parameter decreasing auf TRUE gesetzt werden

# sortiere "spitzname" von "MeinDatenframe"
# absteigend
sort(MeinDatenframe$spitzname, decreasing=T)
##  [1] "Zoid"  "Sam"   "Ryu"   "Ray"   "Ole"   "Momsi" "Ide"   "Hasi"  "Emi"  
## [10] "Efi"   "Dave"  "Adu"

Mit der Funktion order() werden die Zeilenpositionen ausgegeben, an deren Stelle sich die von sort() sortierten Daten befinden.

# sortiere "spitznamen" von "MeinDatenframe" 
# aufsteigend, und zeige Positionen an 
order(MeinDatenframe$spitzname)
##  [1]  7  5  8 12  1  2  3  9 10  4 11  6

Das kann man nun verwenden, um den kompletten Datensatz in dieser Ordnung anzuzeigen. Wir können ja durch Anhängen von eckigen Klammern die gewünschten Zeilen und Spalten des Datenframes referenzieren. Also übergeben wir die Positionsreihenfolge von order() als Argument in die eckige Klammer.

# sortiere "spitznamen" von "MeinDatenframe" 
# aufsteigend, zeige ganzes Datenframe an
MeinDatenframe[ order(MeinDatenframe$spitzname), ]
##        geschlecht spitzname hausnummer angemeldet
## Sieben          m       Adu          7      FALSE
## Fünf            w      Dave          5      FALSE
## Acht            w       Efi          8       TRUE
## Zwölf           d       Emi         12       TRUE
## Eins            m      Hasi          1       TRUE
## Zwei            w       Ide          2       TRUE
## Drei            d     Momsi          3      FALSE
## Neun            d       Ole          9       TRUE
## Zehn            m       Ray         10       TRUE
## Vier            m       Ryu          4       TRUE
## Elf             w       Sam         11      FALSE
## Sechs           d      Zoid          6      FALSE

Oder andersherum

# sortiere "spitznamen" von "MeinDatenframe" 
# absteigend, zeige ganzes Datenframe an 
MeinDatenframe[order(MeinDatenframe$spitzname, decreasing=T), ]
##        geschlecht spitzname hausnummer angemeldet
## Sechs           d      Zoid          6      FALSE
## Elf             w       Sam         11      FALSE
## Vier            m       Ryu          4       TRUE
## Zehn            m       Ray         10       TRUE
## Neun            d       Ole          9       TRUE
## Drei            d     Momsi          3      FALSE
## Zwei            w       Ide          2       TRUE
## Eins            m      Hasi          1       TRUE
## Zwölf           d       Emi         12       TRUE
## Acht            w       Efi          8       TRUE
## Fünf            w      Dave          5      FALSE
## Sieben          m       Adu          7      FALSE

4.7.2 Teilgruppen erstellen

Mit der Funktion subset() können Teilgruppen aus einem Datenframe erstellt werden.

# erstelle eine Teilgruppe aus MeinDatenframe
# für "geschlecht" = d
subset(MeinDatenframe, geschlecht=="d")
##       geschlecht spitzname hausnummer angemeldet
## Drei           d     Momsi          3      FALSE
## Sechs          d      Zoid          6      FALSE
## Neun           d       Ole          9       TRUE
## Zwölf          d       Emi         12       TRUE

Über den Parameter select kann angegeben werden, welche Spalten übernommen werden sollen.

# erstelle eine Teilgruppe aus MeinDatenframe
# für "geschlecht" = d
# aber nur Spalte "spitzname" und "angemeldet"
subset(MeinDatenframe, geschlecht=="d", select = c(spitzname, angemeldet))
##       spitzname angemeldet
## Drei      Momsi      FALSE
## Sechs      Zoid      FALSE
## Neun        Ole       TRUE
## Zwölf       Emi       TRUE

Eine andere Möglichkeit zur Erstellung von Teilgruppen kann über die Referenzierung der Zeilen und Spalten des Datenframes (eckige Klammern) erfolgen

# erstelle eine Teilgruppe aus MeinDatenframe
# für "geschlecht" = w
MeinDatenframe[ MeinDatenframe$geschlecht == "w", ]
##      geschlecht spitzname hausnummer angemeldet
## Zwei          w       Ide          2       TRUE
## Fünf          w      Dave          5      FALSE
## Acht          w       Efi          8       TRUE
## Elf           w       Sam         11      FALSE

Auf diese Weise können die Bedingungen auch mit einem & kombiniert werden

# erstelle eine Teilgruppe aus MeinDatenframe 
# für "geschlecht" = w und "hausnummer" größer 5 
MeinDatenframe[(MeinDatenframe$geschlecht == "w") & (MeinDatenframe$hausnummer > 5) ,]
##      geschlecht spitzname hausnummer angemeldet
## Acht          w       Efi          8       TRUE
## Elf           w       Sam         11      FALSE

Über Angabe der Spaltennummern können wir das Teilset noch weiter zusammenschrumpfen lassen

# erstelle eine Teilgruppe aus MeinDatenframe 
# für "geschlecht" = w und "angemeldet" = TRUE 
# aber nur Spalte "spitzname" und "hausnummer"
MeinDatenframe[(MeinDatenframe$geschlecht == "w") & (MeinDatenframe$angemeldet== T), c(2,3)]
##      spitzname hausnummer
## Zwei       Ide          2
## Acht       Efi          8

Möchte man auf die Referenzierung per Dollarzeichen $ verzichten, kann die Funktion with() verwendet werden.

# with() macht es leichter 
with(MeinDatenframe, MeinDatenframe[(geschlecht == "w") & (angemeldet == T), c(2,3)])
##      spitzname hausnummer
## Zwei       Ide          2
## Acht       Efi          8

4.8 Daten laden und speichern

In R können Daten leicht geladen und gespeichert werden. Eine R-Datei hat die Dateiendung .RData. In der Datei können “beliebig” viele Objekte (Variablen, Datenframes, usw.) enthalten sein.

Mit der Funktion save.image() werden alle Objekte im Speicher, also die aktuelle “Worksession,” als “unsichtbare” Datei .RData ins aktuelle Arbeitsverzeichnis geschrieben.

# speichere die aktuelle Sitzung 
save.image()

In RStudio können Sie im Ausgabefenster (unten rechts) auf den Reiter Files klicken. Sie sehen Ihr aktuelles Arbeitsverzeichnis, und darin die R-Datei .RData (siehe Abbildung 4.9).

Abbildung 4.9: Datei .RData im Arbeitsverzeichnis

Das ist übrigens die selbe Datei, die angelegt wird, wenn Sie RStudio beenden, und “speichere Arbeitsspeicher” klicken. Das heisst, dass diese Datei unter Umständen bald wieder überschrieben wird.

Der Funktion save.image() kann auch ein gewünschter Dateiname übergeben werden.

# speichere die aktuelle Sitzung in Datei "MeineSitzung.RData"
save.image("MeineSitzung.RData")

Die Datei MeineSitzung.RData wird in RStudio im Ausgabefenster angezeigt (siehe Abbildung 4.10).

Abbildung 4.10: Datei MeineSitzung.RData im Arbeitsverzeichnis

Wenn nur einzelne Objekte gespeichert werden sollen, wird die save()-Funktion angewandt. Mit dem list-Parameter werden die gewünschten Objekte angegeben, welche in die Datei gespeichert werden sollen.

# speichere nur die Variable "sequenz" 
# in Datei "Sequenz.RData" 
save(file="Sequenz.RData", list="sequenz")
# speichere die Variablen "sequenz" "normal" und "geschlecht"
# in Datei "MeineVariablen.RData" 
save(file="MeineVariablen.RData", list=c("sequenz", "normal", "geschlecht"))

Daten können mit dem load()-Befehl geladen werden.

# lade Datei "MeineVariablen.RData" 
load("MeineVariablen.RData")

In RStudio kann im Ausgabefenster unter dem Reiter Files einfach auf eine R-Datei geklickt werden, um diese zu laden (Abbildung 4.11).

Abbildung 4.11: Dateien im Arbeitsverzeichnis

Wenn die Datei im Internet liegt, muss sie mit Hilfe der url()-Funktion geladen werden

# Test-Datensatz aus dem Internet laden # (dieser enthält das Datenframe "ordinalSample")
load(url("https://www.produnis.de/R/OrdinalSample.RData"))

# Daten anschauen mit head(ordinalSample) 
head(ordinalSample)

4.9 Arbeitsverzeichnis

Das aktuelle Arbeitsverzeichnis kann per getwd() angezeigt werden.

# Arbeitsverzeichnis ausgeben 
getwd()
## [1] "/home/produnis/Dokumente/Programmierung/R/R-Buch/bookdown"

Mit dem Befehl dir() werden die Dateien des aktuellen Arbeitsverzeichnisses angezeigt.

# Inhalt des Arbeitsverzeichnis ausgeben 
dir()
##  [1] "_book"                       "_bookdown_files"            
##  [3] "_bookdown.yml"               "_output.yml"                
##  [5] "01-Einleitung.Rmd"           "10-Installation.Rmd"        
##  [7] "20-R-und-RStudio.Rmd"        "30-klassischesR.Rmd"        
##  [9] "40-RMarkdown.Rmd"            "50-Tidyverse.Rmd"           
## [11] "60-Weitere-R-Info.Rmd"       "70-Statistik-mit-R.Rmd"     
## [13] "80-Was-willst-du-machen.Rmd" "90-Credits.Rmd"             
## [15] "alteDaten.sav"               "book.bib"                   
## [17] "Datentabelle.txt"            "DieDaten.csv"               
## [19] "dummy-Corona.RData"          "favicon.ico"                
## [21] "images"                      "index.Rmd"                  
## [23] "joe.css"                     "pf8sub.RData"               
## [25] "Pflegeframe.RData"           "preamble.tex"               
## [27] "R-Buch_bookdown.Rproj"       "R-Buch-epubtitelbild.png"   
## [29] "rbuch_files"                 "rbuch.Rmd"                  
## [31] "SCHMIERZETTEL.R"             "style.css"

Mit dem Befehl setwd() kann das aktuelle Arbeitsverzeichnis gewechselt werden.

# Arbeitsverzeichnis wechseln 
setwd("/tmp/R/")

Auf Dauer kann es einfacher sein, ein eigenes Arbeitsverzeichnis beim Startvorgang einzustellen (siehe Abschnitt 3.2.1).

4.10 Daten importieren

In R können Daten auf vielfältige Weise importiert werden. Das Grundproblem beim “Tausch” von Daten zwischen verschiedenen Anwendungen (z.B. SPSS oder Statistica) liegt im verwendeten Format. So können native SPSS-Dateien nur mit einem Zusatzpaket importiert werden, für Statistica gibt es ein solches Zusatzpaket (derzeit) nicht. In beiden Fällen ist es aber möglich, die Daten über das CSV-Format zu tauschen. Hierfür speichert man in SPSS den Datensatz als CSV-Datei ab und liest diese in R ein.

Bedenken Sie ebenfalls, dass R Dezimalstellen mit einem Punkt angibt, und nicht mit einem Komma. So kann es zu Fehlern kommen, wenn die zu importierenden Werte nicht ebenfalls die Dezimalstellen mit einem Punkt angeben! Dies ist ein weiterer häufiger Anfängerfehler!

4.10.1 Import aus Textdateien

In einer Textdatei (mit Dateiendung .txt) liegen unsere Daten wie folgt vor:

m 28 80 170
w 18 55 174
w 25 74 183
m 29 101 190
m 21 84 185
w 19 74 178
w 27 65 169
w 26 56 163
m 31 88 189
m 22 78 184 

Angenommen, diese Textdatei hieße Datentabelle.txt, und läge in unserem Arbeitsverzeichnis, dann können wir die Daten mit der Funktion read.table() in R einlesen.

# importiere Daten aus "Datentabelle.txt" 
MeineTabelle <- read.table("Datentabelle.txt", header=TRUE)

# ausgeben 
MeineTabelle
##    Geschlecht Alter Gewicht Groesse
## 1           m    28      80     170
## 2           w    18      55     174
## 3           w    25      74     183
## 4           m    29     101     190
## 5           m    21      84     185
## 6           w    19      74     178
## 7           w    27      65     169
## 8           w    26      56     163
## 9           m    31      88     189
## 10          m    22      78     184

Liegt die Datei im Internet, kann die Adresse mit der Funktion url() übergeben werden.

# importiere Daten aus "Datentabelle.txt" 
MeineTabelle <- read.table(url("https://www.produnis.de/R/Datentabelle.txt"), header=TRUE)

# ausgeben 
MeineTabelle
##    Geschlecht Alter Gewicht Groesse
## 1           m    28      80     170
## 2           w    18      55     174
## 3           w    25      74     183
## 4           m    29     101     190
## 5           m    21      84     185
## 6           w    19      74     178
## 7           w    27      65     169
## 8           w    26      56     163
## 9           m    31      88     189
## 10          m    22      78     184

Der Parameter header=TRUE gibt an, dass in der ersten Zeile der Textdatei die Spaltennamen (Variablennamen) angegeben sind.

Da wir sonst keine Parameter übergeben haben, geht R davon aus, dass die Werte durch ein Leerzeichen getrennt sind, was in unserem Beispiel auch stimmt. Sollte die Tabelle in diesem Format vorliegen (die Daten sind mit einem Komma getrennt) …

m,28,80,170
w,18,55,174
w,25,74,183
m,29,101,190
m,21,84,185
w,19,74,178
w,27,65,169
w,26,56,163
m,31,88,189
m,22,78,184

…dann müssen wir mit der Option sep (für Datenseparator) angeben, dass die Daten mit einem Komma getrennt sind.

# importiere Daten aus "Datentabelle.txt" 
# Daten sind mit Komma getrennt 
MeineTabelle <- read.table("Datentabelle.txt", sep=",", header=TRUE)

In beiden Fällen wurde die Texttabelle als Datenframe in R importiert. Die Funktion class() bestätigt uns dies.

# welche Datenklasse wurde erzeugt? 
class(MeineTabelle)
## [1] "data.frame"

Aber welche Datentypen wurden in den Spalten erzeugt?

# welcher Datentyp liegt in Spalte 1 vor? 
class(MeineTabelle[,1])
## [1] "character"
# welcher Datentyp liegt in Spalte "Alter" vor?
class(MeineTabelle$Alter)
## [1] "integer"

Die Spalte Geschlecht wurde als character angelegt, die Variable Alter ist numerisch.

Möchten wir Geschlecht in einen Faktor umwandeln, ``überschreiben’’ wir einfach die Spalte entsprechend:

# "Geschlecht" soll factor werden
MeineTabelle$Geschlecht <- factor(MeineTabelle$Geschlecht)

# überprüfen, ob es geklappt hat
class(MeineTabelle$Geschlecht)
## [1] "factor"

4.10.2 Import aus CSV-Datei

Das CSV-Format (für comma-separated-values) wird von vielen Anwendungen unterstützt. So können auch Tabellen, die in LibreOffice oder Excel angelegt wurden, als CSV-Datei gespeichert werden. Wenn Sie eine Datei im CSV-Format speichern, fragt Sie Ihre Anwendung nach dem gewünschten Datenseparator, also nach dem Zeichen, durch welches die Werte voneinander getrennt sind. Standardmäßig wird hier ein Komma “,” verwendet (wie der Name CSV vermuten lässt, und was zusätzlich sicherstellt, dass die zu importierenden Daten ihre Dezimalstellen mit einem Punkt abbilden, denn sonst würde nach jedem Dezimalkomma ein neuer Wert beginnen!) oder ein Semikolon “;” . Ich persönlich verwende gerne das Semikolon.

Der Import in R erfolgt ebenfalls über die Funktion read.table(). Neben dem Parameter header muss ihr der eingestellte Datenseparator übergeben werden.

Angenommen, die CSV-Datei hieße DieDaten.csv, läge in unserem Arbeitsverzeichnis und hätte den Datenseparator “;” dann erfolgt der Import per read.table() mit dem Befehl:

# importiere Daten aus "DieDaten.csv" 
NeueTabelle <- read.table("DieDaten.csv", sep=";", header=TRUE)

Liegt die Datei im Internet, kann die Adresse per url() Funktion übergeben werden.

# importiere Daten aus dem Internet 
NeueTabelle <- read.table(url("http://www.produnis.de/R/DieDaten.csv"), sep=";", header=TRUE)

# anzeigen 
NeueTabelle
##     Name   Geschlecht Lieblingsfarbe Einkommen
## 1   Hans    maennlich          gruen      1233
## 2   Caro     weiblich           blau       800
## 3   Lars intersexuell           gelb      2400
## 4   Ines     weiblich        schwarz      4000
## 5 Samira     weiblich           gelb       899
## 6  Peter    maennlich          gruen      1100
## 7  Sarah     weiblich           blau      1900

Sollte die CSV-Datei mit dem Datenseparator TAB (für Tabulator) erstellt worden sein, lautet der Befehl:

# importiere Daten # Daten sind mit TAB separiert! 
NeueTabelle <- read.table("DieDaten.csv", sep=""͡, header=TRUE)

(Separieren Sie Ihre Daten möglichst niemals mittels Tabulator, da es hier zu ungewollten Effekten kommen kann.)

Sollte read.table)() keine brauchbaren Daten erzeugen (z.B. wegen Sonderzeichen in den Daten oder wenn die Daten per TAB separiert wurden), kann auf die Funktion read.csv() zurückgegriffen werden. Letztendlich ruft diese Funktion intern auch “nur” read.table() auf, jedoch mit jeder Menge voreingestellter Parameter.

# importiere Daten mit read.csv() # Daten sind mit TAB separiert!
NeueTabelle <- read.csv("DieDaten.csv", sep=""͡, header=TRUE)

4.10.3 Import aus SPSS-Datei

Um native SPSS-Dateien in R zu importieren, müssen zunächste Zusatzpakete installiert werden, siehe hierzu den Abschnitt 4.12.

Zum Import von SPSS-Dateien installieren und aktivieren wir das Paket haven.

# installiere das Zusatzpaket "haven" 
install.packages("haven")
# aktiviere das Paket "haven" 
library("haven")

Das Paket haven bietet für jeden SPSS-Dateityp die passende Funktion an. Angenommen, die SPSS-Datei hieße “alteDaten.sav” und läge in unserem Arbeitsverzeichnis, dann kann sie mit der Funktion read_sav() in R importiert werden.

# importiere SPSS-Datei "alteDaten.sav" 
alteDaten <- read_sav("alteDaten.sav")

In SPSS werden kategoriale Daten häufig mit Labels versehen.

# Lade Test-SPSS-Datei mit Labels 
spss <- haven::read_sav(url("https://www.produnis.de/R/alteDaten-lang.sav"))
head(spss)
## # A tibble: 6 x 6
##             v1           v2           v3            v4           v5     thetruth
##      <dbl+lbl>    <dbl+lbl>    <dbl+lbl>     <dbl+lbl>    <dbl+lbl>    <dbl+lbl>
## 1 4 [strongly… 4 [strongly… 4 [strongly… NA            NA           4 [strongly…
## 2 4 [strongly… 4 [strongly… 4 [strongly… NA            NA           4 [strongly…
## 3 4 [strongly… 4 [strongly… 4 [strongly… NA            NA           4 [strongly…
## 4 4 [strongly… 3 [agree]    3 [agree]     4 [strongly…  4 [strongl… 4 [strongly…
## 5 3 [agree]    3 [agree]    2 [disagree]  2 [disagree]  4 [strongl… 4 [strongly…
## 6 2 [disagree] 3 [agree]    3 [agree]     2 [disagree]  4 [strongl… 4 [strongly…

Wir sehen, dass die Werte der Spalten gelabelt sind (4=strongly agree, 3=agree, usw.). Die Labels stehen in eckigen Klammern neben dem eingentlichen Wert der Variable.

Die enthaltenen Labels kann man sich mit der Funktion attr() anzeigen lassen.

# Namen der Variablen 
attr(spss, "names")
## [1] "v1"       "v2"       "v3"       "v4"       "v5"       "thetruth"

Das Label einer Variable wird angezeigt mit

# Label der Variablen 
attr(spss$v1, "label")
## [1] "Blue Question"

Die Labels innerhalb einer Variable mit

# Label der Variablenwerte für "v1"
attr(spss$v1, "labels")
## strongly disagree          disagree             agree    strongly agree 
##                 1                 2                 3                 4 
##         no answer 
##                 9

In R ist die Verwendung von Wertelabels eher untypisch. Es empfiehlt sich, die Ausprägungsstufen so wie sie sind als Werte einzutragen, also z.B. direkt “männlich” - “weiblich” - “divers” anstatt 0 - 1 - 2 und anschließender Labelung. So werden die Ausprägungen auch auf den Grafiken entsprechend “aussagekräftig” angezeigt.

Wir wandeln die Variablen in Faktoren um, welche die Labels als Levelnamen nutzen (die Funktion mutate() wird später genauer erläutert. Der Punkt innerhalb der as_factor()-Funktion bedeutet, dass der Datenstrom der Pipe verwendet werden soll).

library(tidyverse) 
spss %>% 
  mutate(as_factor(.)) 
## # A tibble: 45,278 x 6
##              v1           v2          v3           v4            v5     thetruth
##       <dbl+lbl>    <dbl+lbl>   <dbl+lbl>    <dbl+lbl>     <dbl+lbl>    <dbl+lbl>
##  1 4 [strongly… 4 [strongly… 4 [strongl… NA           NA            4 [strongly…
##  2 4 [strongly… 4 [strongly… 4 [strongl… NA           NA            4 [strongly…
##  3 4 [strongly… 4 [strongly… 4 [strongl… NA           NA            4 [strongly…
##  4 4 [strongly… 3 [agree]    3 [agree]    4 [strongl…  4 [strongly… 4 [strongly…
##  5 3 [agree]    3 [agree]    2 [disagre…  2 [disagre…  4 [strongly… 4 [strongly…
##  6 2 [disagree] 3 [agree]    3 [agree]    2 [disagre…  4 [strongly… 4 [strongly…
##  7 2 [disagree] 1 [strongly… 3 [agree]    2 [disagre…  1 [strongly… 4 [strongly…
##  8 2 [disagree] 3 [agree]    3 [agree]    3 [agree]    3 [agree]    3 [agree]   
##  9 4 [strongly… 4 [strongly… 4 [strongl… NA           NA            1 [strongly…
## 10 3 [agree]    3 [agree]    3 [agree]    4 [strongl…  4 [strongly… 4 [strongly…
## # … with 45,268 more rows

4.10.4 Import aus Excel-Datei

Um xlsx-Dateien in R zu importieren, muss das Zusatzpakete readxl installiert werden. Der Datenimport erfolgt dann mit der Funktion read_excel():

# installiere das Zusatzpaket "readxl" 
install.packages("readxl")
# aktiviere das Paket "readxl" 
library("readxl")

# importiere Excel-Datei "alteDaten.xlsx" 
alteDaten <- read_excel("alteDaten.xlsx")

Soll ein bestimmtes Tabellenblatt der xlsx-Datei importiert werden, kann diese mit dem Parameter sheet übergeben werden.

# importiere Tabelle "Tabelle1" aus Excel-Datei "alteDaten.xlsx"
alteDaten <- read_excel("alteDaten.xlsx", sheet="Tabelle1")

Soll nur ein bestimmter Bereich der Tabelle importiert werden, kann diese mit dem Parameter range übergeben werden.

# importiere aus Excel-Datei "alteDaten.xlsx" 
# Tabellenblatt "Tabelle1" 
# im Bereich A2 bis D3 
alteDaten <- read_excel("alteDaten.xlsx", sheet="Tabelle1", range="A2:D3")

4.10.5 Import aus .ods-Datei

Um ods-Dateien (z.B. aus Libreoffice oder OpenOffice) in R zu importieren, muss das Zusatzpakete readODS installiert werden. Der Datenimport erfolgt dann mit der Funktion read_ods():

# installiere das Zusatzpaket "readODS"
install.packages("readODS")

# aktiviere das Paket "readODS" 
library("readODS")

# importiere ods-Datei "tolleDaten.ods" 
tolleDaten <- read_ods("tolleDaten.ods")

Soll ein bestimmtes Tabellenblatt der ods-Datei importiert werden, kann diese mit dem Parameter sheet übergeben werden.

# importiere Tabelle "Tabelle1" aus ods-Datei "cooleDaten.ods"
cooleDaten <- read_ods("cooleDaten.ods", sheet="Tabelle1")

Soll nur ein bestimmter Bereich der Tabelle importiert werden, kann diese mit dem Parameter range übergeben werden.

# importiere aus ods-Datei "cooleDaten.ods" 
# Tabellenblatt "Tabelle1" 
# im Bereich A2 bis D3 
alteDaten <- read.ods("cooleDaten.ods", sheet="Tabelle1", range="A2:D3")

4.10.6 Import mit RStudio

Mit RStudio können Daten sehr leicht importiert werden. Im Datenfenster klicken Sie oben auf Import Dataset.

Es öffnet sich ein kleines Fenster, in welchem Sie das gewünschte Import-Format auswählen können (Abbildung 4.12). Wie Sie sehen, werden native Dateien aus Excel, SPSS, SAS und Stata unterstützt.

Abbildung 4.12: importiere Daten

Wir nehmen in diesem Beispiel From SPSS.

Da der Datenimport das Zusatzpaket haven erfordert, wird es zur Installation vorgeschlagen, sofern es noch nicht installiert ist (Abbildung 4.13). Wir bestätigen in diesem Fall mit Yes.

Abbildung 4.13: Zusatzpakete installieren

Nun öffnet sich das eigentliche Importierfenster (Abbildung (fig:RStudio-NewRScript)).

Abbildung 4.14: Importfenster

Klicken Sie oben rechts auf den Browse-Knopf und wählen Sie die SPSS-Datei aus, die Sie importieren möchten. Für Abbildung 4.14 habe ich die Datei alteDaten-I.sav in meinem Arbeitsverzeichnis ausgewählt. Sobald Sie eine Datei ausgewählt haben, wird unter Data Preview eine Vorschau des zu importierenden Datensatzes angezeigt. Wie Sie sehen hat mein alter Datensatz die Variablen v1, v2, v3 , usw.

Darunter sehen Sie die Ausprägungen der Variablen.

Unter dem Vorschaufenster können Sie im linken Abschnitt (Import Options) den Objektnamen eintragen, den der Datensatz in  haben soll. Ich habe in Abbildung 4.14 den Namen alteDaten_l gewählt. Das Format ist schon automatisch auf SAV eingestellt (denn der Dateiname endet mit .sav). Der Haken bei Open Data Viewer bewirkt, dass der Datensatz nach dem Import im Scritpfenster angezeigt wird.

Im rechten Abschnitt (Code Preview) sehen Sie die R-Befehle, die in der Konosle ausgeführt werden, um den Import durchzuführen.

Klicken Sie unten rechts auf Import.

4.11 Daten exportieren

In Abschnitt 4.8 wird beschrieben, wie Sie Ihre R-Objekte im .RData-Format abspeichern können.

Es ist aber natürlich ebenso möglich, die Daten in anderen Formaten zu exportieren.

4.11.1 Export als CSV-Datei

Mit dem CSV-Format kommen die meisten Anwendungen zurecht. Daher empfehlen wir, dieses zum Tausch zwischen Anwendungen zu verwenden. Wir benutzen hierfür die Funktion write.csv() und speichern das Datenframe MeinDatenframe in die Datei MeinDatenframe.csv. Als Datenseparator wird standardmäßig ein Leerzeichen verwendet. Soll ein anderer Separator verwendet werden, kann dies über den Parameter sep angegeben werden.

# exportiere "MeinDatenframe" als CSV-Datei # mit "," als Separator 
write.csv(MeinDatenframe, "MeinDatenframe.csv", sep=",")

4.11.2 Export als Textdatei-Datei

Mit der Funktion write.table() können die Daten als simple Textdatei gespeichert werden. Als Datenseparator wird auch hier standardmäßig ein Leerzeichen verwendet. Soll ein anderer Separator verwendet werden, kann dies über den Parameter sep angegeben werden.

# exportiere "MeinDatenframe" als Text-Datei # mit "," als Separator 
write.table(MeinDatenframe, "MeinDatenframe.txt", sep=",")

Sollen die Daten an eine bestehende Datei angehängt werden, muss der Parameter append auf TRUE gesetzt werden.

4.11.3 Export als SPSS-Datei

Mit dem Zusatzpaket haven können R-Objekte als SPSS-Datei abgespeichert werden.

Wir benutzen hierfür die Funktion write_sav() und speichern das Datenframe MeinDatenframe in die Datei MeinDatenframe.sav.

# exportiere "MeinDatenframe" als SPSS-Datei
write_sav(MeinDatenframe, "MeinDatenframe.sav")

Um eine komprimierte .zsav-Datei zu erstellen, setzen wir den Parameter compress auf TRUE.

# exportiere "MeinDatenframe" als komprimierte SPSS-Datei
write_sav(MeinDatenframe, "MeinDatenframe.sav", compressp=TRUE)

4.12 Zusatzpakete installieren

Zusatzpakete lassen sich in R mit dem Befehl install.packages() installieren. Möchte man beispielsweise “ggplot” (siehe Abschnitt 8.4) installieren, lautet der Befehl entsprechend (Achtung, das Paket für ggplot heisst ggplot2 !)

# ggplot installieren, ACHTUNG, das Paket heisst ggplot2 !!!
install.packages("ggplot2")

Manche Pakete benötigen weitere Zusatzpakete, um vollständig laufen zu können. Man spricht hier von “Abhängigkeiten,” da das eine Paket vom anderen abhängt. Möchte man das gewünschte Paket inklusive aller Abhängigkeiten installieren, ändert sich der Befehl in:

# Paket ggplot mit allen Abhängigkeiten installieren
install.packages("ggplot2", dependencies=TRUE)

Sollen mehrere Pakete auf einmal installiert werden, können diese mit der c()-Funktion übergeben werden.

# Pakete ggplot, wikibooks, pwr mit allen Abhängigkeiten installieren
install.packages(c("ggplot2", "wikibooks", "pwr"), dependencies=TRUE)

Um die installierten Zusatzpakete benutzen zu können, müssen sie in einer R-Sitzung zunächst geladen bzw. aktiviert werden. Dies erfolgt mit dem Befehl library().

# aktiviere das ggplot2 Paket 
library(ggplot2)

Mit dem Befehl detach() können die Zusatzpakete wieder deaktiviert werden.

# de-aktiviere das ggplot2 Paket 
detach("package:ggplot2")

Ein anderer Weg besteht darin, den Paketnamen mit zwei Doppelpunkten getrennt vor die Funktion zu schreiben.

# nutze Funktion "read_sav" aus dem Paket "haven"
haven::read_sav("SPSSdaten.sav")

Die beiden Doppelpunkte weisen R an, die Funktion read_sav() aus dem Paket haven zu nutzen. So kann man sich den library(haven)-Aufruf sparen. Dies bietet sich an, wenn man “nur mal kurz” eine bestimmte Funktion eines bestimmten Pakets nutzen möchte. Hat man mehrere Funktionsaufrufe, kann das Laden per library() die Schreibarbeit verkürzen.

In RStudio lassen sich Pakete auf mehrere Arten installieren. Zum einen kann man in der Menüzeile auf Tools \(\rightarrow\) Install packages klicken. Es öffnet sich ein neues Fenster, in welches wir einfach die Paketnamen eintragen können (Abbildung 4.15).

Abbildung 4.15: Zusatzpakete installieren

RStudio bietet eine weitere recht einfache und nützliche Methode zur Installation von Zusatzpaketen. Die Software durchsucht Ihre Scriptdatei nach dem Befehl library(). Ist das dort referenzierte Paket noch nicht installiert, schlägt RStudio die Installation vor (siehe gelber Balken in Abbildung 4.16).

Abbildung 4.16: Zusatzpakete per library()

Klicken Sie im gelben Balken auf Install um das Paket zu installieren. Dies ist nützlich, wenn man z.B. an einem “neuen” PC alte R-Scriptdateien öffnet, oder z.B. fremde R-Scripte verwendet. Nach dem Öffnen schlägt RStudio alle fehlenden Pakete zur Installation vor.

Natürlich können Sie auch einfach install.packages("ggplot2") (oder jeden anderen Paketnamen) in Ihre Scriptdatei schreiben und diese dann in der R-Konsole ausführen lassen.

Das Aktivieren von installierten Zusatzpaketen wird von RStudio ebenfalls ermöglicht. Klicken Sie im Ausgabefenster auf den Reiter Packages. So werden Ihnen alle installierten Zusatzpakete angezeigt (Abbildung 4.17).

Abbildung 4.17: alle installierten Pakete

Wenn Sie ein Paket aktivieren möchten, klicken Sie einfach dessen Häkchen an.

Wie Abbildung 4.18 zeigt, wurde durch den Klick automatisch der Befehl library(haven) in die R-Konsole übertragen und ausgeführt (linke Seite). Zum Deaktivieren müssen Sie einfach wieder auf das Kästchen klicken und den Haken entfernen.

Abbildung 4.18: Paket aktivieren

4.13 Ausgabe in Datei umleiten

Das Umleiten der R-Ausgabe in eine Textdatei ist evtl. ein etwas angestaubtes Verfahren, welches vor allem in Zeiten vor RStudio Anwendung gefunden hat. Mittlerweile steht mit dem RMarkdown eine komfortable Lösung zur Verfügung, hübsche R-Auswertungen z.B. in einem ansprechenden html-Dokument (sprich einer Webseite) zu präsentieren (siehe hierzu Abschnitt 5).

Standardmäßig schreibt R seine Ausgaben in das Konsolfenster. Manchmal kann es aber auch vorteilhaft sein, die Ausgaben in eine Datei umzulenken. Dies kann mit der Funktion sink() erreicht werden. Der folgende Befehl leitet alle Ausgaben in die Textdatei Ausgabe.txt im Arbeitsverzeichnis um.

# leite ab jetzt alle Ausgaben in die Datei "Ausgabe.txt" um
sink("Ausgabe.txt")

Soll die Umleitung aufgehoben werden, erfolgt dies mit einem leeren Funktionsaufruf.

# beende die Umleitung 
sink()

So kann man in der Scriptdatei genau festlegen, ab wann die Ausgaben in eine Datei geschrieben werden sollen, und wann nicht. Beachten Sie, dass R die Textdatei immer wieder überschreiben wird, z.B. wenn der sink() Aufruf beendet und dann erneut gestartet wird. Um die Ausgabe an eine bestehende Datei anzuhängen (ohne diese zu überschreiben) muss der Parameter append auf TRUE gesetzt werden.

# hänge ab jetzt alle Ausgaben an die Datei "Ausgabe.txt" an
sink("Ausgabe.txt", append=TRUE)

An dieser Stelle sei auf die Befehle print() und cat() hingewiesen. Wenn Sie die R-Ausgabe in eine Textdatei umleiten, möchten Sie evtl. ebenfalls Kommentare oder anderen Text in die Textdatei schreiben lassen, z.B. bevor Sie Befehle ausführen (oder nachdem).

Der Befehl print() gibt den Text dabei in der R-bekannten Weise aus.

# schreibe mit print() in die Textdatei 
print("Guten Tag, beginnen wir mit der Analyse.")

In die Textdatei wird geschrieben:

[1] "Guten Tag, beginnen wir mit der Analyse."

Mit dem Befehl cat() wird tatsächlich nur der Text ausgegeben (ohne den Positionsanzeiger [1]).

# schreibe mit cat() in die Textdatei 
cat("Guten Tag, beginnen wir mit der Analyse.geht es!")

In die Textdatei wird geschrieben:

Guten Tag, beginnen wir mit der Analyse.
Los geht es!

Der Parameter n gibt an, dass eine neue Zeile beginnen soll.

4.14 Verteilungsfunktionen

In R sind zahlreiche Verteilungsfunktionen implementiert. Wir beschränken uns in diesem Buch auf die für uns wichtigen Wahrscheinlichkeisverteilungen.

Eine vollständige Liste aller implementierten Verteilungen findet sich unter https://stat.ethz.ch/R-manual/R-devel/library/stats/html/Distributions.html

Der Funktionsumfang folgt dabei einer gewissen Logik, für jede Verteilung existiert je eine d, p, q und r-Funktion. Für die Normalverteilung (siehe Näheres in Abschnitt 4.14.1) sind das dnorm(), pnorm(), qnorm() und rnorm(). Für die t-Verteilung (siehe Abschnitt 4.14.2) heißen die Equivalente dt(), pt(), qt() und rt(), für \(\chi^2\) entsprechend dchisq(), pchisq(), qchisq() und rchisq().

  • d: ist jeweils die Dichtefunktion der Verteilung

  • p: berechnet die Werte der Verteilungsfunktion (kumulierte Dichte)

  • q: bestimmt die Quantile der Verteilung

  • r: erzeugt Zufallswerte aus der Verteilung

Dies möchten wir am Beispiel der Normalverteilung verdeutlichen.

4.14.1 Normalverteilung

Die Normalverteilung ist mit den oben beschriebenen Funktionen in R implementiert.

Mit der Funktion dnorm() berechnet man die Werte der Wahrscheinlichkeitsdichte. Möchte man beispielsweise die Wahrscheinlichkeitsdichte für \(x=2\) aus der Standardnormalverteilung berechnen lautet der Befehl:

# Wahrscheinlichkeitsdichte für x=2 
# in der Standardnormalverteilung 
dnorm(2)
## [1] 0.05399097

Standardmäßig stammen diese Werte aus der Standardnormalverteilung, sie streuen also mit einer Standardabweichung von \(s=1\) um den Mittelwert \(\bar{x}=0\).

Möchte man dies ändern, können der Funktion entsprechende Werte für Mittelwert und Standardabweichung übergeben werden:

# Wahrscheinlichkeitsdichte für x=4 
# aus einer Verteilung mit Mittelwert 8 und Standardabweichung 2 
dnorm(4, mean=8, sd=2)
## [1] 0.02699548

Die Werte der Verteilungsfunktion lassen sich mit pnorm() berechnen. Die Funktion gibt die Wahrscheinlichkeit an, dass ein Zufallsvariable einen Wert von \(\le x\) (= “höchstens\(x\)) annimmt.

# Wahrscheinlichkeit dass Wert kleiner-gleich 2 
# in Standardnormalverteilung 
pnorm(2)
## [1] 0.9772499

Für andere Normalverteilungen ändert sich der Befehl entsprechend:

# Wahrscheinlichkeit dass Wert kleiner-gleich 8 
# in Normalverteilung mit xquer=12 und s=3 
pnorm(8, mean=12, s=3)
## [1] 0.09121122

Quantile lassen sich mit der Funktion qnorm() berechnen. Quantile stellen Grenzen dar, die ein zufälliger Wert mit einer vorgegebenen Wahrscheinlichkeit nicht überschreiten wird. Wenn das 95%-Quantil beispielsweise den Wert \(5\) hat, wird eine zufällig gezogene Zahl mit 95% Sicherheit kleiner als \(5\) sein.

# Grenze des 95% Quantils 
# in Standardnormalverteilung 
qnorm(p=0.95)
## [1] 1.644854

Auch qnorm() können Werte für andere Normalverteilungen übergeben werden.

# Grenze des 95% Quantils
# in Normalverteilung mit xquer=9 und sd=5
qnorm(p=0.95, mean=9, sd=5)
## [1] 17.22427

Mit rnorm() lassen sich normalverteilte Zufallswerte erzeugen:

# erzeuge "zufällig" 10 Werte # aus der Standardnormalverteilung
rnorm(10)
##  [1] -0.9016146  0.1455303  1.5766713 -1.0204963  0.8043461  0.0641912
##  [7] -0.5669779 -0.3892737  0.2117277  0.1366832

Auch mit rnorm() können wir andere Normalverteilungen für unsere Zufallszahlen angeben:

# erzeuge "zufällig" 10 normalverteilte Werte 
# mit Mittelwert 8 und Standardabweichung 2 
rnorm(10, mean=8, sd=2)
##  [1] 10.121712 11.748031  7.306655 10.801588  4.601579  7.084925  8.725928
##  [8]  8.966709  5.502712 10.030013


Plot-Beispiele

# erzeuge Werte von -3 bis 6 
x <- seq(-3,6, by=0.005) 
# übergebe in ein data.frame 
df <- data.frame(x) 

# ggplot erstellen 
library(ggplot2)
p <- ggplot(data=df, aes(x)) + xlim(-3,6) + ylim(0, 0.8) + xlab("x") +
      ylab("Dichtefunktion") + ggtitle("Normalverteilungen") 
p +
      stat_function(fun=dnorm, args=(c(mean=0,sd=1)), colour="black")+
      annotate(geom="text", x=0, y=0.42, label="N(0;1)", color="black")+
      stat_function(fun=dnorm, args=(c(mean=2,sd=0.5)), colour="blue") +
      annotate(geom="text", x=3, y=0.6, label="N(2;0.5)", color="blue")+
      stat_function(fun=dnorm, args=(c(mean=2,sd=2)), colour="darkorchid") +
      annotate(geom="text", x=5, y=0.1, label="N(2;2)",
      color="darkorchid")

Für weitere Plot-Beispiele zur Normalverteilung siehe Abschnitt 9.2.1.

4.14.2 t-Verteilung

Die “kleine Schwester” der Standardnormalverteilung ist die Student-t-Verteilung (oder einfach kurz t-Verteilung). Für sie stehen die selben Funktionstypen zur Verfügung wie für die Normalverteilung (siehe Abschnitt 4.14.1). Diese heissen entsprechend dt(), pt(), qt() und rt() und funktionieren genau wie ihre Pendants der Standardnormalverteilung. Jedoch muss ihnen noch die Anzahl der Freiheitsgrade (\(df\)) übergeben werden:

# Wahrscheinlichkeitsdichte für x=2 
# in der t-Verteilung mit 4 Freiheitsgraden 
dt(2, df=4)
## [1] 0.06629126
# Wahrscheinlichkeit dass Wert kleiner-gleich 2 
# in der t-Verteilung mit 3 Freiheitsgraden 
pt(2, df=3)
## [1] 0.930337
# Grenze des 95% Quantils # in der t-Verteilung mit 3 Freiheitsgraden
qt(p=0.95, df=3)
## [1] 2.353363
# erzeuge "zufällig" 10 Werte 
# aus der t-Verteilung mit 13 Freiheitsgraden 
rt(10, df=13)
##  [1]  0.29679996 -0.40979984  1.35593223 -1.18449926 -1.17524481  0.04829626
##  [7]  0.90598707  0.16680705 -0.80428860 -0.99651708

Möchte man die t-Verteilung plotten, kann das mit ggplot (siehe Kapitel 8.4) so erfolgen.

# Erzeuge x-werte 
df <- data.frame(x=seq(-3,3, by=0.005))

# Grundlegene Plotangaben 
p <- ggplot(data=df, aes(x)) + 
  # begrenze die Achsen 
  xlim(-3,3) + ylim(0, 0.4) + 
  # Achsen-Titel 
  xlab("x") +   ylab("Dichtefunktion") + 
  # Plot-Titel 
  ggtitle("t-Verteilungen", subtitle = "nach Freiheitsgraden")

# t-Verteilung plotten 
p + stat_function(fun=dt, args=list(df=1), col="black") + 
  # Textfeld hinzufügen 
  annotate(geom="text", x=0, y=0.25, label="df=1", color="black")

Für weitere Plot-Beispiele zur Normalverteilung siehe Abschnitt 9.2.2.

4.14.3 \(\chi^2\)-Verteilung

Die \(\chi^2\)-Verteilung ist mit den oben beschriebenen Funktionen in R implementiert. Diese heissen entsprechend dchisq(), pchisq(), qchisq() und rchisq() und funktionieren genau wie ihre Pendants der Standardnormalverteilung. Jedoch muss ihnen (wie bei der t-Verteilung) noch die Anzahl der Freiheitsgrade (\(df\)) übergeben werden:

# Wahrscheinlichkeitsdichte für x=2
# in der Chi^2-Verteilung mit 4 Freiheitsgraden
dchisq(2, df=4)
## [1] 0.1839397

Möchte man die \(\chi^2\)-Verteilung plotten, kann das mit ggplot (siehe Kapitel 8.4) so erfolgen.

# Erzeuge x-werte
x=seq(0,25, by=0.005)
df <- data.frame(  x,
  df01 = dchisq(x, df=1), 
  df05 = dchisq(x, df=5),
  df10 = dchisq(x, df=10),
  df15 = dchisq(x, df=15)
)

# erzeuge long-table
df <- pivot_longer(df, cols=c(df01, df05, df10, df15))

p <- ggplot(data=df, aes(x, value, fill=name)) +
  xlim(0,25) + ylim(0, 0.2) +
  xlab("x") + ylab("Dichtefunktion") +
  ggtitle("Chi^2-Verteilungen", subtitle = "nach Freiheitsgraden")
p + geom_line(aes(col=name,linetype=name))+
labs(col="Freiheitsgrade",linetype="")

Für weitere Plot-Beispiele zur \(\chi^2\)-Verteilung siehe Abschnitt 9.2.3.


  1. Isfort, M; Rottländer, R; Weidner, F; Gehlen, D, Hylla, J, Tucman, D (2018): Pflege-Thermometer 2018. Eine bundesweite Befragung von Leitungskräften zur Situation der Pflege und Patientenversorgung in der stationären Langzeitpflege in Deutschland, Deutsches Institut für angewandte Pflegeforschung e.V. (DIP), Köln, https://www.dip.de S.31↩︎