11  Daten bearbeiten

Letzte Änderung am 02. April 2024 um 09:52:43

“The only way to learn a new programming language is by writing programs in it.” — Dennis Ritchie

Wir haben in dem vorherigen Kapitel Daten eingelesen. Jetzt wollen wir die Daten aufräumen (eng. tidy). Es ist notwendig, dass wir die Daten so aufarbeiten, dass R damit umgehen kann. Insbesondere das Erstellen von Faktoren ist wichtig, wenn die Spalte ein Faktor ist. R muss wissen was für Eigenschaften eine Spalte hat. Sonst funktionieren spätere Anwendungen in R nicht richtig oder geben einen Fehler wieder.

Es gibt zwei Möglichkeiten wie du mit deinen Daten umgehst:

  1. Du änderst all deine Daten in Excel. Das mag bei einem kleinen Datensatz gut funktionieren. Dann musst du dich nicht mit dem Programmieren beschäftigen.
  2. Du willst lernen die Daten auch in R zu verändern. Dann hilft dir dieses Kapitel. Auch in den folgenden Kapiteln werde ich immer wieder Funktionen wie select(), filter() und mutate()nutzen. Dann kannst du hier nochmal schauen, was die Funktionen machen.
  3. Und ich nutze dieses Kapitel ein wenig dafür um für mich persönlich wichtige Funktionen und Schritte zu speichern. Irgendwo muss ja auch mein Copy & Paste Kram liegen, was ich dann immer wieder nutze. Deshalb wird es nach unten dann immer komplexer…

Im Folgenden wollen wir den Datensatz data_tbl in R bearbeiten. Das heißt wir wollen Spalten auswählen mit select() oder Zeilen auswählen mit filter(). Schlussendlich wollen wir auch die Eigenschaften von Spalten mit der Funktion mutate ändern. Wir laden also den Datensatz flea_dog_cat.xlsx einmal in R.

data_tbl <- read_excel("data/flea_dog_cat_fox.xlsx")

Es ergibt sich folgende Tabelle 11.1, die wir schon aus vorherigen Kapiteln kennen.

Tabelle 11.1— Tabelle der Sprunglängen [cm], Anzahl an Flöhen, Boniturnote sowie der Infektionsstatus von Hunden, Katzen und Füchsen.
animal jump_length flea_count weight grade infected
dog 5.7 18 2.1 8 0
dog 8.9 22 2.3 8 1
dog 11.8 17 2.8 6 1
dog 5.6 12 2.4 8 0
dog 9.1 23 1.2 7 1
dog 8.2 18 4.1 7 0
dog 7.6 21 3.2 9 0
cat 3.2 12 1.1 7 1
cat 2.2 13 2.1 5 0
cat 5.4 11 2.4 7 0
cat 4.1 12 2.1 6 0
cat 4.3 16 1.5 6 1
cat 7.9 9 3.7 6 0
cat 6.1 7 2.9 5 0
fox 7.7 21 3.1 5 1
fox 8.1 25 4.2 4 1
fox 9.1 31 5.1 4 1
fox 9.7 12 3.5 5 1
fox 10.6 28 3.2 4 0
fox 8.6 18 4.6 4 1
fox 10.3 19 3.7 3 0

11.1 Genutzte R Pakete

Wir wollen folgende R Pakete in diesem Kapitel nutzen.

pacman::p_load(tidyverse, readxl, magrittr, janitor)

An der Seite des Kapitels findest du den Link Quellcode anzeigen, über den du Zugang zum gesamten R-Code dieses Kapitels erhältst.

11.2 Spalten wählen mit select()

Der Datensatz, den wir im Experiment erschaffen, ist meist riesig. Jetzt könnten wir natürlich eine Exceltabelle mit unterschiedlichen Sheets bzw. Reitern erstellen oder aber die Spalten die wir brauchen in R selektieren. Wir nutzen die Funktion select()um Spalten zu wählen. Im folgenden Codeblock wählen wir die Spalten animal, jump_length und flea_count.

data_tbl |> 
  select(animal, jump_length, flea_count)
# A tibble: 21 x 3
   animal jump_length flea_count
   <chr>        <dbl>      <dbl>
 1 dog            5.7         18
 2 dog            8.9         22
 3 dog           11.8         17
 4 dog            5.6         12
 5 dog            9.1         23
 6 dog            8.2         18
 7 dog            7.6         21
 8 cat            3.2         12
 9 cat            2.2         13
10 cat            5.4         11
# i 11 more rows

Wir können die Spalten beim selektieren auch umbenennen und in eine andere Reihenfolge bringen.

data_tbl |> 
  select(Sprungweite = jump_length, flea_count, animal)
# A tibble: 21 x 3
   Sprungweite flea_count animal
         <dbl>      <dbl> <chr> 
 1         5.7         18 dog   
 2         8.9         22 dog   
 3        11.8         17 dog   
 4         5.6         12 dog   
 5         9.1         23 dog   
 6         8.2         18 dog   
 7         7.6         21 dog   
 8         3.2         12 cat   
 9         2.2         13 cat   
10         5.4         11 cat   
# i 11 more rows

Du findest auf der englischen Hilfeseite für select() noch weitere Beispiele für die Nutzung.

11.3 Zeilen wählen mit filter()

Während wir die Auswahl an Spalten gut und gerne auch in Excel durchführen können, so ist dies bei der Auswahl der Zeilen nicht so einfach. Wir können in R hier auf die Funktion filter() zurückgreifen. Wir nutzen die Funktion filter() um Zeilen nach Kriterien zu wählen.

Im folgenden Codeblock wählen wir die Zeilen aus in denen die Worte dog und fox stehen. Wir nutzen dazu den Operator %in% um auszudrücken, dass wir alle Einträge in der Spalte animal wollen die in dem Vektor c("dog", "fox") beschrieben sind.

data_tbl |> 
  filter(animal %in% c("dog", "fox"))
# A tibble: 14 x 6
   animal jump_length flea_count weight grade infected
   <chr>        <dbl>      <dbl>  <dbl> <dbl>    <dbl>
 1 dog            5.7         18    2.1     8        0
 2 dog            8.9         22    2.3     8        1
 3 dog           11.8         17    2.8     6        1
 4 dog            5.6         12    2.4     8        0
 5 dog            9.1         23    1.2     7        1
 6 dog            8.2         18    4.1     7        0
 7 dog            7.6         21    3.2     9        0
 8 fox            7.7         21    3.1     5        1
 9 fox            8.1         25    4.2     4        1
10 fox            9.1         31    5.1     4        1
11 fox            9.7         12    3.5     5        1
12 fox           10.6         28    3.2     4        0
13 fox            8.6         18    4.6     4        1
14 fox           10.3         19    3.7     3        0

Es stehen dir Folgende logische Operatoren zu Verfügung wie in Tabelle 11.2 gezeigt. Am Anfang ist es immer etwas schwer sich in den logischen Operatoren zurechtzufinden. Daher kann ich dir nur den Tipp geben einmal die Operatoren selber auszuprobieren und zu schauen, was du da so raus filterst.

Tabelle 11.2— Logische Operatoren und R und deren Beschreibung
Logischer Operator Beschreibung
< kleiner als (eng. less than)
<= kleiner als oder gleich (eng. less than or equal to)
> größer als (eng. greater than)
>= größer als oder gleich (eng. greater than or equal to)
== exact gleich (eng. exactly equal to)
!= nicht gleich (eng. not equal to)
!x nicht (eng. not x)
x | y oder (eng. x or y)
x & y und (eng. x and y)

Hier ein paar Beispiele. Probiere gerne auch mal Operatoren selber aus. Im folgenden Codeblock wollen wir nur die Zeilen haben, die eine Anzahl an Flöhen größer von 15 haben.

data_tbl |> 
  filter(flea_count > 15)
# A tibble: 13 x 6
   animal jump_length flea_count weight grade infected
   <chr>        <dbl>      <dbl>  <dbl> <dbl>    <dbl>
 1 dog            5.7         18    2.1     8        0
 2 dog            8.9         22    2.3     8        1
 3 dog           11.8         17    2.8     6        1
 4 dog            9.1         23    1.2     7        1
 5 dog            8.2         18    4.1     7        0
 6 dog            7.6         21    3.2     9        0
 7 cat            4.3         16    1.5     6        1
 8 fox            7.7         21    3.1     5        1
 9 fox            8.1         25    4.2     4        1
10 fox            9.1         31    5.1     4        1
11 fox           10.6         28    3.2     4        0
12 fox            8.6         18    4.6     4        1
13 fox           10.3         19    3.7     3        0

Wir wollen nur die infizierten Tiere haben.

data_tbl |> 
  filter(infected == TRUE)
# A tibble: 10 x 6
   animal jump_length flea_count weight grade infected
   <chr>        <dbl>      <dbl>  <dbl> <dbl>    <dbl>
 1 dog            8.9         22    2.3     8        1
 2 dog           11.8         17    2.8     6        1
 3 dog            9.1         23    1.2     7        1
 4 cat            3.2         12    1.1     7        1
 5 cat            4.3         16    1.5     6        1
 6 fox            7.7         21    3.1     5        1
 7 fox            8.1         25    4.2     4        1
 8 fox            9.1         31    5.1     4        1
 9 fox            9.7         12    3.5     5        1
10 fox            8.6         18    4.6     4        1

Wir wollen nur die infizierten Tiere haben UND die Tiere mit einer Flohanzahl größer als 20.

data_tbl |> 
  filter(infected == TRUE & flea_count > 20)
# A tibble: 5 x 6
  animal jump_length flea_count weight grade infected
  <chr>        <dbl>      <dbl>  <dbl> <dbl>    <dbl>
1 dog            8.9         22    2.3     8        1
2 dog            9.1         23    1.2     7        1
3 fox            7.7         21    3.1     5        1
4 fox            8.1         25    4.2     4        1
5 fox            9.1         31    5.1     4        1

Du findest auf der englischen Hilfeseite für filter() noch weitere Beispiele für die Nutzung.

11.4 Spalten ändern mit mutate()

Nachdem wir die Spalten mit select() udn eventuell die Zeieln mit filter() gewählt haben. müssen wir jetzt noch die Eigenschaften der Spalten ändern. Das Ändern müssen wir nicht immer tun, aber häufig müssen wir noch einen Faktor erschaffen. Wir nutzen noch die Funktion pull() um uns die Spalte animal aus dem Datensatz zu ziehen. Nur so sehen wir die vollen Eigenschaften des Faktors. Später nutzen wir pull seltener und nur um zu kontrollieren, was wir gemacht haben. Wir nutzen die Funktion mutate() um die Eigenschaften von Spalten daher Variablen zu ändern. Die Reihenfolge der Funktionen ist wichtig um unliebsame Effekte zu vermeiden.

  1. Erst wählen wir die Spalten mit select()
  2. Dann filtern wir die Zeilen mit filter()
  3. Abschließend ändern wir die Eigenschaften der Spalten mit mutate()

Im folgenden Codeblock verwandeln wir die Variable animal in einen Faktor durch die Funktion as_factor. Wir sehen, dass die Level des Faktors so sortiert sind, wie das Auftreten in der Spalte animal.

data_tbl |> 
  mutate(animal = as_factor(animal)) |> 
  pull(animal)
 [1] dog dog dog dog dog dog dog cat cat cat cat cat cat cat fox fox fox fox fox
[20] fox fox
Levels: dog cat fox

Wollen wir die Sortierung der Level ändern, können wir die Funktion factor() nutzen. Wir ändern die Sortierung des Faktors zu fox, dog und cat.

data_tbl |> 
  mutate(animal = factor(animal, levels = c("fox", "dog", "cat"))) |> 
  pull(animal)
 [1] dog dog dog dog dog dog dog cat cat cat cat cat cat cat fox fox fox fox fox
[20] fox fox
Levels: fox dog cat

Wir können auch die Namen (eng. labels) der Level ändern. Hier musst du nur aufpassen wie du die alten Labels überschreibst. Wenn ich gleichzeitig die Level und die Labels ändere komme ich häufig durcheinander. Da muss du eventuell nochmal schauen, ob auch alles so geklappt hat wie du wolltest.

data_tbl |> 
  mutate(animal = factor(animal, labels = c("Hund", "Katze", "Fuchs"))) |> 
  pull(animal)
 [1] Katze Katze Katze Katze Katze Katze Katze Hund  Hund  Hund  Hund  Hund 
[13] Hund  Hund  Fuchs Fuchs Fuchs Fuchs Fuchs Fuchs Fuchs
Levels: Hund Katze Fuchs

Du findest auf der englischen Hilfeseite für mutate() noch weitere Beispiele für die Nutzung. Insbesondere die Nutzung von mutate() über mehrere Spalten gleichzeitig erlaubt sehr effiezientes Programmieren. Aber das ist für den Anfang etwas viel.

Die Funktionen select(), filter() und mutate() in R

Bitte schaue dir auch die Hilfeseiten der Funktionen an. In diesem Skript kann ich nicht alle Funktionalitäten der Funktionen zeigen. Oder du kommst in das R Tutorium welches ich anbiete und fragst dort nach den Möglichkeiten Daten in R zu verändern.

11.5 Gruppieren mit group_by()

Sobald wir einen Faktor erschaffen haben, können wir die Daten in R auch nach dem Faktor gruppieren. Das heißt wir nutzen die Funktion group_by() um R mitzuteilen, dass nun folgende Funktionen getrennt für die einzelen Gruppen erfolgen sollen. Im folgenden Codeblock siehst du die Anwendung.

data_tbl |> 
  mutate(animal = as_factor(animal)) |> 
  group_by(animal)
# A tibble: 21 x 6
# Groups:   animal [3]
   animal jump_length flea_count weight grade infected
   <fct>        <dbl>      <dbl>  <dbl> <dbl>    <dbl>
 1 dog            5.7         18    2.1     8        0
 2 dog            8.9         22    2.3     8        1
 3 dog           11.8         17    2.8     6        1
 4 dog            5.6         12    2.4     8        0
 5 dog            9.1         23    1.2     7        1
 6 dog            8.2         18    4.1     7        0
 7 dog            7.6         21    3.2     9        0
 8 cat            3.2         12    1.1     7        1
 9 cat            2.2         13    2.1     5        0
10 cat            5.4         11    2.4     7        0
# i 11 more rows

Auf den ersten Blick ändert sich nicht viel. Es entsteht aber die Zeile # Groups: animal [3]. Wir wissen nun, dass wir nach der Variable animal mit drei Gruppen die Datentabelle gruppiert haben.

11.6 Mehr Informationen durch glimpse() und str()

Am Ende noch zwei Funktionen zur Kontrolle, was wir hier eigentlich gerade tun. Mit der Funktion glimpse() können wir uns einen Einblick in die Daten geben lassen. Wir sehen dann nochmal kurz und knapp wieviel Zeieln und Spalten wir haben und welche Inhalte in den Spalten stehen. Die gleichen Informationen erhalten wir auch durch die Funktion str(). Die Funktion str()geht aber noch einen Schritt weiter und nennt uns auch Informationen zu dem Objekt. Daher wir wissen jetzt, dass es sich beim dem Objekt data_tbl um ein tibble() handelt.

glimpse(data_tbl)
Rows: 21
Columns: 6
$ animal      <chr> "dog", "dog", "dog", "dog", "dog", "dog", "dog", "cat", "c~
$ jump_length <dbl> 5.7, 8.9, 11.8, 5.6, 9.1, 8.2, 7.6, 3.2, 2.2, 5.4, 4.1, 4.~
$ flea_count  <dbl> 18, 22, 17, 12, 23, 18, 21, 12, 13, 11, 12, 16, 9, 7, 21, ~
$ weight      <dbl> 2.1, 2.3, 2.8, 2.4, 1.2, 4.1, 3.2, 1.1, 2.1, 2.4, 2.1, 1.5~
$ grade       <dbl> 8, 8, 6, 8, 7, 7, 9, 7, 5, 7, 6, 6, 6, 5, 5, 4, 4, 5, 4, 4~
$ infected    <dbl> 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1~
str(data_tbl)
tibble [21 x 6] (S3: tbl_df/tbl/data.frame)
 $ animal     : chr [1:21] "dog" "dog" "dog" "dog" ...
 $ jump_length: num [1:21] 5.7 8.9 11.8 5.6 9.1 8.2 7.6 3.2 2.2 5.4 ...
 $ flea_count : num [1:21] 18 22 17 12 23 18 21 12 13 11 ...
 $ weight     : num [1:21] 2.1 2.3 2.8 2.4 1.2 4.1 3.2 1.1 2.1 2.4 ...
 $ grade      : num [1:21] 8 8 6 8 7 7 9 7 5 7 ...
 $ infected   : num [1:21] 0 1 1 0 1 0 0 1 0 0 ...