Teile diesen Beitrag:

So, liebe R-Braineos, hier kommt der zweite Teil zu Datentypen in R. Nachdem wir in Teil 1 die Basis-Datentypen von R erledigt haben, geht es nun datum, diese zu kombinieren.

Zusammengesetzte Datentypen in R

Die Power von R liegt nämlich nicht in den Basisdatentypen, sondern darin, dass fast alles auf Vektoren aufbaut. Vector und data.frame (Tabellen) sind die Objekte, die ich als Data Scientist ständig gebrauche. Aber auch list ist nicht zu verachten.

Mehrere Elemente eines Datentyps – Der Datentyp VECTOR in R

Vektoren sind eine durchnummerierte Kette von Objekten eines Datentyps. Wichtig: Es geht nur ein Datentyp pro Vektor, man kann nicht bunt mischen (dafür benötigt man dann Listen). Und in R ist jeder der Basisdatentypen automatisch ein Vektor, das erkennt man an der 1 in eckigen Klammern vor dem Output. Eckige Klammern sind das Stichwort, denn so können wir die einzelnen Elemente ansprechen. Die Funktion zum Verbinden von Elementen zu einem Vektor heißt einfach c (für combine). Mit length bekommt man die Länge des Vektors zurück.

# Einen Vektor x mit drei Elementen erzeugen
x = c(3,4,5)
# Die Klasse eines Vektors ist der zugrundeliegende Datentyp, hier numeric
class(x)
# length gibt die Anzahl Elemente des Vektors zurücl
length(x)
# die Elemente spricht man über Indizes in den eckigen Klammern an
x[1]
# das erste und dritte Element
x[c(1,3)]

Operationen und Vergleiche werden für jedes Element durchgeführt. Und hier kommt die Power von R ins Spiel, die manchmal leider auch schwierig sein kann. Es geht um die vektorielle Auswertung. Anstatt zum Beispiel eine Schleife zu programmieren, mit der jedes Element von x um 1 erhöht wird, schreibt man einfach x+1. Solche Vektoroperationen haben übrigens auch einen enormen Geschwindigkeitsvorteil und sollten (fast) immer einer Schleife vorgezogen werden.

# Operationen wie Addition wird auf jedes Element angewandt
y <- x + 1
y
# auch Vergleiche sind Operationen und werden auf jedes Element angewandt
z = y > 4
class(z)
# Auswahl über einen boolschen Vektor der gleichen Länge
y[z]
# Das geht natürlich auch direkt, ohne eine andere Variable zu erzeugen
y[y > 4]

Vektoren lassen sich von jedem Grunddatentyp erzeugen. Im nächsten Beispiel ist der Vektor a vom Typ character. Negative Indizes entfernen die entsprechende Stelle. a[-1] entspricht also a[2:length(a)]. Mit dem Doppelpunkt erzeugt man übrigens einen integer-Vektor mit alles ganzen Zahlen zwischen den beiden angegeben Zahlen, also 1:3 entspricht also c(1L, 2L, 3L).

a = c("H","a","l","l","o")
class(a)
a[1]
# Der Doppelpunkt erzeugt einen Vektor von ganzen Zahlen
1:3
a[1:3]
a[c(1,2,3)]
# Ein negativer Wert entfernt das Element aus dem Vektor
a[-1]
a[-3:-1]
length(a)
 
# nchar wird auf jedes Element angewandt
b = c("Ha","llo")
nchar(b)
# paste verbindet mehrere Strings
paste(a, collapse ="")
 
# implizite Umwandlung von numeric in character, damit der Vektor nur einen Datentyp hat
x = c("Hallo",1L, 3.14)
# Kombination von zwei Vektoren zu einem
z = c(x,y)

Mehrere Elemente verschiedener Datentypen – Der Datentyp LIST in R

Vektoren sind super, haben aber die Einschränkung, dass es sich immer um einen Datentyp handeln muss. Wollen wir verschiedene Datentypen in einem Objekt, dann benötigen wir eine Liste.

Auch Listen sind in R ganz einfach und schnell erstellt. Sie sind aber bei weitem nicht so performant wie Vektoren. Wenn es also möglich ist, sollten Vektoren verwendet werden. Dafür sind Listen aber soooo flexibel. Listen können Vektoren, wiederum Listen und eben jedes Objekt in R enthalten.

Die Elemente einer Liste lassen sich wie bei Vektoren über den Index ansprechen, wir brauchen hier aber doppelte eckige Klammern. Die Anzahl Elemente bekommt man wie bei Vektoren über die Funktion length.

l = list(1L, 1.34, "Hallo", 1:3)
# l ist vom Typ list
class(l)
is.list(l)
length(l)
l[[1]]
class(l[[1]])
l[[4]][1]

Eine super nützliche Sache ist das Benennen der Elemente einer Liste mit der Funktion names. Dazu einfach einen Character-Vektor der gleichen Länge übergeben. Dann lassen sich die Elemente per Namen, besonders praktisch in der $-Notation, ansprechen. Der Name eines Elements lässt sich auch einfach ändern, denn die Namen sind nur ein Vektor.

names(l) <- c("Tick","Tack","Toe","Foo")
l[["Tick"]]
l$Tick
# Benennung der Elemente direkt beim Erzeugen
l2 <- list(pi=3.14, euler=2.718, Toe="Hallo", Foo=1:3)
l2$Foo
names(l)[3] <- "Tock"
names(l)

Listen lassen sich wie Vektoren mit c einfach zusammenfügen. Beim Löschen gibt es zwei Varianten. Willst Du wirklich ein Element in der Liste löschen, also die Liste verändern, dann setzt man das Element auf NULL. Willst Du die Liste ohne ein Element übergeben, also die Liste selber nicht verändern, dann geht es wie bei Vektoren mit einem negativen Index.

l3 <- c(l, l2)
# Löschen eines Elements, Liste wird dadurch verändert
l3[[1]] <- NULL
# Element wird nicht mit übergeben, l3 aber nicht verändert
l4 <- l3[-1]

Tabellen – Der Datentyp DATA.FRAME in R

Data.frames sind ein Muss für alle Datenanalyen. Im Endeffekt sind data.frames Tabellen, bei der jede Spalte von einem Datentyp ist. Stellt euch die Erfassung einer Befragung vor. Jede Zeile entspricht einem Befragten, die Spalten sind die einzelnen Fragen.

Einen data.frame erzeugt man, indem man die einzelnen Spalten der Funktion data.frame übergibt. Die Anzahl Spalten bzw. Zeilen bekommt man mit ncol bzw. nrow oder direkt beide mit dim.

df = data.frame(x = rnorm(10),
y = sample(c("Rot","Gelb","Grün"), 10, replace = TRUE),
z = 1L:10L)
class(df)
ncol(df)
nrow(df)
dim(df)

Der Zugriff auf die einzelnen Elemente oder Spalten bzw. Zeilen ist eine Mischung aus Vektor und Liste. Ein Element des data.frames bekommt man über Zeilen- und Spaltenangabe in eckigen Klammern. Lässt man einen der beiden Indizes weg (das Komma aber nicht), dann bekommt man die ganze Zeile bzw. Spalte. Die Spalten lassen sich wie bei Listen praktisch über den Spaltennamen ansprechen.

df[1,3]
df[1,]
df[,1]
df$x
df[,"x"]
df[1,1:2]
class(df$x)
 
# Filterung der Zeilen anhand einer Bedingung
df[df$y=="Gelb",]
# Mittelwert der Spalte x, wenn auf Gelb gefiltert wurde
mean(df$x[df$y=="Gelb"])

Die Spaltennamen lassen sich über colnames ansprechen. names wie bei Listen geht auch, aber colnames ist eindeutiger, es gibt auch rownames. Eine neue Spalte kann man einfach anfügen, indem man diese direkt benennt.

colnames(df)[1] <- "a"
colnames(df)
df$b <- rbinom(nrow(df),20,0.4)
df$b <- NULL

Spezielle Datentypen in R

Folge von kategoriellen Variablen – Der Datentyp FACTOR

R wurde für Datenauswertungen konzipiert. Und wer ein wenig Statistikerfahrung hat, weiß, dass Merkmale unterschiedliche Skalenniveaus haben können, also nominal, ordinal oder kardinal. Haben Daten ein nominales Skalenniveau, können also nur benannt werden wie z.B. Lieblingsfarbe, dann gibt es dafür in R den Datentyp factor.

f <- factor(c("Rot","Gelb","Rot","Blau","Blau","Blau"))
f
class(f)
is.factor(f)
length(f)
levels(f)
levels(f) <- c("Rot","Gelb","Blau","Grün")
f

Für ordinale Skalenniveaus, deren Ausprägungen geordnet werden können, kann das auch mit angegeben werden. Wir erhalten dann ein Objekt, was zwei Klassen angehört, nämlich factor und ordered.

auspraegungen <- c("nie","selten","oft","sehr oft")
of <- factor(c(1,1,2,2,4,4,3),labels = auspraegungen, ordered = TRUE)
of
class(of)
table(of)
 
# Mittelwert gibt es bei Faktoren nicht
mean(of)
# Median ist eigentlich bei ordinalen Skalen erlaubt
# in R funktioniert median nicht, man kann aber das 50%-Quantil verwenden
median(of)
quantile(of, .5, type=1)

Matrizenrechnung – Der Datentyp MATRIX

In R gibt es einen extra Datentyp Matrix. Im Prinzip wie ein data.frame, nur dass alle Elemente von einem Datentyp sein müssen. Besser ist daher der Vergleich mit einem Vektor, der zusätzlich Angaben zu den Dimensionen hat (so ist es auch in R realisiert).

Eine Matrix initialisiert man also durch Angabe eines Vektors und einer Spalten- oder Zeilenanzahl. Die Elemente des Vektors werden dann spaltenweise verwendet. Alternativ setzt man byrow auf TRUE, dann wird der Vektor zeilenweise verwendet.

Der Zugriff auf einzelne Elemente, Spalten und Zeilen erfolgt über einen Doppelindex in eckigen Klammern.

M = matrix(c(1,2,3,4,5,6),nrow=2)
class(M)
ncol(M)
nrow(M)
dim(M)
M
M[1,2]
M[1,]
M[,2]
M = matrix(c(1,2,3,4,5,6),nrow=2, byrow = TRUE)
M

Quadratische Matrizen können miteinander multizipliert werden. Achtung, dabei muss man zwischen der elementweisen Multiplikation * und der echten mathematische Matrixmultiplikation %*% unterscheiden. Die elementweise Multiplikation multipliziert jeden Eintrag der einen Matrix mit dem entsprechenden Eintrag der zweiten Matrix. M*M entspricht also dem quadrieren jedes Eintrags.

M = matrix(1:9,nrow=3, byrow = TRUE)
M
M * M
M %*% M
diag(M)

So, damit ist auch der zweite Teil geschafft und ihr seid nun R-Datentypen-Experten. Wenn ihr mit den Erklärungen und Beispielen etwas anfangen konntet, dann helft mir auch, indem ihr den Beitrag teilt. Danke!

Happy Coding,
Euer Holger

Teile diesen Beitrag: