Veröffentlichungsdatum

10. Oktober 2023

Arbeiten mit RStudio “Project”

Wir empfehlen die Verwendung von “Projects” innerhalb von RStudio. RStudio legt für jedes Projekt dann einen Ordner an, in welches die Projekt-Datei abgelegt wird (Dateiendung .Rproj). Sollen innerhalb des Projekts dann R-Skripts geladen oder erzeugt werden, werden diese dann auch im angelegten Ordner abgelegt. Mehr zu RStudio Projects findet ihr hier.

Das Verwenden von Projects bringt verschiedene Vorteile, wie zum Beispiel:

  • Festlegen der Working Directory ohne die Verwendung des expliziten Pfades (setwd()). Das ist sinnvoll, da sich dieser Pfad ändern kann (Zusammenarbeit mit anderen Usern, Ausführung des Scripts zu einem späteren Zeitpunkt)
  • Automatisches Zwischenspeichern geöffneter Scripts und Wiederherstellung der geöffneten Scripts bei der nächsten Session
  • Festlegen verschiedener projektspezifischer Optionen
  • Verwendung von Versionsverwaltungssystemen (z.B. git)

Arbeiten mit Libraries / Packages

R ist ohne Zusatzpackete, sogenannte “Packages” nicht mehr denkbar. Die allermeisten Packages werden auf CRAN gehostet und können leicht mittels install.packages() installiert werden. Eine sehr wichtige Sammlung von Packages wird von RStudio entwickelt. Unter dem Namen Tidyverse werden eine Reihe von Packages angeboten, den R-Alltag enorm erleichtert. Wir werden später näher auf das “Tidy”-Universum eingehen, an dieser Stelle können wir einfach mal die wichtigsten Packages aus tidyverse installieren (heute werden wir davon nur einen kleinen Teil benutzen).

Um ein package in R verwenden zu können, gibt es zwei Möglichkeiten:

  • entweder man lädt es zu Beginn der R-session mittles library("dplyr") (ohne Anführungs- und Schlusszeichen).
  • oder man ruft eine function mit vorangestelltem Packetname sowie zwei Doppelpunkten auf. dplyr::filter() ruft die Funktion filter() des Packets dplyr auf.

Letztere Notation ist vor allem dann sinnvoll, wenn sich zwei unterschiedliche Funktionen mit dem gleichen namen in verschiedenen pacakges existieren. filter() existiert als Funktion einersits im package dplyr sowie in stats. Dieses Phänomen nennt man “masking”.

Zu Beginn laden wir die nötigen Pakete:

library("readr")
library("lubridate")

Aufgabe 1

Erstelle eine data.frame mit nachstehenden Daten.

Code
df <- data.frame(
  Tierart = c("Fuchs", "Bär", "Hase", "Elch"),
  Anzahl = c(2, 5, 1, 3),
  Gewicht = c(4.4, 40.3, 1.1, 120),
  Geschlecht = c("m", "f", "m", "m"),
  Beschreibung = c("Rötlich", "Braun, gross", "klein, mit langen Ohren", "Lange Beine, Schaufelgeweih")
)
Tierart Anzahl Gewicht Geschlecht Beschreibung
Fuchs 2 4.4 m Rötlich
Bär 5 40.3 f Braun, gross
Hase 1 1.1 m klein, mit langen Ohren
Elch 3 120.0 m Lange Beine, Schaufelgeweih

Aufgabe 2

Was für Datentypen wurden in der letzten Aufgabe automatisch angenommen? Ermittle diese mit str() und prüfe, ob diese sinnvoll sind und wandle um wo nötig.

Code
str(df)
## 'data.frame':    4 obs. of  5 variables:
##  $ Tierart     : chr  "Fuchs" "Bär" "Hase" "Elch"
##  $ Anzahl      : num  2 5 1 3
##  $ Gewicht     : num  4.4 40.3 1.1 120
##  $ Geschlecht  : chr  "m" "f" "m" "m"
##  $ Beschreibung: chr  "Rötlich" "Braun, gross" "klein, mit langen Ohren" "Lange Beine, Schaufelgeweih"
typeof(df$Anzahl)
## [1] "double"
# Anzahl wurde als `double` interpretiert, ist aber eigentlich ein `integer`.

df$Anzahl <- as.integer(df$Anzahl)

Aufgabe 3

Nutze die Spalte Gewicht um die Tiere in 3 Gewichtskategorien einzuteilen:

  • leicht: < 5kg
  • mittel: 5 - 100 kg
  • schwer: > 100kg
Code
df$Gewichtsklasse[df$Gewicht > 100] <- "schwer"
df$Gewichtsklasse[df$Gewicht <= 100 & df$Gewicht > 5] <- "mittel"
df$Gewichtsklasse[df$Gewicht <= 5] <- "leicht"

Das Resultat:

Tierart Anzahl Gewicht Geschlecht Beschreibung Gewichtsklasse
Fuchs 2 4.4 m Rötlich leicht
Bär 5 40.3 f Braun, gross mittel
Hase 1 1.1 m klein, mit langen Ohren leicht
Elch 3 120.0 m Lange Beine, Schaufelgeweih schwer

Aufgabe 4

Auf Moodle findest du ein Zip-Files mit dem Namen prepro.zip. Lade das File herunter und entpacke es in deinem Projektordner. Importiere die Datei weather.csv. Falls du dafür das RStudio GUI verwendest, speichere den Import-Befehl in deinem R-Script ab. Bitte verwende einen relativen Pfad (also kein Pfad der mit C:/, ~/ o.ä. beginnt).)

Hinweis

Wir nutzen readr um csvs zu importieren und verwenden die Funktion read_delim (mit underscore) als alternative zu read.csv oder read.delim (mit Punkt). Das ist eine persönliche Präferenz1, es ist euch überlassen welche Funktion ihr verwendet. Beachtet, dass die beiden Funktionen leicht andere Parameter erwarten.

Code
wetter <- read_delim("datasets/prepro/weather.csv", ",")
stn time tre200h0
ABO 2000010100 -2.6
ABO 2000010101 -2.5
ABO 2000010102 -3.1
ABO 2000010103 -2.4
ABO 2000010104 -2.5
ABO 2000010105 -3.0
ABO 2000010106 -3.7
ABO 2000010107 -4.4
ABO 2000010108 -4.1
ABO 2000010109 -4.1

Aufgabe 5

Schau dir die Rückmeldung von read_csv()an. Sind die Daten korrekt interpretiert worden?

Code
# Die Spalte 'time' wurde als 'integer' interpretiert. Dabei handelt es
# sich offensichtlich um Zeitangaben.

Aufgabe 6

Die Spalte time ist eine Datum/Zeitangabe im Format JJJJMMTTHH (siehe meta.txt). Damit R dies als Datum-/Zeitangabe erkennt, müssen wir die Spalte in einem R-Format (POSIXct) einlesen und dabei R mitteilen, wie sie aktuell formatiert ist. Lies die Spalte mit as.POSIXct() ein und spezifiziere sowohl format wie auch tz.

Tipp
  • Wenn keine Zeitzone festgelegt wird, trifft as.POSIXct() eine Annahme (basierend auf Sys.timezone()). In unserem Fall handelt es sich aber um Werte in UTC (siehe metadata.csv)
  • as.POSIXcterwartet character: Wenn du eine Fehlermeldung hast die 'origin' must be supplied (o.ä) heisst, hast du der Funktion vermutlich einen Numeric übergeben.
Code
wetter$time <- as.POSIXct(as.character(wetter$time), format = "%Y%m%d%H", tz = "UTC")
Die neue Tabelle sollte so aussehen
stn time tre200h0
ABO 2000-01-01 00:00:00 -2.6
ABO 2000-01-01 01:00:00 -2.5
ABO 2000-01-01 02:00:00 -3.1
ABO 2000-01-01 03:00:00 -2.4
ABO 2000-01-01 04:00:00 -2.5
ABO 2000-01-01 05:00:00 -3.0
ABO 2000-01-01 06:00:00 -3.7
ABO 2000-01-01 07:00:00 -4.4
ABO 2000-01-01 08:00:00 -4.1
ABO 2000-01-01 09:00:00 -4.1

Aufgabe 7

Erstelle zwei neue Spalten mit Wochentag (Montag, Dienstag, etc) und Kalenderwoche. Verwende dazu die neu erstellte POSIXct-Spalte sowie eine geeignete Funktion aus lubridate.

Code
wetter$wochentag <- wday(wetter$time, label = T)
wetter$kw <- week(wetter$time)
stn time tre200h0 wochentag kw
ABO 2000-01-01 00:00:00 -2.6 Sa. 1
ABO 2000-01-01 01:00:00 -2.5 Sa. 1
ABO 2000-01-01 02:00:00 -3.1 Sa. 1
ABO 2000-01-01 03:00:00 -2.4 Sa. 1
ABO 2000-01-01 04:00:00 -2.5 Sa. 1
ABO 2000-01-01 05:00:00 -3.0 Sa. 1
ABO 2000-01-01 06:00:00 -3.7 Sa. 1
ABO 2000-01-01 07:00:00 -4.4 Sa. 1
ABO 2000-01-01 08:00:00 -4.1 Sa. 1
ABO 2000-01-01 09:00:00 -4.1 Sa. 1

Aufgabe 8

Erstelle eine neue Spalte basierend auf die Temperaturwerte mit der Einteilung “kalt” (unter Null Grad) und “warm” (über Null Grad)

Code
wetter$temp_kat[wetter$tre200h0 > 0] <- "warm"
wetter$temp_kat[wetter$tre200h0 <= 0] <- "kalt"
stn time tre200h0 wochentag kw temp_kat
ABO 2000-01-01 00:00:00 -2.6 Sa. 1 kalt
ABO 2000-01-01 01:00:00 -2.5 Sa. 1 kalt
ABO 2000-01-01 02:00:00 -3.1 Sa. 1 kalt
ABO 2000-01-01 03:00:00 -2.4 Sa. 1 kalt
ABO 2000-01-01 04:00:00 -2.5 Sa. 1 kalt
ABO 2000-01-01 05:00:00 -3.0 Sa. 1 kalt
ABO 2000-01-01 06:00:00 -3.7 Sa. 1 kalt
ABO 2000-01-01 07:00:00 -4.4 Sa. 1 kalt
ABO 2000-01-01 08:00:00 -4.1 Sa. 1 kalt
ABO 2000-01-01 09:00:00 -4.1 Sa. 1 kalt

  1. Vorteile von read_delim gegenüber read.csv: https://stackoverflow.com/a/60374974/4139249↩︎