Datenrahmen in R unterteilen
Gerade wenn wir mit großen Datensätzen arbeiten, interessiert uns oft nur ein kleiner Teil daraus für eine bestimmte Analyse. Wie also können wir all die überflüssigen Fremdvariablen und -beobachtungen aussortieren und nur diejenigen extrahieren, die wir tatsächlich benötigen? In diesem Artikel besprechen wir einige Möglichkeiten wie.
Wenn man eine Untermenge aus Daten nimmt, erstellt man ein subset. Die Unterteilung von Daten wird entsprechend auch als subsetting bezeichnet.
Für alle Beispiele nehmen wir den Iris-Daztensatz:
iris <- read.csv(url("https://statistikguru.de/iris.data"), header = TRUE, encoding = "UTF-8")
# Kelchlänge Kelchbreite Blütenblattlänge Blütenblattbreite Gattung
# 1 5.1 3.5 1.4 0.2 Iris-setosa
# 2 4.9 3.0 1.4 0.2 Iris-setosa
# 3 4.7 3.2 1.3 0.2 Iris-setosa
# 4 4.6 3.1 1.5 0.2 Iris-setosa
# 5 5.0 3.6 1.4 0.2 Iris-setosa
# ...
# 146 6.7 3.0 5.2 2.3 Iris-virginica
# 147 6.3 2.5 5.0 1.9 Iris-virginica
# 148 6.5 3.0 5.2 2.0 Iris-virginica
# 149 6.2 3.4 5.4 2.3 Iris-virginica
# 150 5.9 3.0 5.1 1.8 Iris-virginica
Eckige Klammern
Die einfachste Art, einen data.frame
in R zu unterteilen, ist die Verwendung von eckigen Klammern, und zwar so:
iris[x, y]
iris[4, 3]
# 1.5
Hier entspricht x der Zeile (beginnend bei 1, ohne die Kopfzeile) und y der Spalte (auch beginnend bei 1). Bei Aufruf von iris[4, 3]
möchten wir also den Wert aus der 4. Zeile und 3. Spalte (Blütenblattlänge) haben, der in dem Iris-Datensatz dem Wert 1.5 entspricht.
Eckigen Klammern und Vektoren
In den meisten Fällen wollen wir aber nicht nur einen einzigen Wert haben, sondern mehrere. Statt bei x und y einfach nur Zahlen einzugeben, können wir auch Vektoren verwenden:
iris[2:5, 3:4]
# Blütenblattlänge Blütenblattbreite
# 2 1.4 0.2
# 3 1.3 0.2
# 4 1.5 0.2
# 5 1.4 0.2
Das Beispiel funktioniert analog zur ersten Möglichkeit, nur, dass wir jetzt mehrere Spalten und Zeilen zurückbekommen können.
Oft sind die Zeilen und Spalten aber nicht direkt nebeneinander und wir müssen eventuell auch mal über ein paar Zeilen und Spalten springen. Auch das können wir mit der Vektorschreibweise machen, diesmal in Kombination mit der Funktion c()
.
iris[c(2:5, 149:150), c(1, 3:4)]
# Kelchlänge Blütenblattlänge Blütenblattbreite
# 2 4.9 1.4 0.2
# 3 4.7 1.3 0.2
# 4 4.6 1.5 0.2
# 5 5.0 1.4 0.2
# 149 6.2 5.4 2.3
# 150 5.9 5.1 1.8
Hier bekommen wir die 2. bis 5. Zeile und noch zusätzlich die 149. bis 150. Zeile. Bei den Spalten haben wir die erste Spalte (Kelchlänge) noch zusätzlich zu der dritten und vierten Spalte ausgewählt (Blütenblattlänge und Blütenblattbreite).
Ungewollte Daten ausschließen
Dies ist eine Erweiterung des Subsettings mit Vektoren. Im vorigen Beispiel haben wir angegeben welche Bereiche in den Daten wir auswählen wollen. Wir können aber auch das Gegenteil machen und die Daten angeben, die wir ausschließen möchten. Dies funktioniert ganz einfach indem wir lediglich das Vorzeichen ändern:
iris[-c(15:150), -c(1, 3:4)]
# Kelchbreite Gattung
# 1 3.5 Iris-setosa
# 2 3.0 Iris-setosa
# 3 3.2 Iris-setosa
# 4 3.1 Iris-setosa
# 5 3.6 Iris-setosa
# 6 3.9 Iris-setosa
# 7 3.4 Iris-setosa
# 8 3.4 Iris-setosa
# 9 2.9 Iris-setosa
# 10 3.1 Iris-setosa
# 11 3.7 Iris-setosa
# 12 3.4 Iris-setosa
# 13 3.0 Iris-setosa
# 14 3.0 Iris-setosa
Jetzt haben wir alle Zeilen von Zeile 15 bis 150 ausgeschlossen und die erste, dritte und vierte Spalte.
Subsetting bei größeren Datenmengen
Diese grundlegenden Möglichkeiten der Unterteilung eines Datenrahmens in R können allerdings bei großen Datensätzen mühsam werden. Wir müssen die genauen Spalten- und Zeilennummern kennen und im ungünstigsten Fall verschieben sich die Daten zwischenzeitlich nochmal. Bei 5 Spalten und 150 Zeilen ist alles noch recht überschaubar, aber was machen wir bei 500 Spalten und 15.000 Zeilen?
iris[which(iris$Kelchlänge > 7),
names(iris) %in% c("Kelchlänge","Blütenblattlänge","Gattung")]
# Kelchlänge Blütenblattlänge Gattung
# 103 7.1 5.9 Iris-virginica
# 106 7.6 6.6 Iris-virginica
# 108 7.3 6.3 Iris-virginica
# 110 7.2 6.1 Iris-virginica
# 118 7.7 6.7 Iris-virginica
# 119 7.7 6.9 Iris-virginica
# 123 7.7 6.7 Iris-virginica
# 126 7.2 6.0 Iris-virginica
# 130 7.2 5.8 Iris-virginica
# 131 7.4 6.1 Iris-virginica
# 132 7.9 6.4 Iris-virginica
# 136 7.7 6.1 Iris-virginica
Dieses Mal extrahieren wir jedoch die benötigten Zeilen mit der which()
-Funktion. Diese Funktion gibt die Indizes zurück, bei denen die Spalte „Kelchlänge“ der Daten größer als 7 ist, so dass wir die entsprechenden Zeilen erhalten. Mit der names()
-Funktion und dem %in%
-Operator wählen wir die Spalten aus, die wir benötigen.
Nun, diese Zeile Code mag vielleicht etwas zu kompliziert erscheinen. Es muss doch einen einfacheren Weg geben, das zu machen?! Nun, den gibt es! Es gibt eine weitere grundlegende Funktion in R, die es uns erlaubt, einen Datenrahmen zu unterteilen, ohne die Zeilen- und Spaltenindizes zu kennen. Passenderweise heißt handelt es sich dabei um die subset()
-Funktion.
subset(iris, Kelchlänge > 7, select = c("Kelchlänge","Blütenblattlänge","Gattung"))
# Kelchlänge Blütenblattlänge Gattung
# 103 7.1 5.9 Iris-virginica
# 106 7.6 6.6 Iris-virginica
# 108 7.3 6.3 Iris-virginica
# 110 7.2 6.1 Iris-virginica
# 118 7.7 6.7 Iris-virginica
# 119 7.7 6.9 Iris-virginica
# 123 7.7 6.7 Iris-virginica
# 126 7.2 6.0 Iris-virginica
# 130 7.2 5.8 Iris-virginica
# 131 7.4 6.1 Iris-virginica
# 132 7.9 6.4 Iris-virginica
# 136 7.7 6.1 Iris-virginica
Die Funktion subset() erwartet 3 Argumente: den Datenrahmen, den wir unterteilen möchten, die Bedingung, die für für unser Subset erfüllt sein muss, und die Spalten, die wir benötigen. In unserem Fall wollen wir nur Datensätze haben, wo die Kelchlänge größer als 7 ist und wählen dann die Spalten „Kelchlänge“, „Blütenblattlänge“ und „Gattung“ aus.
Wie wir sehen können, sind die Ausgaben von which()
und subset()
identisch, wobei die which()
-Funktion in unseren Tests immer etwas schneller war als die subset()
-Funktion. Der Unterschied in der Geschwindigkeit fällt aber erst bei sehr großen Datensätzen ins Gewicht.
Daten mit dplyr unterteilen
Die letzte Funktion auf unserer Liste ist nicht Teil von der R-Standardinstallation. Um sie zu verwenden, müssen wir zuerst das dplyr
-Paket installieren und laden, wie im Beispiel unten. Das dplyr
-Paket ist speziell für einfache und schnelle Operationen gemacht worden.
Wenn wir dplyr
heruntergeladen haben, erstellen wir einen neuen Datenrahmen, indem wir zwei Funktionen aus diesem Paket verwenden:
- filter(): Das erste Argument ist der Datenrahmen; das zweite Argument ist die Bedingung, nach der wir ihn unterteilen wollen. Das Ergebnis ist der gesamte Datenrahmen mit nur den von uns gewünschten Zeilen.
- select(): das erste Argument ist der Datenrahmen; das zweite Argument sind die Namen der Spalten, die wir daraus auswählen wollen. Wir müssen nicht die Funktion names() verwenden, und wir müssen nicht einmal Anführungszeichen verwenden. Wir listen einfach die Spaltennamen als Objekte auf.
install.packages("dplyr")
library(dplyr)
select(filter(iris, Kelchlänge > 7), c("Kelchlänge","Blütenblattlänge","Gattung"))
# Kelchlänge Blütenblattlänge Gattung
# 1 7.1 5.9 Iris-virginica
# 2 7.6 6.6 Iris-virginica
# 3 7.3 6.3 Iris-virginica
# 4 7.2 6.1 Iris-virginica
# 5 7.7 6.7 Iris-virginica
# 6 7.7 6.9 Iris-virginica
# 7 7.7 6.7 Iris-virginica
# 8 7.2 6.0 Iris-virginica
# 9 7.2 5.8 Iris-virginica
# 10 7.4 6.1 Iris-virginica
# 11 7.9 6.4 Iris-virginica
# 12 7.7 6.1 Iris-virginica
Die Funktionen aus dem dplyr
-Packet sind nicht nur einfacher zu verwenden, sie sind auch in unserem Vergleich schneller als alle anderen hier vorgestellten Möglichkeiten.