Dynamisch durch Tabellenspalten iterieren

R - Fragen und Antworten

Heute schreibe ich über komplexere Abläufe in Schleifen – bzw. darüber, wie man in R dynamisch durch Tabellenspalten iterieren kann. Dieser Post ist die Antwort auf einen Kommentar, der sich auf das Thema Schleifen in R bezog (siehe hier):

„Ich möchte für einige Reihen (sagen wir A,B,C,…) diverse Befehle ausführen, wofür ich einen „Platzhalter“ bräuchte. […] Gibt es eine Möglichkeit, dies mit Schleifen durchzuführen?“

Operationen für mehrere Tabellenspalten durchführen

Ausgangslage

Wir haben mehrere Zeitreihen in einer Tabelle, jede in ihrer eigenen Spalte mit folgenden Namen: „ReiheA“, „ReiheB“, „ReiheC“, usw. Im Folgenden simulieren wir drei Zeitreihen mit je Werten aus 5 Jahren – bestehend aus Trend, Saisonalität und zufälliger Streuung:

#Set seed
set.seed(42)

#Create mock data list
N <- 5*365
x <- 1:N
yBase <- sin(x*2*pi / 365)
dateVec <- as.Date(Sys.time()) - c(N:1)
dataNames <- c("A", "B", "C")
dt <- data.table(Date=dateVec)
for (currentName in dataNames) {
  constant <- rnorm(1, 20, 5)
  trend <- rnorm(1, 0, 0.002)*x
  noise <- rnorm(N, 0, 1.0)
  currentSeries <- constant + trend + yBase + noise
  currentColumn <- paste0("Reihe", currentName)
  dt[, (currentColumn) := currentSeries]
}

Die Tabelle sieht dann wie folgt aus:
Tabelle mit mehreren Spalten für Zeitreihen

Das Ziel

Ziel ist es nun, für jede Zeitreihe (= jede Spalte) verschiedene Operationen auszuführen und die Resultate abzuspeichern. Je Spalte sollen folgende Schritte geschehen:

  • Umwandeln in ein time series object (ts)
  • Durchführen einer Schätzung (hier mit stlf)
  • Erstellen einer Prognose
  • Speichern der Prognosewerte
  • Anzeigen der Prognose

Als Extra habe ich beschlossen, eine finale Tabelle zu erstellen, in der sowohl Basisdaten als auch Prognose für die jeweilige Zeitreihe zu finden sind.

Eine Lösung mit Schleifen und Listen

Um den Code möglichst nachhaltig zu gestalten und Wiederholungen zu vermeiden, greife ich auch hier auf Schleifen zurück. Um mehrere verschiedenartige Objekte abzuspeichern werde ich Listen nutzen.

Die get-Funktion bei data.table

Neben der grundlegenden Struktur ist die wichtigste Funktion die get-Funktion in data.table (siehe hier für eine Einführung in data.table). Mit dieser Funktion kann man auf eine Spalte per Variable zugreifen (= der Name ist in einer Variable gespeichert). Wir müssen also nur die relevanten Spaltennamen in einem Vektor haben (columnNames <- names(dt)[-1]) und schon können wir durch diesen iterieren und für jede Spalte eine Operation durchführen (for (currentColumn in columnNames) { ... }):

#Iterate through column names
columnNames <- names(dt)[-1]
lst <- list()
dtForecast <- data.table()
for (currentColumn in columnNames) {
  #Create list for current series and perform operations
  subList <- list()
  subList$Name <- currentColumn
  subList$Data <- dt[, get(currentColumn)]
  subList$TSData <- ts(subList$Data, start=2015, frequency=365)
  subList$Fit <- stlf(subList$TSData)
  subList$Forecast <- forecast(subList$Fit, h=365)
  subList$Predictions <- subList$Forecast$mean
  plot(subList$Forecast)
  
  #Append sublist to list
  lst[[currentColumn]] <- subList
  
  #Create forecast data table and append to final table
  dtCur <- data.table(
    Name = subList$Name,
    Type = c(
      rep("Data", length(subList$Data)),
      rep("Prediction", length(subList$Predictions))
    ),
    Series = c(subList$Data, subList$Predictions)
  )
  dtCur[, Case := sequence(.N)]
  dtForecast <- rbindlist(list(dtForecast, dtCur))
}

Wir sehen: Für jede Zeitreihe wird nun eine Liste subList angelegt, welche wiederum in einer Hauptliste lst gespeichert wird (lst[[currentColumn]] <- subList). Über subList$Data <- dt[, get(currentColumn)] wird die Zeitreihe erstmal als Data abgespeichert. Anschließend können wir alles weitere über subList$Data machen. Mit str(lst) können wir uns ganz zum Schluss die Struktur der finalen Liste anschauen. Außerdem wird beim Iterieren jeweils ein Plot erstellt:

Zeitreihenprognose STL

Nun habe ich gezeigt, wie man in R dynamisch durch Tabellenspalten iterieren kann. Ich hoffe, dass mein Ansatz für das dargestellte Problem hilfreich und verständlich ist. Kommentiert oder schreibt mir gerne, wenn einige Fragen noch unbeantwortet sind oder wenn es ein Wunsch für ein Thema gibt.

Beste Grüße und frohe Weihnachten!

Add a comment

*Please complete all fields correctly

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.

Ähnliche Posts

tjohannsen