3.2 Datenstrukturen

Vergleich eines Skalars und eines Vektors

Figure 3.6: Vergleich eines Skalars und eines Vektors

Der einfachste Datentyp in R ist ein Skalar (Mathematische Größe, die allein durch die Angabe eines Zahlenwertes charakterisiert ist). Im Gegensatz zu der mathematischen Beschreibung, kann in R ein Skalar jedoch character sein und muss nicht zwangsläufig als numeric definiert sein. Mathematische Operationen sind mit numerischen Skalaren möglich, nicht jedoch wenn diese in R als character gespeichert sind.

a <- "1"
b <- "2"
a + b

Fehler in a + b : nicht-numerisches Argument für binären Operator

Bisher haben wir einfache Objekte in R erzeugt, wie eben genau Skalare oder kürzere Vektoren. Es gibt jedoch noch weitere Datenstrukturen, die sich hinsichtlich der Dimensionalität unterscheiden (1D und 2D) und ob die Objekttypen homogen (nur ein Objekttyp) und heterogen (unterschiedliche Objekttypen) beinhalten:

|Datenstruktur | Dimensionalität | Objekttypen| |Vektor | eindimensional | homogen| |Liste | eindimensional |heterogen| |Matrix | zweidimensional | homogen| |Dataframe | zweidimensional |heterogen|

Table: Datenstrukturen in R.

3.2.1 Vektor

Ein Vektor ist eine Ansammlung von Skalaren, die als ein R Objekt gespeichert wurden. Die Zahlen von 1 bis 10 bspw. bilden einen numerischen Vektor mit der Länge 10. Die Buchstaben im Alphabet sind ein Vektor mit der Länge 26.

🚨 Vektoren können nur numeric oder character sein…nicht beides!

Es gibt verschiedene Möglichkeiten einen Vektor selber zu bilden.

Funktionen um einen Vektor zu erzeugen.
Funktion Beispiel Ergebnis
c(a, b, ...) c(1, 5, 9) 1, 5, 9
a:b 1:5 1, 2, 3, 4, 5
seq(from, to, by, length.out) seq(from = 0, to = 6, by = 2) 0, 2, 4, 6
rep(x, times, each, length.out) rep(c(7, 8), times = 2, each = 2) 7, 7, 8, 8, 7, 7, 8, 8

Die einfachste Möglichkeit einen Vektor zu erzeugen ist mit der c() Funktion. “c” leitet sich von dem englischen Wort concatenate ab und lässt sich frei übersetzen mit “zusammenbringen” oder “zusammenführen”.

# Speichere einen Vektor mit den Zahlen von 1 bis 10 
a <- c(1,2,3,4,5,6,7,8,9,10)
# Stelle die Zahlen dar
a
##  [1]  1  2  3  4  5  6  7  8  9 10

Man kann auch Vektoren miteinander verknüpfen:

a <- c(1,2,3,4,5)
b <- c(6,7,8,9,10)
x <- c(a, b)
x
##  [1]  1  2  3  4  5  6  7  8  9 10

😎 Yeah! Das hat ja gut geklappt.

Man kann auch character Vektoren erstellen mit demselben Prinzip

wort_vec <- c("Beste", "Exkursion", "der", "Welt")
wort_vec
## [1] "Beste"     "Exkursion" "der"       "Welt"

Wenn ihr allerdings einen Vektor von 1:1000 erstellen wollt… 🤯 Aber keine Sorge! Auch hierfür gibt es Funktionen in R um das Leben zu erleichtern.

3.2.1.1 a:b

Die Vektoren werden in Inkrementen von 1 aufgefüllt

1:10
##  [1]  1  2  3  4  5  6  7  8  9 10
# Das ganze geht auch Rückwärts
10:1
##  [1] 10  9  8  7  6  5  4  3  2  1
# Oder mit nicht runden Zahlen (non-integers)
2.5:8.5
## [1] 2.5 3.5 4.5 5.5 6.5 7.5 8.5

3.2.1.2 seq()

Diese Funktion musste ich für Zeitreihenuntersuchungen schon öfter verwenden und ist ein wahrer Retter in der Not.

Argument Definition
from Beginn der Sequenz
to Ende der Sequenz
by Die Inkremente
length.out Die gewünschte Länge der Sequent (nur wichtig wenn by festgelegt wurde)
# Erstelle Nummer von 1 bis 10 in einer Schritten
seq(from = 1, to = 10, by = 1)
##  [1]  1  2  3  4  5  6  7  8  9 10
# Erstelle ganze Zahlen von 0 bis 100 in 10er Schritten
seq(from = 0, to = 100, by = 10)
##  [1]   0  10  20  30  40  50  60  70  80  90 100

Wenn das Argument length.out verwendet wird, entspricht die Länge des Vektors dem Wert von length.out.

# Erstelle 10 Zahlen von 1 bis 5
seq(from = 1, to = 5, length.out = 10)
##  [1] 1.000000 1.444444 1.888889 2.333333 2.777778 3.222222 3.666667 4.111111
##  [9] 4.555556 5.000000
# Erstelle 3 Zahlen von 0 bis 100
seq(from = 0, to = 100, length.out = 3)
## [1]   0  50 100

3.2.1.3 rep()

Argument Definition
x Ein Skalar oder Vektor der wiederholt werden soll
times Die Anzahl wie häufig x wiederholt werden soll
each Die Anzahl wie häufig jeder Wert in x wiederholt werden soll
length.out Die gewünschte Länge der Sequenz

Die rep() Funktion erlaubt es also einen Skalar oder Vektor beliebig oft zu wiederholen.

rep(x = 3, times = 10)
##  [1] 3 3 3 3 3 3 3 3 3 3
rep(x = c(1, 2), each = 3)
## [1] 1 1 1 2 2 2
rep(x = 1:3, length.out = 10)
##  [1] 1 2 3 1 2 3 1 2 3 1

💡 Man kann eine a:b Funktion mit einer rep() Funktion verknüpfen. 💡 Sogar das times und each Argument lassen sich in die rep() Funktion integrieren

rep(x = 1:3, each = 2, times = 2)
##  [1] 1 1 2 2 3 3 1 1 2 2 3 3

3.2.1.4 Vektorelemente auswählen

Um auf eine Zahl in einem Vektor zuzugreifen können wir dies über eine eckige Klammer [] tun.

a <- c(1,2,3,4,5)
a[2]
## [1] 2
a[5]
## [1] 5

Wenn wir mehrere Elemente des Vektors auswählen möchten, dann müssen wir einen neuen Vektor über die Positionen erzeugen, beispielsweise um das erste, dritte und fünfte Element des Vektors auszugeben:

a[c(1,3,5)]
## [1] 1 3 5

Eine weitere Möglichkeite die ersten drei Elemente eines Vektors auszuwählen ist mit dem Doppelpunkt : was so viel bedeutet wie von bis.

a[1:4]
## [1] 1 2 3 4

Elemente in einem Vektor können auch mit = benannt werden. Bei der Benennung von Spaltennamen in einer Tabelle (dataframe oder Matrix in R) ist der Befehl ähnlich.

namen <- c(eins = "Dies", zwei = "ist", drei = "ein", vier = "Test")
namen
##   eins   zwei   drei   vier 
## "Dies"  "ist"  "ein" "Test"
namen["vier"]
##   vier 
## "Test"

3.2.2 Liste

Listen ähneln Vektoren und können über die Funktion list() erzeugt werden. Beispielsweise der Standort Speicherkoog kann als Liste wie folgt erzeugt werden:

koog <- list(country = "Germany", state = "Schleswig-Holstein", city = "Meldorf", name = "Speicherkoog")
koog
## $country
## [1] "Germany"
## 
## $state
## [1] "Schleswig-Holstein"
## 
## $city
## [1] "Meldorf"
## 
## $name
## [1] "Speicherkoog"

Die Darstellung gegenüber Vektoren ist jedoch eine andere. Anstelle der Darstellung nebeneinander werden die Listen Elemente untereinander dargestellt.

3.2.3 Matrix und dataframe

Darstellung von Datenstrukturen

Figure 3.7: Darstellung von Datenstrukturen

3.2.3.1 Matrix

Eine Matrix ist eine zweidimensionale Struktur und kann mit der Funktion matrix() erzeugt werden.

# Erstelle einen Vektor von 1 bis 10
a <- c(1:10)
# Teile den Vektor auf zwei Spalten auf
b <- matrix(a, ncol = 2)
b
##      [,1] [,2]
## [1,]    1    6
## [2,]    2    7
## [3,]    3    8
## [4,]    4    9
## [5,]    5   10
# Teile den Vektor auf zwei Zeilen auf
c <- matrix(a, nrow = 2)
c
##      [,1] [,2] [,3] [,4] [,5]
## [1,]    1    3    5    7    9
## [2,]    2    4    6    8   10

Mit der Funktion rbind() (row = Zeile) oder cbind() (column = Spalte) können wir mehrere Vektoren auch zusammenführen.

a <- c(1:10)
b <- c(11:20)
c <- c(21:30)
# Erstelle eine Matrix mit drei Spalten
cbind(a,b,c)
##        a  b  c
##  [1,]  1 11 21
##  [2,]  2 12 22
##  [3,]  3 13 23
##  [4,]  4 14 24
##  [5,]  5 15 25
##  [6,]  6 16 26
##  [7,]  7 17 27
##  [8,]  8 18 28
##  [9,]  9 19 29
## [10,] 10 20 30
# Erstelle eine Matrix mit drei Zeilen
rbind(a,b,c)
##   [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
## a    1    2    3    4    5    6    7    8    9    10
## b   11   12   13   14   15   16   17   18   19    20
## c   21   22   23   24   25   26   27   28   29    30

Die Spalten- oder Zeilennamen einer Matrix können auch benannt oder umbenannt werden mit der Funktion colnames() oder rownames().

mat <- rbind(a,b,c)
mat
##   [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
## a    1    2    3    4    5    6    7    8    9    10
## b   11   12   13   14   15   16   17   18   19    20
## c   21   22   23   24   25   26   27   28   29    30
rownames(mat) <- c("Zeile 1", "Zeile 2", "Zeile 3")
mat
##         [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10]
## Zeile 1    1    2    3    4    5    6    7    8    9    10
## Zeile 2   11   12   13   14   15   16   17   18   19    20
## Zeile 3   21   22   23   24   25   26   27   28   29    30

Eine nützliche Funktion lautet t() um eine Matrix oder dataframe zu transponieren, also umzuwandeln und um 90° zu vertauschen.

# Transponiere die Matrix mat 
t(mat)
##       Zeile 1 Zeile 2 Zeile 3
##  [1,]       1      11      21
##  [2,]       2      12      22
##  [3,]       3      13      23
##  [4,]       4      14      24
##  [5,]       5      15      25
##  [6,]       6      16      26
##  [7,]       7      17      27
##  [8,]       8      18      28
##  [9,]       9      19      29
## [10,]      10      20      30

Unsere Zeilennamen machen jetzt natürlich keinen Sinn mehr 🙃 Versuche mal die Spaltennamen richtig zu beschriften.

3.2.3.2 Dataframe

Eine Matrix ähnelt der Datenstruktur wie man sie aus Excel, SPSS etc. kennt. Großer Unterschied ist aber, dass eine Matrix nur einen Datentyp erlaubt und ein dataframe mehrere Typen. Mit der Funktion data.frame() können wir gleich lange Vektoren unterschiedlichen Typs kombinieren.

# Erstelle einen dataframe
beatles_data <- data.frame(
  name = c("John", "Paul", "George", "Ringo"),
  surname = c("Lennon", "McCartney", "Harrison", "Starr"),
  born = c(1940, 1942, 1943, 1940)
)
beatles_data
##     name   surname born
## 1   John    Lennon 1940
## 2   Paul McCartney 1942
## 3 George  Harrison 1943
## 4  Ringo     Starr 1940

Die händische Eingabe von tabellarischen Daten wäre natürlich umständlich. In R gibt es einfache Möglichkeiten diese aus externen Datenquellen (z.B. CSV, Excel, txt, …) einzulesen und zu verarbeiten.

3.2.3.3 tibble

tibble haben dieselbe Datenstruktur wie data.frame, nur das Attribut class in einem tibble ist länger:

# create a data frame
df1 <- data.frame(
  x = c("a", "b", "c"),
  y = c(1,2,3)
)
typeof(df1)
## [1] "list"
attributes(df1)
## $names
## [1] "x" "y"
## 
## $class
## [1] "data.frame"
## 
## $row.names
## [1] 1 2 3
# create a tibble
df2 <- tibble(
  x = c("a", "b", "c"),
  y = c(1,2,3)
)
typeof(df2)
## [1] "list"
attributes(df2)
## $class
## [1] "tbl_df"     "tbl"        "data.frame"
## 
## $row.names
## [1] 1 2 3
## 
## $names
## [1] "x" "y"