1 Das Problem

Eine Frage dieser Art taucht im R-Forum unter forum.r-statistik.de häufiger auf: Im folgenden Code wird hundert Mal ein Ergebnis berechnet, aber nachher sind bis auf das letzte alle Ergebnisse weg:

for(i in 1:100)
  ergebnis <- 5.43*i + i^exp(i) # hier beliebig komplexes Problem einsetzen

Im Folgenden sind drei Lösungsmöglichkeiten für dieses Problemmuster dargestellt.

Wenn Du im Forum auf diese Seite verwiesen worden bist, dann sollte Dir der folgende Code helfen können, Dein Problem zu lösen.

2 Abstraktion der jeweiligen Rechenaufgabe

Sei f(x) eine Funktion, die einen Wert zurück gibt. Wir machen es ganz einfach:

f <- function(x) "bla"

3 Werte merken mit der for-Schleife

diese Funktion rufen wir jetzt für die Werte 1 bis 10 auf:

for(i in 1:10)
  ergebnis <- f(i)

dabei wird jedes vorherige Ergebnis überschrieben und nur das letzte bleibt erhalten

print(ergebnis)
## [1] "bla"

Probieren wir es also anders: wir kündigen zunächst an, dass wir eine Variable ‘ergebnis’ verwenden wollen, weisen ihr aber noch keinen Wert zu

ergebnis <- NULL

jetzt die neue Schleife

for(i in 1:10)
    ergebnis <- c(ergebnis, f(i))

Diesesmal wir das Ergebnis von f(i) jedesmal an die bisherigen Ergebnisse angehängt, und die bisherigen Ergebnisse bleiben erhalten:

print(ergebnis)
##  [1] "bla" "bla" "bla" "bla" "bla" "bla" "bla" "bla" "bla" "bla"

Wenn wir jetzt auf das 5. Ergebnis zugreifen wollen, ist das ganz einfach:

print(ergebnis[5])
## [1] "bla"

4 apply und Freunde

Eleganter ist es oft, die Schleife in einem Aufruf aus der apply-Familie zu verstecken. Dazu gehen wir davon aus, dass unsere Ausgangswerte in einem Vektor oder einer Liste vorliegen.

Beispiel für einen Vektor:

meineX <- 1:20
print(meineX)
##  [1]  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20

Jetzt wenden wir unsere Funktion f(x) = “bla”, die wir von oben kennen und die wir oben definiert haben, auf alle Elemente dieses Vektors an:

meineY <- sapply(X = meineX, FUN = f)
print(meineY)
##  [1] "bla" "bla" "bla" "bla" "bla" "bla" "bla" "bla" "bla" "bla" "bla"
## [12] "bla" "bla" "bla" "bla" "bla" "bla" "bla" "bla" "bla"

Dieses Vorgehen ist typisch für die sogenannte Funktionale Programmierung. Die Gefahr, ein Zwischenergebnis zu überschreiben, gibt es dabei nicht. in funktionalen Programmiersprachen heißt diese Funktion oft ‘map’, in R heißt sie ‘apply’, oder ‘sapply’ oder ‘lapply’ oder ‘replicate’ oder ganz selten mal ‘rapply’. Das kommt immer auf den Kontext an. Da helfen wir im Forum auch gerne.

5 Vectorize

Vektorisierte Funktionen sind groß in R. Die Funktion ‘Vectorize’ (Achtung: Mit großem ‘V’) macht es oft ganz leicht, eigene Funktionen vektortauglich zu machen. Im Fall unserer oben aufgeführten Beispielfunktion f machen wir z. B.:

f2 <- Vectorize(f)

und können jetzt ganz einfach f2 auf unseren Vektor mit Ausgangswerten anwenden:

meineX <- 1:20
meineY <-f2(meineX)
print(meineY)
##  [1] "bla" "bla" "bla" "bla" "bla" "bla" "bla" "bla" "bla" "bla" "bla"
## [12] "bla" "bla" "bla" "bla" "bla" "bla" "bla" "bla" "bla"

Wenn wir Vectorize einmal auf die Funktion f angewendet haben, wurde eine Funktion geschaffen, die sich immer auf ganze Vektoren bezieht, ohne dass wir jedes Mal ‘sapply’ oder ähnliches aufrufen müssten. Das ist idiomatisches R!

Ich hoffe, das hilft. Weitere Fragen gerne im Forum.

LG, Bernhard