Difference between revisions of "Grundlagen in R"
From DHVLab
StSchneider (talk | contribs) (→Datentypen) |
StSchneider (talk | contribs) (→Datenstrukturen) |
||
Line 122: | Line 122: | ||
== Datenstrukturen == | == Datenstrukturen == | ||
+ | Ein Level über den Datentypen liegen die Datenstrukturen: ein- bis mehrdimensionale Beschreibungen über die (der Name verrät es bereits) Struktur der Daten. Sie nehmen also Ihre bisherigen einzelnen Objekte und bündeln sie – in Vektoren (<code>vector</code>), Matrizen (<code>matrix</code>), Dataframes (<code>data.frame</code>) oder Listen (<code>list</code>). Jede Struktur besitzt die grundlegende Eigenschaft <code>length</code>. In mindestens zweidimensionalen Strukturen kommen weitere Eigenschaften hinzu, die über die Funktion <code>attributes</code> ermittelt werden können. Die Unterschiede und Merkmale der Strukturen seien im Folgenden erläutert. | ||
+ | |||
+ | === Vektoren === | ||
+ | Die einfachste Datenstruktur in R, den Vektor, kennen Sie bereits, ohne es zu wissen. Denn alle Objekte, die nur einen Wert beinhalten, sind Vektoren der Länge 1. Stellen Sie sich einen Vektor jedoch nicht im schulmathematischen oder abstrakten Sinne vor, sondern beispielsweise als Stapel von Büchern, deren Titel Sie alphabetisch notieren. Die entstandene Liste würde bei Eingabe in R schließlich einen Vektor ergeben. Betrachten Sie zunächst allerdings noch einmal folgenden ''Output'': | ||
+ | |||
+ | <syntaxhighlight lang="rsplus"> | ||
+ | x <- "Bild" | ||
+ | x | ||
+ | ## [1] "Bild" | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Vor der Zeichenkette <code>"Bild"</code> steht die Zahl <code>1</code> in eckigen Klammern: Es handelt sich um die Position des Wertes <code>"Bild"</code> im Objekt <code>x</code>. Und dieses Objekt <code>x</code> ist hier ein Vektor. Eine Information über die Länge eines Objekts (also die Anzahl der in einem Objekt enthaltenen Elemente) erhalten Sie mit der Funktion <code>length</code>: | ||
+ | |||
+ | <syntaxhighlight lang="rsplus"> | ||
+ | length(x) | ||
+ | ## [1] 1 | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Nun gehen wir einen Schritt weiter und legen einen Vektor an, der mehr als ein Element enthält: | ||
+ | |||
+ | <syntaxhighlight lang="rsplus"> | ||
+ | x <- c(2,3,5,7) | ||
+ | x | ||
+ | ## [1] 2 3 5 7 | ||
+ | |||
+ | length(x) | ||
+ | ## [1] 4 | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Betrachten Sie die erste Zeile und insbesondere den Befehl <code>c(2,3,5,7)</code>: Die Funktion <code>c</code> (kurz für ''combine'' oder ''concatenate'') legt mehrere durch Kommata getrennte Werte (hier die Zahlen <code>2,3,5,7</code>) als Vektor ab (hier in das Objekt <code>x</code>). Anschließend geben Sie den Inhalt von <code>x</code> aus. Es fällt auf: Die Markierung <code>[1]</code> wird für alle folgenden Werte nicht weitergeführt – sie steht ausschließlich am Anfang jeder Zeile des ''Outputs''. Die Länge des Vektors wird daraufhin geprüft: <code>x</code> enthält (wenig überraschend) vier Elemente. | ||
+ | |||
+ | Wenn Sie den Wert eines bestimmten Elements in einem Vektor extrahieren möchten, übergeben Sie die Position des besagten Elements nach dem Namen des Vektors in eckigen Klammern (hier das Element mit Index 3): | ||
+ | |||
+ | <syntaxhighlight lang="rsplus"> | ||
+ | x[3] | ||
+ | ## [1] 5 | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Mehrere Elemente können ebenso angesprochen werden. Handelt es sich um in einem Vektor aufeinander folgende Werte, verknüpfen Sie Start- und Endindex mit einem Doppelpunkt (hier die Elemente mit Index 2 bis 4): | ||
+ | |||
+ | <syntaxhighlight lang="rsplus"> | ||
+ | x[2:4] | ||
+ | ## [1] 3 5 7 | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Handelt es sich hingegen um Elemente, die in einem Vektor nicht aufeinander folgen, müssen Sie dem Vektor einen weiteren Vektor mit den entsprechenden Indizes übergeben (hier die Elemente mit Index 2 und 4): | ||
+ | |||
+ | <syntaxhighlight lang="rsplus"> | ||
+ | x[c(2,4)] | ||
+ | ## [1] 3 7 | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Warum dies nur scheinbar umständlich möglich ist (und nicht beispielsweise über den Befehl <code>x[2,4]</code> abgedeckt wird), bemerken Sie in Kürze, wenn Sie zweidimensionale Strukturen kennenlernen. Die Selektion einzelner Elemente mag Ihnen übrigens trivial und in diesem Stadium unnütz erscheinen – je mehr Elemente ein Vektor (oder eine Datenstruktur allgemein) allerdings besitzt, umso schwerer wird es Ihnen fallen, ein für Sie relevantes Element im betreffenden Vektor zu finden. | ||
+ | |||
+ | Eine weitere und überaus relevante Eigenschaft dieser Datenstruktur: Ein Vektor kann nur Elemente desselben Datentyps aufnehmen. Probieren Sie folgendes: | ||
+ | |||
+ | <syntaxhighlight lang="rsplus"> | ||
+ | x <- c("Bild", 3) | ||
+ | x | ||
+ | ## [1] "Bild" "3" | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Da R die Zeichenkette <code>"Bild"</code> schlecht zu einer Zahl umfunktionieren kann, wird der Datentyp der Zahl <code>3</code> geändert – in das Zeichen <code>3</code>. Den Datentyp aller in einem Vektor enthaltenen Elemente erhalten Sie wie bislang über die Funktion <code>mode</code>: | ||
+ | |||
+ | <syntaxhighlight lang="rsplus"> | ||
+ | mode(x) | ||
+ | ## [1] "character" | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Ein Vektor kann ferner vorne und hinten durch beliebig viele weitere Elemente ergänzt werden: | ||
+ | |||
+ | <syntaxhighlight lang="rsplus"> | ||
+ | x <- c(2,3,5,7) | ||
+ | x | ||
+ | ## [1] 2 3 5 7 | ||
+ | |||
+ | x <- c("Bild", x, 3) | ||
+ | x | ||
+ | ## [1] "Bild" "2" "3" "5" "7" "3" | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Kurzum können wir daher sagen: Ein Vektor ist eine geordnete Sammlung von Objekten mit gleichem Datentyp. | ||
+ | |||
+ | === Matrizen === | ||
+ | Gehen wir einen Schritt weiter: Statt eindimensionalen Vektoren widmen wir uns jetzt zweidimensionalen Matrizen. Zweidimensional heißt im anschaulichen Sinne nichts anderes als: Es wird eine Tabelle mit Zeilen (waagerecht) und Spalten (senkrecht) aufgespannt. In Code ausgedrückt bedeutet dies: | ||
+ | |||
+ | <syntaxhighlight lang="rsplus"> | ||
+ | x <- matrix(data=5:10, nrow=3, ncol=2) | ||
+ | x | ||
+ | |||
+ | ## [,1] [,2] | ||
+ | ## [1,] 5 8 | ||
+ | ## [2,] 6 9 | ||
+ | ## [3,] 7 10 | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Mit der Funktion <code>matrix</code> teilen Sie R mit, eine Matrix zu erstellen, die in diesem Fall mit den Werten 5 bis 10 (<code>data=5:10</code>) über drei Zeilen (<code>nrow=3</code>) und zwei Spalten (<code>ncol=2</code>) bestückt werden soll. Die Argumente der Funktion werden durch Kommata abgetrennt. Die Reihenfolge der Argumente spielt im Grunde keine Rolle, wenn Sie die entspechenden Argumente nicht abkürzen (also <code>matrix(5:10, 3, 2)</code> statt <code>matrix(data=5:10, nrow=3, ncol=2)</code> schreiben). | ||
+ | |||
+ | Der ''Output'' macht Ihnen auch deutlich: Die Daten, bestehend aus den Zahlen 5 bis 10, füllen die Matrix spaltenweise auf – zunächst wird die erste Spalte vervollständigt (im ''Output'' markiert durch <code>[,1]</code>), dann die zweite Spalte (<code>[,2]</code>). Diese Voreinstellung ändern Sie, indem Sie der Funktion <code>matrix</code> das Argument <code>byrow=TRUE</code> übergeben: | ||
+ | |||
+ | <syntaxhighlight lang="rsplus"> | ||
+ | x <- matrix(data=5:10, nrow=3, ncol=2, byrow=TRUE) | ||
+ | x | ||
+ | |||
+ | ## [,1] [,2] | ||
+ | ## [1,] 5 6 | ||
+ | ## [2,] 7 8 | ||
+ | ## [3,] 9 10 | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Eine Matrix hat zudem immer auch eine Dimension, welche über die Funktion <code>dim</code> ausgegeben werden kann: | ||
+ | |||
+ | <syntaxhighlight lang="rsplus"> | ||
+ | dim(x) | ||
+ | ## [1] 3 2 | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Die Dimension der Matrix <code>x</code> besteht aus der Anzahl der Zeilen an Position 1 (<code>3</code>) und der Anzahl der Spalten an Position 2 (<code>2</code>). Die Länge derselben Matrix bildet sich folglich aus der Multiplikation der Anzahl der Zeilen mit der Anzahl der Spalten: | ||
+ | |||
+ | <syntaxhighlight lang="rsplus"> | ||
+ | length(x) | ||
+ | ## [1] 6 | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Was passiert nun aber, wenn sich die Anzahl der Elemente, die in eine Matrix eingefügt werden sollen, von der Dimension der aufzuspannenden Matrix unterscheidet? Sehen Sie selbst: | ||
+ | |||
+ | <syntaxhighlight lang="rsplus"> | ||
+ | matrix(data=5:11, nrow=3, ncol=2) | ||
+ | |||
+ | ## [,1] [,2] | ||
+ | ## [1,] 5 8 | ||
+ | ## [2,] 6 9 | ||
+ | ## [3,] 7 10 | ||
+ | |||
+ | ## Warning in matrix(5:11, nrow = 3, ncol = 2): data length [7] is not a sub-multiple or multiple of the number of rows [3] | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Im vorhergehenden Fall versuchen Sie, einen Vektor der Länge 7 (die Zahlen 5 bis 11) in einer Matrix der Länge 6 unterzubringen: R gibt eine Warnung zurück (''Warning'') und ignoriert das Element an Position 7 des Vektors (die Zahl <code>11</code>), da 7 kein Vielfaches von 3 (der Anzahl der Zeilen) ist – es werden wie bislang nur die Werte 5 bis 10 an die Matrix übergeben. | ||
+ | |||
+ | Für den Fall, dass die Anzahl der einzufügenden Elemente die Länge der Matrix unterschreitet, ergibt sich folgendes Bild: | ||
+ | |||
+ | <syntaxhighlight lang="rsplus"> | ||
+ | matrix(data=5:9, nrow=3, ncol=2) | ||
+ | |||
+ | ## [,1] [,2] | ||
+ | ## [1,] 5 8 | ||
+ | ## [2,] 6 9 | ||
+ | ## [3,] 7 5 | ||
+ | |||
+ | ## Warning in matrix(5:9, nrow = 3, ncol = 2): data length [5] is not a sub-multiple or multiple of the number of rows [3] | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Das erste Element des Vektors (die Zahl <code>5</code>) wird in letzterem Beispiel ''recycelt'' – es tritt in Ermangelung eines weiteren Elements an Position 10 des Vektors. Damit ist das Resultat identisch zu folgendem Befehl: | ||
+ | |||
+ | <syntaxhighlight lang="rsplus"> | ||
+ | matrix(data=c(5:9,5), nrow=3, ncol=2) | ||
+ | |||
+ | ## [,1] [,2] | ||
+ | ## [1,] 5 8 | ||
+ | ## [2,] 6 9 | ||
+ | ## [3,] 7 5 | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Kommen wir zu der Selektion eines oder mehrerer Elemente in einer Matrix. Die Struktur lässt sich im zweidimensionalen Fall mit folgendem Schema beschreiben: <code>matrix[zeile,spalte]</code>. Das Element in der zweiten Zeile der ersten Spalte erhalten Sie daher mit dem Befehl: | ||
+ | |||
+ | <syntaxhighlight lang="rsplus"> | ||
+ | x[2,1] | ||
+ | ## [1] 7 | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Alle Regelungen für die Indexierung eines Elements in einem Vektor gelten analog auf Zeilen- und Spaltenebene in einer Matrix. Möchten Sie die Werte einer bestimmten Spalte extrahieren, müssen Sie keine Angabe über die benötigten Zeilen treffen: | ||
+ | |||
+ | <syntaxhighlight lang="rsplus"> | ||
+ | x[,1] | ||
+ | ## [1] 5 7 9 | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Der Befehl gibt Ihnen die erste Spalte der Matrix <code>x</code> zurück. Wenn Sie Interesse an den Werten der zweiten Zeile haben, gehen Sie wie folgt vor: | ||
+ | |||
+ | <syntaxhighlight lang="rsplus"> | ||
+ | x[2,] | ||
+ | ## [1] 7 8 | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Um den Umgang zu erleichtern, ist es zudem möglich, den Zeilen und Spalten Namen zuzuweisen. Entweder spezifizieren Sie diese zusätzlichen Informationen gleich bei Anlage der Matrix: | ||
+ | |||
+ | <syntaxhighlight lang="rsplus"> | ||
+ | x <- matrix(data=5:10, nrow=3, ncol=2, dimnames=list(c("Zeile1", "Zeile2", "Zeile3"), c("Spalte1", "Spalte2"))) | ||
+ | x | ||
+ | |||
+ | ## Spalte1 Spalte2 | ||
+ | ## Zeile1 5 8 | ||
+ | ## Zeile2 6 9 | ||
+ | ## Zeile3 7 10 | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Oder im Nachhinein mit der Funktion <code>dimnames</code>: | ||
+ | |||
+ | <syntaxhighlight lang="rsplus"> | ||
+ | x <- matrix(data=5:10, nrow=3, ncol=2) | ||
+ | dimnames(x) <- list(c("Zeile1", "Zeile2", "Zeile3"), c("Spalte1", "Spalte2")) | ||
+ | x | ||
+ | |||
+ | ## Spalte1 Spalte2 | ||
+ | ## Zeile1 5 8 | ||
+ | ## Zeile2 6 9 | ||
+ | ## Zeile3 7 10 | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | In beiden Fällen übergeben Sie <code>dimnames</code> eine Liste, die aus einem Vektor mit den Zeilennamen und einem Vektor mit den Spaltennamen besteht. Weiteres zum Thema Listen finden Sie am Ende dieses Abschnitts. Über die vergebenen Namen können Sie ebenso auf die Zeilen und Spalten zugreifen: | ||
+ | |||
+ | <syntaxhighlight lang="rsplus"> | ||
+ | x["Zeile3",] | ||
+ | ## Spalte1 Spalte2 | ||
+ | ## 7 10 | ||
+ | |||
+ | x[,"Spalte2"] | ||
+ | ## Zeile1 Zeile2 Zeile3 | ||
+ | ## 8 9 10 | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | Eine Matrix ist somit vergleichbar mit einem zweidimensionalen Vektor und nimmt wie dieser nur Objekte gleichen Datentyps auf. | ||
+ | |||
+ | === Dataframes === | ||
+ | ''Coming Soon.'' | ||
+ | |||
+ | === Listen === | ||
''Coming Soon.'' | ''Coming Soon.'' | ||
Revision as of 11:12, 10 May 2016
R ist eine objektorientierte, funktionale Programmiersprache. Oder um es in den Worten von John Chambers, Entwickler der Software S und ihres Nachfolgers R, zu sagen: „Alles, was existiert, ist ein Objekt. Alles, was passiert, ist ein Funktionsaufruf.“ [1] Ob Sie also mit einer Zahl arbeiten oder mit einer Zeichenkette, ist im übergeordneten Sinne irrelevant – eine Zahl ist ebenso ein Objekt wie eine Zeichenkette. Darauf aufbauend ist eine Feinabstufung möglich: Bei einem Objekt kann es sich um eine Funktion handeln – oder um Daten. Daten wiederum erlauben eine Untergliederung in Datentypen und Datenstrukturen, die beide jeweils weitere Verästelungen nach sich ziehen (Abbildung 1).
Contents
Objekte und Zuweisungen
Ein Objekt auf Datenebene ist demzufolge nichts anderes als ein Auffangbehälter, der weitere Objekte unterschiedlichsten Typs und unterschiedlichster Struktur beinhalten kann. [A 1] Für den Anfang stellen Sie sich jedoch erst einmal ein Objekt vor, das aus einem einzigen Wert (beispielsweise der Zahl 5
) besteht. Möchten Sie dieses Objekt später für weitere Berechnungen verwenden, ohne permanent 5
eingeben zu müssen, können Sie ihm einen Namen zuweisen:
x <- 5
x
## [1] 5
Umgangssprachlich ausgedrückt teilen Sie R mit: Nehme den Namen x
und übergebe ihm (<-
) die Zahl 5
. Das Objekt namens x
enthält nun den Wert 5
. Wie Sie durch Eingabe des vorhergehenden Codes vielleicht schon bemerkt haben, gibt Ihnen R den Inhalt eines Objekts nicht automatisch zurück – Sie müssen den Namen des Objekts in die Konsole eingeben und ausführen (hier x
in Zeile 2). Im Prinzip speichern Sie ein Objekt durch Zuweisung eines Namens also immer nach folgendem Schema ab: name <- objekt
.
Namen müssen folgenden Vorschriften genügen:
- Sie dürfen keine Leerzeichen enthalten.
- Sie dürfen nicht mit einer Zahl beginnen (
1x
ist nicht erlaubt). - Auf Namen, die mit einem Punkt beginnen, darf keine Zahl folgen (
.1x
führt zu einer Fehlermeldung,.x1
verursacht jedoch keine Probleme). - Sie dürfen nicht von R vorbelegt sein. [A 2]
Bis auf diese Ausnahmen sind alle Buchstaben [A 3], alle Zahlen und die Zeichen _
(Unterstrich) und .
(Punkt) erlaubt. Eine weitere Anmerkung: R unterscheidet grundsätzlich zwischen Groß- und Kleinschreibung. Ein Objekt namens A1
ist daher nicht identisch mit einem Objekt namens a1
. In jedem Fall ist es jedoch empfehlenswert, sich für eine Konvention bei der Namenszuweisung zu entscheiden und diese im gesamten Skript einzuhalten. Sie können beispielsweise eine dieser Regeln verwenden:
- Namen bestehen nur aus Kleinbuchstaben. Bei mehreren Wörtern wird kein Trennzeichen verwendet (
digitalhumanities
). - Namen bestehen nur aus Kleinbuchstaben. Als Trennzeichen wird ein Punkt (
digital.humanities
) oder Unterstrich (digital_humanities
) verwendet. - Namen mit einem Wort bestehen aus Kleinbuchstaben. Bei Namen mit mehreren Wörtern wird das erste Wort klein geschrieben, die restlichen Wörter leiten mit einem Großbuchstaben ein (
digitalHumanities
). - Namen bestehen aus Klein- und Großbuchstaben. Ein Wort wird durch einen Großbuchstaben eingeleitet (
DigitalHumanities
).
Datentypen
Ein Objekt lässt sich auf elementarster Ebene näher spezifizieren – über seinen Datentyp. Die drei wichtigsten Datentypen in R lauten: numeric
, character
und logical
. Handelt es sich bei Ihrem Objekt um eine Zahl, ordnen Sie den entsprechenden Datentyp also vermutlich bereits intuitiv richtig zu: numeric
. Auch die weiteren zwei Typen sind annähernd selbsterklärend: character
ist der Container für Zeichen (beispielsweise Buchstaben), logical
der Container für Wahrheitswerte (TRUE
, FALSE
) [A 4].
Eine komprimierte Fassung finden Sie in nachfolgender Tabelle:
Beschreibung | Beispiel | Datentyp |
---|---|---|
Ganze und reelle Zahlen | 3.17 |
numeric
|
Zeichen und Zeichenketten | "Bild" |
character
|
Wahrheitswerte | TRUE , FALSE |
logical
|
Zwei Beispiele dürften Sie zurecht irritieren: Zum einen wird ein Punkt als Dezimaltrennzeichen verwendet, zum anderen ist das Wort Bild
von Anführungszeichen umschlossen ("..."
). Diese Fälle betrachten wir nun genauer. Zunächst geben Sie die Zahl 3,17
in üblicher Notation mit Komma als Dezimaltrennzeichen in die Konsole ein und führen die Zeile aus:
3,17
## Error: unexpected ',' in "3,
Sie merken: RStudio gibt statt eines ordnungsgemäßen Outputs eine (durchaus kryptische) Fehlermeldung (Error) zurück. Um diese zu verstehen, müssen Sie sich bewusst machen, dass die Verwendung des Kommas in R vorbelegt ist: Das Zeichen kann Objekte eines Vektors ebenso abtrennen wie Argumente einer Funktion (mehr dazu in den Abschnitten Datenstrukturen und Funktionen). Reelle Zahlen (Zahlen mit Nachkommastellen) benötigen daher in R einen Punkt statt eines Kommas als Dezimaltrennzeichen.
Sehen Sie sich nun das zweite Beispiele an, indem Sie Bild
in die Konsole eingeben und die Zeile ausführen:
Bild
## Error in eval(expr, envir, enclos): Objekt 'Bild' nicht gefunden
Auch hier zeigt uns RStudio einen Error an, dieses Mal jedoch mit einer konkreteren weiterführenden Information: Objekt 'Bild' nicht gefunden
. Die Erklärung ist simpel: Ohne Anführungszeichen erwartet R beim Ausführen der Zeile ein Objekt namens
Bild
, das im Workspace bereits existiert – von Ihnen also, wie im Abschnitt Objekte und Zuweisungen beschrieben, erzeugt wurde. Achten Sie daher immer darauf, einen Wert mit Anführungszeichen ("Bild"
oder 'Bild'
) zu umschließen, wenn es sich bei ihm um Buchstaben oder eine Zeichenkette handelt und R diese als solche erkennen soll.
Den Datentyp eines Objekts können Sie infolge über zwei Funktionen bestimmen: mode
und is.datentyp
(also is.numeric
, is.character
oder is.logical
). Der Unterschied: mode
gibt den genauen Datentyp zurück – is.datentyp
prüft lediglich, ob es sich um den von Ihnen spezifizierten Datentyp handelt und spuckt einen Wahrheitswert aus. Sehen Sie sich dazu beispielhaft folgenden Code an:
x <- 5
mode(x)
## [1] "numeric"
is.character(x)
## [1] FALSE
Laut mode
ist das Objekt x
vom Typ numeric
. Eine Prüfung, ob es sich bei x
um ein Objekt des Typs character
handelt, resultiert folgerichtig in der Rückgabe FALSE
. Aber Achtung:
x <- "5"
mode(x)
## [1] "character"
is.character(x)
## [1] TRUE
Sie weisen x
im vorhergehenden Code durch die umschließenden Anführungszeichen nicht mehr die Zahl sondern das Zeichen 5
zu – arithmetische Operationen wie im Abschnitt Operatoren können mit diesem Objekt nicht mehr durchgeführt werden. Eine nachträgliche Änderung des Datentyps ist über die Funktion as.datentyp
möglich:
x <- "5"
mode(x)
## [1] "character"
x <- as.numeric(x)
mode(x)
## [1] "numeric"
Das Objekt x
enthält zunächst wie bislang das Zeichen 5
, dessen Datentyp Sie über mode
testen. Im Anschluss entscheiden Sie sich mit dem Aufruf as.numeric(x)
, den Typ in numeric
umzuwandeln und das Ergebnis wieder in einem Objekt namens x
abzulegen. Die erneute Eingabe von mode
sagt Ihnen daraufhin: Der Datentyp des Objekts x
ist numeric
.
Die Umwandlung einer Zahl oder eines Zeichens in einen Wahrheitswert funktioniert hingegen nicht ohne Weiteres:
x <- "5"
x <- as.logical(x)
x
## [1] NA
Das Objekt x
enthält nach der Änderung des Datentyps die Angabe NA
– statt eine Umwandlung des Zeichens 5
in einen Wahrheitswert vorzunehmen, hinterlegt R im Objekt x
die Konstante für einen fehlenden Wert, NA
(Not Available). NA
kann in jeden beliebigen Datentyp umgewandelt werden, ohne seine Form zu verlieren:
x <- NA
as.numeric(x)
## [1] NA
as.character(x)
## [1] NA
as.logical(x)
## [1] NA
Datenstrukturen
Ein Level über den Datentypen liegen die Datenstrukturen: ein- bis mehrdimensionale Beschreibungen über die (der Name verrät es bereits) Struktur der Daten. Sie nehmen also Ihre bisherigen einzelnen Objekte und bündeln sie – in Vektoren (vector
), Matrizen (matrix
), Dataframes (data.frame
) oder Listen (list
). Jede Struktur besitzt die grundlegende Eigenschaft length
. In mindestens zweidimensionalen Strukturen kommen weitere Eigenschaften hinzu, die über die Funktion attributes
ermittelt werden können. Die Unterschiede und Merkmale der Strukturen seien im Folgenden erläutert.
Vektoren
Die einfachste Datenstruktur in R, den Vektor, kennen Sie bereits, ohne es zu wissen. Denn alle Objekte, die nur einen Wert beinhalten, sind Vektoren der Länge 1. Stellen Sie sich einen Vektor jedoch nicht im schulmathematischen oder abstrakten Sinne vor, sondern beispielsweise als Stapel von Büchern, deren Titel Sie alphabetisch notieren. Die entstandene Liste würde bei Eingabe in R schließlich einen Vektor ergeben. Betrachten Sie zunächst allerdings noch einmal folgenden Output:
x <- "Bild"
x
## [1] "Bild"
Vor der Zeichenkette "Bild"
steht die Zahl 1
in eckigen Klammern: Es handelt sich um die Position des Wertes "Bild"
im Objekt x
. Und dieses Objekt x
ist hier ein Vektor. Eine Information über die Länge eines Objekts (also die Anzahl der in einem Objekt enthaltenen Elemente) erhalten Sie mit der Funktion length
:
length(x)
## [1] 1
Nun gehen wir einen Schritt weiter und legen einen Vektor an, der mehr als ein Element enthält:
x <- c(2,3,5,7)
x
## [1] 2 3 5 7
length(x)
## [1] 4
Betrachten Sie die erste Zeile und insbesondere den Befehl c(2,3,5,7)
: Die Funktion c
(kurz für combine oder concatenate) legt mehrere durch Kommata getrennte Werte (hier die Zahlen 2,3,5,7
) als Vektor ab (hier in das Objekt x
). Anschließend geben Sie den Inhalt von x
aus. Es fällt auf: Die Markierung [1]
wird für alle folgenden Werte nicht weitergeführt – sie steht ausschließlich am Anfang jeder Zeile des Outputs. Die Länge des Vektors wird daraufhin geprüft: x
enthält (wenig überraschend) vier Elemente.
Wenn Sie den Wert eines bestimmten Elements in einem Vektor extrahieren möchten, übergeben Sie die Position des besagten Elements nach dem Namen des Vektors in eckigen Klammern (hier das Element mit Index 3):
x[3]
## [1] 5
Mehrere Elemente können ebenso angesprochen werden. Handelt es sich um in einem Vektor aufeinander folgende Werte, verknüpfen Sie Start- und Endindex mit einem Doppelpunkt (hier die Elemente mit Index 2 bis 4):
x[2:4]
## [1] 3 5 7
Handelt es sich hingegen um Elemente, die in einem Vektor nicht aufeinander folgen, müssen Sie dem Vektor einen weiteren Vektor mit den entsprechenden Indizes übergeben (hier die Elemente mit Index 2 und 4):
x[c(2,4)]
## [1] 3 7
Warum dies nur scheinbar umständlich möglich ist (und nicht beispielsweise über den Befehl x[2,4]
abgedeckt wird), bemerken Sie in Kürze, wenn Sie zweidimensionale Strukturen kennenlernen. Die Selektion einzelner Elemente mag Ihnen übrigens trivial und in diesem Stadium unnütz erscheinen – je mehr Elemente ein Vektor (oder eine Datenstruktur allgemein) allerdings besitzt, umso schwerer wird es Ihnen fallen, ein für Sie relevantes Element im betreffenden Vektor zu finden.
Eine weitere und überaus relevante Eigenschaft dieser Datenstruktur: Ein Vektor kann nur Elemente desselben Datentyps aufnehmen. Probieren Sie folgendes:
x <- c("Bild", 3)
x
## [1] "Bild" "3"
Da R die Zeichenkette "Bild"
schlecht zu einer Zahl umfunktionieren kann, wird der Datentyp der Zahl 3
geändert – in das Zeichen 3
. Den Datentyp aller in einem Vektor enthaltenen Elemente erhalten Sie wie bislang über die Funktion mode
:
mode(x)
## [1] "character"
Ein Vektor kann ferner vorne und hinten durch beliebig viele weitere Elemente ergänzt werden:
x <- c(2,3,5,7)
x
## [1] 2 3 5 7
x <- c("Bild", x, 3)
x
## [1] "Bild" "2" "3" "5" "7" "3"
Kurzum können wir daher sagen: Ein Vektor ist eine geordnete Sammlung von Objekten mit gleichem Datentyp.
Matrizen
Gehen wir einen Schritt weiter: Statt eindimensionalen Vektoren widmen wir uns jetzt zweidimensionalen Matrizen. Zweidimensional heißt im anschaulichen Sinne nichts anderes als: Es wird eine Tabelle mit Zeilen (waagerecht) und Spalten (senkrecht) aufgespannt. In Code ausgedrückt bedeutet dies:
x <- matrix(data=5:10, nrow=3, ncol=2)
x
## [,1] [,2]
## [1,] 5 8
## [2,] 6 9
## [3,] 7 10
Mit der Funktion matrix
teilen Sie R mit, eine Matrix zu erstellen, die in diesem Fall mit den Werten 5 bis 10 (data=5:10
) über drei Zeilen (nrow=3
) und zwei Spalten (ncol=2
) bestückt werden soll. Die Argumente der Funktion werden durch Kommata abgetrennt. Die Reihenfolge der Argumente spielt im Grunde keine Rolle, wenn Sie die entspechenden Argumente nicht abkürzen (also matrix(5:10, 3, 2)
statt matrix(data=5:10, nrow=3, ncol=2)
schreiben).
Der Output macht Ihnen auch deutlich: Die Daten, bestehend aus den Zahlen 5 bis 10, füllen die Matrix spaltenweise auf – zunächst wird die erste Spalte vervollständigt (im Output markiert durch [,1]
), dann die zweite Spalte ([,2]
). Diese Voreinstellung ändern Sie, indem Sie der Funktion matrix
das Argument byrow=TRUE
übergeben:
x <- matrix(data=5:10, nrow=3, ncol=2, byrow=TRUE)
x
## [,1] [,2]
## [1,] 5 6
## [2,] 7 8
## [3,] 9 10
Eine Matrix hat zudem immer auch eine Dimension, welche über die Funktion dim
ausgegeben werden kann:
dim(x)
## [1] 3 2
Die Dimension der Matrix x
besteht aus der Anzahl der Zeilen an Position 1 (3
) und der Anzahl der Spalten an Position 2 (2
). Die Länge derselben Matrix bildet sich folglich aus der Multiplikation der Anzahl der Zeilen mit der Anzahl der Spalten:
length(x)
## [1] 6
Was passiert nun aber, wenn sich die Anzahl der Elemente, die in eine Matrix eingefügt werden sollen, von der Dimension der aufzuspannenden Matrix unterscheidet? Sehen Sie selbst:
matrix(data=5:11, nrow=3, ncol=2)
## [,1] [,2]
## [1,] 5 8
## [2,] 6 9
## [3,] 7 10
## Warning in matrix(5:11, nrow = 3, ncol = 2): data length [7] is not a sub-multiple or multiple of the number of rows [3]
Im vorhergehenden Fall versuchen Sie, einen Vektor der Länge 7 (die Zahlen 5 bis 11) in einer Matrix der Länge 6 unterzubringen: R gibt eine Warnung zurück (Warning) und ignoriert das Element an Position 7 des Vektors (die Zahl 11
), da 7 kein Vielfaches von 3 (der Anzahl der Zeilen) ist – es werden wie bislang nur die Werte 5 bis 10 an die Matrix übergeben.
Für den Fall, dass die Anzahl der einzufügenden Elemente die Länge der Matrix unterschreitet, ergibt sich folgendes Bild:
matrix(data=5:9, nrow=3, ncol=2)
## [,1] [,2]
## [1,] 5 8
## [2,] 6 9
## [3,] 7 5
## Warning in matrix(5:9, nrow = 3, ncol = 2): data length [5] is not a sub-multiple or multiple of the number of rows [3]
Das erste Element des Vektors (die Zahl 5
) wird in letzterem Beispiel recycelt – es tritt in Ermangelung eines weiteren Elements an Position 10 des Vektors. Damit ist das Resultat identisch zu folgendem Befehl:
matrix(data=c(5:9,5), nrow=3, ncol=2)
## [,1] [,2]
## [1,] 5 8
## [2,] 6 9
## [3,] 7 5
Kommen wir zu der Selektion eines oder mehrerer Elemente in einer Matrix. Die Struktur lässt sich im zweidimensionalen Fall mit folgendem Schema beschreiben: matrix[zeile,spalte]
. Das Element in der zweiten Zeile der ersten Spalte erhalten Sie daher mit dem Befehl:
x[2,1]
## [1] 7
Alle Regelungen für die Indexierung eines Elements in einem Vektor gelten analog auf Zeilen- und Spaltenebene in einer Matrix. Möchten Sie die Werte einer bestimmten Spalte extrahieren, müssen Sie keine Angabe über die benötigten Zeilen treffen:
x[,1]
## [1] 5 7 9
Der Befehl gibt Ihnen die erste Spalte der Matrix x
zurück. Wenn Sie Interesse an den Werten der zweiten Zeile haben, gehen Sie wie folgt vor:
x[2,]
## [1] 7 8
Um den Umgang zu erleichtern, ist es zudem möglich, den Zeilen und Spalten Namen zuzuweisen. Entweder spezifizieren Sie diese zusätzlichen Informationen gleich bei Anlage der Matrix:
x <- matrix(data=5:10, nrow=3, ncol=2, dimnames=list(c("Zeile1", "Zeile2", "Zeile3"), c("Spalte1", "Spalte2")))
x
## Spalte1 Spalte2
## Zeile1 5 8
## Zeile2 6 9
## Zeile3 7 10
Oder im Nachhinein mit der Funktion dimnames
:
x <- matrix(data=5:10, nrow=3, ncol=2)
dimnames(x) <- list(c("Zeile1", "Zeile2", "Zeile3"), c("Spalte1", "Spalte2"))
x
## Spalte1 Spalte2
## Zeile1 5 8
## Zeile2 6 9
## Zeile3 7 10
In beiden Fällen übergeben Sie dimnames
eine Liste, die aus einem Vektor mit den Zeilennamen und einem Vektor mit den Spaltennamen besteht. Weiteres zum Thema Listen finden Sie am Ende dieses Abschnitts. Über die vergebenen Namen können Sie ebenso auf die Zeilen und Spalten zugreifen:
x["Zeile3",]
## Spalte1 Spalte2
## 7 10
x[,"Spalte2"]
## Zeile1 Zeile2 Zeile3
## 8 9 10
Eine Matrix ist somit vergleichbar mit einem zweidimensionalen Vektor und nimmt wie dieser nur Objekte gleichen Datentyps auf.
Dataframes
Coming Soon.
Listen
Coming Soon.
Funktionen
Coming Soon.
Operatoren
Coming Soon.
Anmerkungen
- ↑ Die Rolle der Funktionen sei vorerst außen vor gelassen, eine ausführliche Erklärung dieser finden Sie im Abschnitt Funktionen.
- ↑ Alle reservierten Namen finden Sie unter: https://stat.ethz.ch/R-manual/R-devel/library/base/html/Reserved.html.
- ↑ Sie könnten beispielsweise ein Objekt namens
â
anlegen. Es sei allerdings aus Gründen des guten Stils davon abgeraten, Sonderzeichen zu benutzen. - ↑ Ein Wahrheitswert gibt an, ob eine Aussage wahr oder falsch ist. Die Aussage „Albrecht Dürer war ein Maler“ wäre demnach wahr (
TRUE
).
Einzelnachweise
- ↑ Chambers, John M. (2014): Object-Oriented Programming, Functional Programming and R. In: Statistical Science. 29.2, S. 167-180, URL: http://arxiv.org/pdf/1409.3531