Die for-Schleife in R

Schleifen mit einer Z√§hlvariable werden eingesetzt, wenn bekannt ist, wie oft ein gewisser Vorgang wiederholt werden muss (wobei die Anweisungen nicht exakt identisch sind, sondern meist vom Wert der Z√§hlvariable abh√§ngen). Die Syntax der for-Schleife sowie einige mit ihr verbundene Spitzfindigkeiten werden erkl√§rt. Zus√§tzliche Kontrolle √ľber den Ablauf einer Schleife erh√§lt man durch break (vorzeitiges Verlassen der Schleife) und next (sofortiger √úbergang zum n√§chsten Wert der Z√§hlvariable).
Noch keine Stimmen abgegeben
Noch keine Kommentare

Einordnung des Artikels

Einf√ľhrung

Arten von Schleifen

Nach der Alternative ist die Schleife (oder Iteration) die wichtigste Kontrollstruktur, die den Ablauf von Programmen regelt. Mit einer Schleife ist gemeint, dass etwas wie eine Liste abgearbeitet werden muss, wobei f√ľr jeden Listen-Eintrag dieselben Befehle ausgef√ľhrt werden m√ľssen In Pseudocode und formale Sprachen im Abschnitt Schleife (Iteration) wurden

  • die kopfgesteuerte Schleife,
  • die fu√ügesteuerte Schleife und
  • die Schleife mit Z√§hlvariable

im Pseudocode vorgestellt. Letztere wird in R mit der for-Anweisung realisiert; und da dies diejenige Schleife ist, die am klarsten strukturiert ist, wird sie zuerst besprochen.

F√ľr eine ausf√ľhrliche Einf√ľhrung in Schleifen ‚Äď unabh√§ngig von einer Programmiersprache ‚Äď ist oben zitierter Abschnitt zu empfehlen.

Die Schleife mit Zählvariable (for-Schleife)

Das Paradebeispiel einer Schleife, das in Pseudocode und formale Sprachen im Abschnitt Schleife (Iteration) diskutiert wird, ist:

Es sollen die Personalien aller sich in einem Raum befindlichen Personen aufgenommen werden.

Das Problem wird zunächst in 2 Teilprobleme zerlegt:

  1. Was ist zu tun, um von einer Person die Personalien aufzunehmen?
  2. Wie sorgt man daf√ľr, dass alle Personen durchlaufen werden?

Im Pseudocode lautet die Lösung des Problems etwa

F√ľr i = 1 bis N Schrittweite 1
    PersonalienAufnehmen(P(i))

Dabei wird vorausgesetzt:

  1. Es ist bekannt, dass N Personen im Raum sind.
  2. Die Personen sind durchnumeriert und können mit P(i), i = 1, 2, ..., N aufgerufen werden.
  3. Das erste Teilproblem oben ist bereits gelöst: Der Aufruf des Unterprogramms PersonalienAufnehmen(P(i)) nimmt die Personalien der Person i auf.

Man erkennt dann, wie durch Zeile 1 das zweite Teilproblem gelöst wird:

Es wird eine Z√§hlvariable i eingef√ľhrt, √ľber die die Personen aufgerufen werden k√∂nnen. Die Z√§hlvariable l√§uft von 1 bis N bei einer Schrittweite von 1. Dies garantiert, dass jede Person aufgerufen wird.

Man kann die Schleife auch als Abk√ľrzung f√ľr die Folge von N Anweisungen sehen:

PersonalienAufnehmen(P(1))
PersonalienAufnehmen(P(2))
...
PersonalienAufnehmen(P(N))

Da R auf Vektoren basiert, wird auch die Schleife mit Z√§hlvariable √ľber einen Vektor konfiguriert: Man gibt sich einen Vektor seq vor, dessen Komponenten nacheinander von der Z√§hlvariable var angenommen werden. Der Ausdruck expr ist ein beliebiger Block von Anweisungen, der mit jedem Wert von var ausgef√ľhrt wird.

for(var in seq) expr

Darum dass nach einem Abarbeiten von expr der n√§chste Wert von var gesetzt wird und wiederum expr abgearbeitet wird, muss sich der Programmierer nicht k√ľmmern ‚Äď dies ist gerade die Ausf√ľhrung der Schleife. (Ebenso, dass die Schleife verlassen wird, wenn var den letzten Wert aus seq angenommen hat und die zugeh√∂rigen Anweisungen abgearbeitet wurden.)

Bezeichnungen: Schleife, Schleifenkörper, Schleifen-Durchlauf

F√ľr das Beispiel, das oben im Pseudocode formuliert wurde, n√§mlich

F√ľr i = 1 bis N Schrittweite 1
    PersonalienAufnehmen(P(i))

sollen nun die Bezeichnungen vereinbart werden, die im Folgenden verwendet werden.

Angenommen es befinden sich 7 Personen im Raum, dann sagt man auch gerne, dass die Schleife 7-mal durchlaufen werden muss. Diese Sprechweise ist etwas irref√ľhrend und soll nun pr√§zisiert werden.

Die Anweisung PersonalienAufnehmen(P(i)) wird als der Schleifenkörper bezeichnet; weiter unten wird erklärt, dass hier auch mehrere Anweisungen stehen können. Die Anweisungen im Schleifenkörper hängen vom aktuellen Wert der Zählvariable i ab.

Werden jetzt von allen 7 Personen die Personalien aufgenommen, so sollte man besser sagen: Der Schleifenkörper wird 7-mal durchlaufen. Das Aufnehmen der Personalien einer Person wird auch als ein Schleifen-Durchlauf bezeichnet.

Die eigentliche Schleife besteht aus sämtlichen Schleifen-Durchläufen. Wenn die Zählvariable ihren letzten Wert angenommen hat und alle Personen abgearbeitet wurden, wird die Schleife verlassen; es folgen Anweisungen, die nicht mehr zur Schleife gehören.

In salopper Sprechweise wird oft der Begriff Schleife sowohl f√ľr die Gesamtheit aller Schleifen-Durchl√§ufe als auch f√ľr einen einzigen Schleifen-Durchlauf verwendet. Achten Sie beim Lesen der einschl√§gigen Literatur an dieser Stelle darauf, wie der Begriff Schleife eingesetzt wird.

Oft ‚Äď und gleichwertig ‚Äď wird die Schleife auch als Iteration bezeichnet. Ein Schleifen-Durchlauf ist dann ein Iterationsschritt. Den Schleifenk√∂rper nennt man dann den K√∂rper (oder den Rumpf) der Iteration.

Auswahl der Beispiele

Die Beispiele, mit denen im Folgenden Schleifen erl√§utert werden, lassen sich in R auch deutlich einfacher realisieren ‚Äď weil entsprechende Funktionen bereits implementiert sind. Die einfacheren L√∂sungen werden dann nur verwendet, um eine Kontrollrechnung durchzuf√ľhren.

Ziel diese Kapitels ist es nat√ľrlich, eine Einf√ľhrung in Schleifen zu geben und nicht die vorgestellten Aufgaben m√∂glichst einfach zu l√∂sen.

Gerade im Zusammenhang mit Schleifen muss darauf hingewiesen werden, dass es in R die sogenannte Familie von apply()-Funktionen gibt, mit der sich viele Schleifen vermeiden lassen. Diese Familie wird aber erst später besprochen, wenn erklärt wurde, wie man selber Funktionen definiert.

Die Syntax der for-Schleife

Der einfachste Fall

Wie in R eine Schleife allgemein aussieht, wurde oben bereits gezeigt. Die allgemeine Syntax soll jetzt an einem einfachen Beispiel erklärt werden: Die Zahlen von 1 bis 100 werden mit einer for-Schleife addiert.

idx <- (1:100)
summe <- 0

for(i in idx){
  summe <- summe + i
}

cat("Summe: ", summe, "\n")
# Summe:  5050 

# Kontrolle:
sum(idx)
# [1] 5050

Zeile 1: Es wird der Vektor der Zahlen vorbereitet, die addiert werden sollen.

Zeile 2: Es wird eine Variable summe vorbereitet, die die Zwischensummen berechnet; am Ende der Schleifen-Durchl√§ufe muss sie die Gesamtsumme beinhalten. Diese Hilfsvariable muss nat√ľrlich am Anfang den Wert 0 besitzen.

Zeile 4 bis 6: Die eigentliche for-Schleife. Nach dem Schl√ľsselwort for folgt in runden Klammern die Konfiguration der Schleife:

  • Man kann den Namen der Z√§hlvariable selbst bestimmen (hier i).
  • Das Schl√ľsselwort in besagt, dass i alle Werte des folgenden Vektors durchl√§uft.
  • Der Vektor, der durchlaufen wird, sind hier die Zahlen von 1 bis 100, die zuvor in idx abgespeichert wurden. Man h√§tte statt Zeile 4 nat√ľrlich auch schreiben k√∂nnen for(i in (1:100)){ ; der Vektor idx wurde nur eingef√ľhrt, um ausdr√ľcklich darauf hinzuweisen, dass hier meist ein Vektor steht. (Welche anderen Objekte anstelle eines Vektors verwendet werden k√∂nnen, wird weiter unten erkl√§rt.)

Zeile 8 und 9: Nach Beendigung der Schleife wird die Variable summe ausgegeben; sie liefert den Wert 5050.

Zeile 11 und 12. Die Kontrollrechnung mit der Funktion sum() liefert den selben Wert.

Was gehört vor die Schleife, in die Schleife und nach die Schleife?

F√ľr das Verst√§ndnis des Ablaufs einer Schleife ist es wichtig, sich zu fragen:

  • Welche Anweisungen m√ľssen vor der Schleife stehen (und diese vorbereiten)?
  • Welche Anweisungen stehen im Schleifenk√∂rper?
  • Welche Anweisungen stehen nach der Schleife?

Man kann dazu obiges Beispiel verwenden und die Anweisungen verschieben.

Zuerst wird die Anweisung summe <- 0 in den Schleifenkörper verschoben:

idx <- (1:100)

for(i in idx){
  summe <- 0
  summe <- summe + i
}

cat("Summe: ", summe, "\n")
# Summe:  100 

# Kontrolle:
sum(idx)
# [1] 5050

Wie kann man das Ergebnis 100 erklären?

Wird summe bei jedem Durchlauf der Schleife auf 0 zur√ľckgesetzt, stimmt nach dem Durchlauf einer Schleife summe genau mit dem aktuellen Wert von i √ľberein. Nach dem letzten Durchlauf ist somit summe mit 100 belegt.

Was passiert, wenn die Ausgabe cat("Summe: ", summe, "\n") in den Schleifenkörper verschoben wird?

idx <- (1:100)
summe <- 0

for(i in idx){ 
  summe <- summe + i
  cat("Summe: ", summe, "\n")
}

# Kontrolle:
sum(idx)
# [1] 5050

Jetzt wird bei jedem Schleifen-Durchlauf eine Ausgabe erzeugt, nämlich mit dem aktuellen Wert von summe. Dies ergibt 100 Ausgaben mit den Werten: 1, 3, 6, 10, ..., 5050.

Diese Zwischensummen sind hier irrelevant, gefragt war nur der letzte Zahlenwert von summe. Um die Zwischensummen zu unterdr√ľcken, muss die Ausgabe nach der Schleife erfolgen.

Man kann versuchen, die Antwort auf die Frage "was gehört vor, in und nach die Schleife?" etws allgemeiner zu formulieren:

  1. Vor die Schleife gehören Anweisungen, die die Schleife vorbereiten, also etwa die Definition von Variablen, die sich auf die Gesamtheit der Schleifen-Durchläufe beziehen. Dies sind meist einmalige Anweisungen, die nicht wiederholt werden.
  2. In den Schleifenk√∂rper geh√∂ren Anweisungen, die bei jedem Durchlauf ausgef√ľhrt werden m√ľssen (also so oft wiederholt werden wie es Schleifen-Durchl√§ufe gibt).
  3. Nach der Schleife stehen Anweisungen, die sich wieder auf die Gesamtheit der Schleifen-Durchläufe beziehen, also etwa die Weiterverarbeitung von Variablen, die sich auf die Gesamtheit der Schleifen beziehen.

Einige Spitzfindigkeiten

Die geschweiften Klammern

In der Dokumentation wird die for-Schleife erklärt durch:

for(var in seq) expr

Im Beispiel oben lautete die Schleife (hier wird idx nicht ausdr√ľcklich definiert):

for(i in (1:100)){
  summe <- summe + i
}

Es stellen sich sofort zwei Fragen:

  • Wann muss man die geschweiften Klammern setzen und wann kann man sie weglassen?
  • Kann man den Schleifenk√∂rper in die Zeile mit for schreiben oder muss man eine neue Zeile beginnen?

Zun√§chst zur Bedeutung der geschweiften Klammern: Die Anweisungen innerhalb der geschweiften Klammern bilden einen Block, der insgesamt den Schleifenk√∂rper ausmacht. Besteht der Schleifenk√∂rper aus mehreren Anweisungen, so m√ľssen geschweifte Klammern gesetzt werden.

Besteht dagegen der Schleifenkörper nur aus einer einzigen Anweisung, so kann man die geschweiften Klammern weglassen. Es gibt jetzt zwei Möglichkeiten:

  1. Der Schleifenkörper steht in der Zeile mit for.
  2. Der Schleifenkörper steht in einer eigenen Zeile.

Die folgenden Skripte zeigen diese zwei Möglichkeiten:

summe <- 0

for(i in (1:100))
  summe <- summe + i

cat("Summe: ", summe, "\n")
# Summe:  5050
summe <- 0

for(i in (1:100))       summe <- summe + i

cat("Summe: ", summe, "\n")
# Summe:  5050

Die beiden Skripte sind identisch.

Setzt man keine geschweiften Klammern f√ľr den Schleifenk√∂rper, dann wird der Befehl, der nach der for-Anweisung kommt, ‚Äď und nur dieser Befehl ‚Äď als der Schleifenk√∂rper interpretiert; im Beispiel ist dies jeweils der Befehl summe <- summe + i . Der n√§chste Befehl ist bereits der Befehl nach der Schleife.

Empfohlen wird aber die Schreibweise, die selbst f√ľr einen einzigen Befehl im Schleifenk√∂rper geschweifte Klammern verwendet. Die Gr√ľnde daf√ľr sind einfach:

  1. Der Schleifenkörper ist kar als solcher zu erkennen und von den Befehlen nach der Schleife zu unterscheiden.
  2. Sollen sp√§ter Befehle im Schleifenk√∂rper erg√§nzt werden, muss man nicht umst√§ndlich Klammern hinzuf√ľgen (gerade zum Testen muss man oft Ausgaben in den Schleifenk√∂rper einbauen).

Die Unver√§nderlichkeit des Vektors, √ľber den iteriert wird

In den bisherigen Beispielen wurde meist vor der Schleife ein Vektor idx definiert, √ľber den in der Schleife iteriert wird. Man kann hier nat√ľrlich auf die Idee kommen, diesen Vektor idx in der Schleife zu ver√§ndern. L√§sst sich dadurch das Verhalten der Schleife, die ja eigentlich durch for(i in idx) kontrolliert wird, nachtr√§glich anpassen? Die Antwort ist nein und wird durch das folgende Beispiel best√§tigt:

idx <- (1:100)
summe <- 0

for(i in idx){
  summe <- summe + i
  if(i > 50){
    idx <- append(idx, i)
  }
}

cat("Summe: ", summe, "\n")
Summe:  5050 

length(idx)
# [1] 150

sum(idx)
# [1] 8825

Zeile 1, 2, 4 und 5: Dies sind die bekannten Anweisungen zur Berechnung der Summe der Zahlen von 1 bis 100.

Zeile 6 bis 8: Neu ist die if-Anweisung, in der f√ľr i = 51, 52, ..., 100 der Vektor idx um die entsprechende Zahl erweitert wird.

Wenn der veränderte Vektor in der Iteration verwendet wird, ergibt sich eine Endlos-Schleife, da immer wieder die Zahlen 51, 52, ..., 100 an idx angehängt werden. Die Ausgaben zeigen aber Folgendes:

  • Der Vektor, √ľber den iteriert wird, ist das Objekt idx so wie es definiert wurde als es in for(i in idx) an die Schleife √ľbergeben wurde. Eine nachtr√§gliche √Ąnderung ist f√ľr den Ablauf der Schleife unerheblich.
  • Das Objekt idx wird in der Schleife tats√§chlich ver√§ndert: man erkennt an den Ausgaben, dass die Zahlen 51, 52, ..., 100 einmal an den urspr√ľnglichen Vektor idx angeh√§ngt wurden.

Iterierbare Objekte

Andere Vektoren als (1:n)

Bisher wurde in allen Beispielen √ľber den Vektor (1:100) iteriert. Dies k√∂nnte den Eindruck erwecken, dass nur Vektoren dieser Art als Wertemenge f√ľr die Z√§hlvariable zul√§ssig sind. Die Dokumentation ist dagegen so zu verstehen, dass ein beliebiger Vektor eingesetzt werden kann. Im folgenden Beispiel wird der Vektor gew√§hlt, der aus den ungeraden Zahlen 1, 3, 5, ..., 99 besteht, und √ľber diesen iteriert:

idx <- seq(from = 1, to = 99, by = 2)

summe <- 0

for(i in idx){
  summe <- summe + i
}

cat("Summe: ", summe, "\n")
# Summe:  2500

# Zur Kontrolle:
sum(idx)
# [1] 2500

Die Abarbeitung der Schleife kann man sich so vorstellen:

  • Die Z√§hlvariable, hier i, nimmt beim ersten Iterationsschritt den Wert der ersten Komponente von idx an,
  • beim zweiten Iterationsschritt ist i gleich der zweiten Komponente von idx und so weiter.
  • Beim letzten Iterationsschritt stimmt i mit der letzten Komponente von idx √ľberein, also ist i == 99 .
  • Jetzt besitzt idx keine weitere Komponente und daher wird die Schleife verlassen und der cat()-Befehl ausgef√ľhrt (Zeile 9).

Damt sollte klar sein, dass man anstelle von idx jeden beliebigen Vektor einsetzen kann. Der Vektor muss auch nicht aus ganzen Zahlen bestehten wie das folgende Beispiel zeigt:

for(i in c(TRUE, FALSE, TRUE)){
    cat("i: ", i, "\n")
}
# i:  TRUE 
# i:  FALSE 
# i:  TRUE

Andere Objekte als Vektoren

Zur Iteration können nicht nur Vektoren eingesetzt werden, sondern jedes Objekt, das in einen Vektor verwandelt werden kann, zum Beispiel:

  • Spalten eines Dataframes,
  • Spalten oder Zeilen einer Matrix,
  • Komponenten einer Liste,
  • eine Liste, wobei man bei der Verarbeitung der Komponenten im Schleifenk√∂rper darauf achten muss, dass die Komponenten unterschiedliche Datentypen haben k√∂nnen.

Das folgende Beispiel definiert zun√§chst eine Liste und iteriert in der for-Schleife √ľber ihre Komponenten:

book <- list(author = "R-Expert", title = "Introduction to R", year = 2019)

for(i in book){
  cat("i: ", i, "||", storage.mode(i), "\n")
  storage.mode(i)
}
# i:  R-Expert || character 
# i:  Introduction to R || character 
# i:  2019 || double

Selbst eine Matrix kann verwendet werden, da eine Matrix intern als Vektor gespeichert wird. Iteration √ľber eine Matrix bedeutet dann, dass der zugrunde liegende Vektor verwendet wird. Man muss dabei eventuell beachten, in welcher Reihenfolge der Vektor die Matrix-Elemente liefert.

Das folgende Skript zeigt ein einfaches Beispiel, bei dem ene Matrix definiert wird und anschließend wird die Summe der Komponenten bestimmt; an der Ausgabe erkennt man, in welcher Reihenfolge die Komponenten angearbeitet werden:

v <- (1:6)
m <- matrix(data = v, nrow = 2, byrow = TRUE)
m
#    [,1] [,2] [,3]
# [1,]    1    2    3
# [2,]    4    5    6

summe <- 0

for(i in m){
  cat("i: ", i, "\n")
  summe <- summe + i
}

# i:  1 
# i:  4 
# i:  2 
# i:  5 
# i:  3 
# i:  6 

cat("Summe: ", summe, "\n")
# Summe:  21

Nicht ganz klar ist, wie sich Faktoren verhalten, wenn √ľber sie iteriert wird. Denn Faktoren aus character-Vektoren werden intern als integer-Vektoren abgespeichert.

sample <- c("A", "A", "E", "C", "B", "A", "E", "C", "A")

length(sample)    # 9

sample
# [1] "A" "A" "E" "C" "B" "A" "E" "C" "A"

mode(sample)            # [1] "character"

sf <- factor(x = sample)
sf
# [1] A A E C B A E C A
# Levels: A B C E

for(i in sample){
  cat("i: ", i, "\n")
}
# i:  A 
# i:  A 
# i:  E 
# i:  C 
# i:  B 
# i:  A 
# i:  E 
# i:  C 
# i:  A 

for(i in sf){
  cat("i: ", i, "||", storage.mode(i), "\n")
}
# i:  A || character 
# i:  A || character 
# i:  E || character 
# i:  C || character 
# i:  B || character 
# i:  A || character 
# i:  E || character 
# i:  C || character 
# i:  A || character

Zeile 1 bis 13: Es wird ein character-Vektor sample definiert und untersucht. Aus dem Vektor wird ein Faktor sf erzeugt und ausgegeben.

Zeile 15 bis 26: Wird √ľber den character-Vektor sample iteriert, erkennt man in den Ausgaben die Zeichen, die in den Komponenten von sample abgespeichert sind.

Zeile 28 bis 40: Wird √ľber den Faktor sf iteriert, so sind die Komponenten ebenfalls Zeichen; man erkennt dies ausdr√ľcklich an der Ausgabe von storage.mode(i) .

Die Schl√ľsselw√∂rter break und next

So wie die Schleifen bisher behandelt wurden, kann man sie noch nicht sehr flexibel einsetzen: Allein der in for(i in seq) definierte Vektor seq bestimmt den Ablauf der Schleife:

  • Die Z√§hlvariable i nimmt nacheinander die Werte der Komponenten von seq an.
  • F√ľr jeden Wert von i wird der gesamte Schleifenk√∂rper abgearbeitet.
  • Nach der letzten Komponente von seq wird die Schleife verlassen.

Manchmal ist es aber w√ľnschenswert, dass

  • unter gewissen Umst√§nden, die Schleife vorzeitig verlassen wird oder dass
  • nur ein Teil des Schleifenk√∂rpers abgearbeitet wird (und sofort der n√§chste Durchlauf startet).

Diese beiden M√∂glichkeiten werden durch die Schl√ľsselw√∂rter break und next realisiert:

  • break sorgt daf√ľr, dass die Schleife vorzeitig verlassen wird.
  • next sorgt daf√ľr, dass der folgende Teil des Schleifenk√∂rpers √ľbersprungen wird und die Z√§hlvariable sofort den n√§chsten Wert annimmt.

Es folgen zwei Beispiele, die den Einsatz von break und next demonstrieren.

1. Beispiel: Der Einsatz von break

Es sollen wieder die Zahlen von 1 bis 100 addiert werden, aber die Berechnung soll vorzeitig abbrechen, wenn die Summe größer als 1000 ist. In diesem Fall sollen der aktuelle Wert der Zählvariable und die Summe ausgegeben werden.

Das folgende Skript zeigt eine mögliche Realisierung:

idx <- (1:100)
summe <- 0

for(i in idx){
  summe <- summe + i
  if(summe > 1000){
    cat("Index: ", i, " || Summe: ", summe, "\n")
    break
  }
}

# Index:  45  || Summe:  1035 

cat("Summe: ", summe, "\n")
# Summe:  1035 

# Kontrolle:
sum(1:45)
# [1] 1035

Zeile 6 bis 9: Innerhalb des Schleifenk√∂rpers wird abgefragt, ob der aktuelle Wert von summe 1000 √ľberschreitet. Falls ja, werden der aktuelle Wert der Z√§hlvariable und der Summe ausgegeben. Anschlie√üend sorgt in Zeile 8 der Befehl break daf√ľr, dass die Schleife verlassen wird.

Zeile 12: Die Ausgabe aus der cat()-Anweisung im if-Zweig.

Zeile 14 und 15: Die Ausgabe von summe nach der Schleife zeigt, dass die Schleife tatsächlich abgebrochen wurde.

Zeile 18 und 19: Zur Kontrolle wird die Summe der Zahlen von 1 bis 45 berechnet.

2. Beispiel: Der Einsatz von next

Es sollen wieder die Zahlen von 1 bis 100 addiert werden, aber Zahlen, die durch 7 teilbar sind, sollen nicht eingerechnet werden.

Das folgende Skript zeigt eine mögliche Realisierung:

idx <- (1:100)
summe <- 0

for(i in idx){
  if(i %% 7 == 0){
    next
  }
  summe <- summe + i
}

cat("Summe: ", summe, "\n")
# Summe:  4315 

# Kontrolle
5050 - sum(7*(1:14))
# [1] 4315

Zeile 5 bis 7: Falls i durch 7 teilbar ist, wird next aufgerufen und dadurch der n√§chste Iterationsschritt angesto√üen; der Befehl summe <- summe + i wird f√ľr durch 7 teilbare i nicht ausgef√ľhrt.

Zeile 11 bis 7: Die Summe ergibt jetzt nur noch 4315. Zur Kontrolle wird von 5050 die Summe der durch 7 teilbaren Zahlen (also 7, 14, ..., 98) abgezogen.

Verschachtelte Schleifen

Oben wurde erkl√§rt, dass der Schleifenk√∂rper in geschweifte Klammern eingeschlossen werden soll (falls er nur aus einer einzigen Anweisung besteht, k√∂nnte man die Klammern weglassen). Da man den Schleifenk√∂rper mit beliebigen Anweisungen f√ľllen kann, ist es m√∂glich dort wiederum eine Schleife einzubauen; man spricht dann von verschachtelten Schleifen.

Eine typische Anwendung daf√ľr ist, dass man die Werte der Komponenten einer Matrix durch zwei Iterationen setzt:

  • die √§u√üere Iteration durchl√§uft die Zeilen-Indizes,
  • die innere Iteration durchl√§uft die Spalten-Indizes.

Im Kapitel Matrizen in R: der Datentyp matrix wurde gezeigt, wie man spezielle Matrizen erzeugen kann. Manchmal ist es einfacher, die Werte der Komponenten einzeln zu berechnen; das folgende Beispiel zeigt, wie man dies mit zwei Schleifen erledigen kann:

v <- (1:6)
S2 <- matrix(data = 0, nrow = 6, ncol = 6)

for(i in v){      # i: Zeilenindex
  for(j in v){    # j: Spaltenindex
    S2[i, j] <- i + j
  }
}

S2
#      [,1] [,2] [,3] [,4] [,5] [,6]
# [1,]    2    3    4    5    6    7
# [2,]    3    4    5    6    7    8
# [3,]    4    5    6    7    8    9
# [4,]    5    6    7    8    9   10
# [5,]    6    7    8    9   10   11
# [6,]    7    8    9   10   11   12

outer(X = v, Y = v, FUN = "+")
#      [,1] [,2] [,3] [,4] [,5] [,6]
# [1,]    2    3    4    5    6    7
# [2,]    3    4    5    6    7    8
# [3,]    4    5    6    7    8    9
# [4,]    5    6    7    8    9   10
# [5,]    6    7    8    9   10   11
# [6,]    7    8    9   10   11   12

In diesem Beispiel wird die Augensumme beim zweimaligen W√ľrfeln berechnet. Dazu wird der Vektor v der m√∂glichen Ergebnisse bei einem Wurf vorbereitet (Zeile 1) sowie eine Matrix S2 mit geeigneten Dimensionen (Zeile 2).

In den verschachtelten Schleifen (Zeile 4 bis 8) werden die Komponenten durch die Summe von Zeilen- und Spalten-Index gesetzt. Dabei ist i der Zeilen-Index und j der Spalten-Index.

Die Ausgabe von S2 zeigt die Matrix der Augensummen (Zeile 10 bis 17). Man kann diese Matrix auch einfacher mit Hilfe der Funktion outer() erzeugen (Zeile 19).

Zusammenfassung

Bei einer for-Schleife durchl√§uft die Z√§hlvariable var die Werte der Komponenten des Vektors seq. F√ľr jede dieser Komponenten wird die Anweisung expr ausgef√ľhrt, die √ľblicherweise von var abh√§ngig ist.

for(var in seq) expr

Weitere Informationen √ľber for-Schleifen findet man in der Dokumentation unter ?Control im Paket base.