Pętle w języku R

(kliknij w obrazek, żeby zobaczyć pliki źródłowe)

Pętle

W każdym języku programowania występują specyficzne instrukcje sterujące, które pozwalają na zapanowanie nad wykonywanym kodem. Odnosząc się do pętli należy postrzegać je jako instrukcje, które pozwalają na wielokrotne wykonywanie wskazanych komend. Pętle (instrukcje w ich wnętrzu) wykonują się tak długo, aż nie zostanie spełniony warunek wyjścia.

Jeśli nadal nie czujesz czym są pętle, postaram się to zobrazować.
Z pętlami jest jak z żonami i wynoszeniem śmieci:

Żona powtarza codziennie mężowi: “Wynieś śmieci”, kolejnego dnia: “No wynieś te śmieci”.
Nieczuły mąż, nie wysłuchuje próśb swojej kobiety “Kochanie, nie che mi się!” , nie chce mu się pofatygować do kontenera – warunek wyjścia z pętli nie zostaje spełniony. W związku z całą sytuacją, kobieta cały czas powtarza i powtarza.
W końcu mąż się opanowuje i w środę wynosi śmieci “Kochanie, wyniosłem śmieci”warunek wyjścia z pętli zostaje spełniony.
Żona już nie musi powtarzać swoich próśb.
I wszyscy żyją długo i szczęśliwie*.
*do pojawienia się kolejnych śmieci

Tyle słowem wstępu 🙂 Wracając do bardziej technicznej nomenklatury, w R wyróżniamy 3 rodzaje pętli, poniżej postaram się je zrozumiale opisać.

Pętla typu REPEAT

REPEAT – pętla nieskończona, która będzie non stop wykonywała kod, zawarty w jej wnętrzu.

repeat{
print("Wynies smieci!")
Sys.sleep(1)
}

W powyższym kodzie tworzymy zmienną licznik i nadajemy jej wartość 0, a następnie tworzymy pętlę repeat. Program wyświetla tekst, po czym czeka bezczynnie sekundę.

Jest idealny przykład na to jak nie programować. Program zablokował się, wpadł w pętlę nieskończoną, sam nigdy z niej nie wyjdzie (chyba, że wyłączymy komputer, wymusimy zamknięcie środowiska itp.). Zazwyczaj jest to zjawisko niepożądane, chcąc uniknąć takiej sytuacji uniknąć należy w odpowiedni sposób przerwać wykonywanie się programu.

W środowisku RSudio możemy w dowolnym momencie przerwać wykonywanie się programu wciskając czerwony przycisk STOP:

Należy wówczas zastosować instrukcję break. Dodatkowo, najczęściej implementuje się ją wewnątrz instrukcji warunkowej if, gdzie wskazujemy warunki wyjścia z pętli: w naszym przypadku będzie to, gdy wartość zmiennej licznik będzie wynosić 5.  Poniżej przykładowy kod:

licznik <- 1
repeat{
if(licznik == 5)
{
break
}

print("Wynies smieci!")
licznik <- licznik + 1
Sys.sleep(1)

}

Pętla typu WHILE

To przykład pętli, która w swojej definicji posiada możliwość definiowania warunku wyjścia z jej wnętrza. Zaraz po słowie while występują warunek ten uwieszany jest wewnątrz nawiasów.

# Author: Lukasz Joksch
# Source www.joksch.pl

prosbyZony <- c("wyrzuc smieci!","no wyrzuc te smieci!","wyrzuc w koncu smieci!","nareszcie!")
odpowiedziMeza <- c("nie chce mi sie!","nie chce mi sie!","nie chce mi sie!","teraz mam spokoj!")

licznik <- 1

while(licznik<5){
print("Zona:")
print(prosbyZony[licznik])
print("------------------------")
Sys.sleep(1)
print("Maz")
print(odpowiedziMeza[licznik])
Sys.sleep(1)
print("------------------------")

licznik <- licznik+1
}

Na początku definiujemy dwa wektory z kwestiami wypowiadanymi przez małżonków oraz licznik, któremu przypisujemy początkową wartość równą 1.
Następnie powołujemy do życia pętlę while, ustalamy warunek wyjącia: licznik<5. Należy odczytywać to w sposób: “Wykonuj zawartość pętli dopóki wartość zmiennej licznik jest mniejsza niż 5”. Nasz program w każdym obiegu pętli będzie dodawał do zmiennej licznik wartość 1. Czyli kod wewnątrz pętli wykona się czterokrotnie.

Pętla typu FOR

Ostatnim omawianym typem pętli jest pętla for.  Jest ona bardzo podobna do poprzednich,  jednak posiada nieco inną budowę oraz dodatkowe możliwości. Tak jak pętla while, deklarując pętlę for od razu  możemy zdefiniować jak wiele razy wykonamy kod. Przyjrzyjmy się prostemu programowi:


# Author: Lukasz Joksch
# Source www.joksch.pl

prosbyZony <- c("wyrzuc smieci!","no wyrzuc te smieci!","wyrzuc w koncu smieci!","nareszcie!")
odpowiedziMeza <- c("nie chce mi sie!","nie chce mi sie!","nie chce mi sie!","teraz mam spokoj!")
licznik <-0

for(licznik in 1:4){
 print("Zona:")
 print(prosbyZony[licznik])
 print("------------------------")
 Sys.sleep(1)
 print("Maz")
 print(odpowiedziMeza[licznik])
 Sys.sleep(1)
 print("------------------------")
}

Pętla for swojej najprostszej postaci wykonuje kod tyle razy, ile wskażemy w wyrażeniu (licznik in 1:4) – oznacza to, że pętla wykona się dokładnie 4 razy. Widzimy, że tym razem nie ma konieczności wcześniejszej definicji zmiennej licznik.  Często zamiast ustalać konkretną liczbę obiegów pętli, używamy innej funkcji, która nam to ułatwi. Takim przykładem może być funkcja służąca do określania rozmiaru wektora: length(), zmodyfikujmy zatem poprzedni fragment kodu:


# Author: Lukasz Joksch
# Source www.joksch.pl

prosbyZony <- c("wyrzuc smieci!","no wyrzuc te smieci!","wyrzuc w koncu smieci!","nareszcie!")
odpowiedziMeza <- c("nie chce mi sie!","nie chce mi sie!","nie chce mi sie!","teraz mam spokoj!")
licznik <- length(prosbyZony)

for(licznik in 1:licznik){
 print("Zona:")
 print(prosbyZony[licznik])
 print("------------------------")
 Sys.sleep(1)
 print("Maz")
 print(odpowiedziMeza[licznik])
 Sys.sleep(1)
 print("------------------------")
}

Tym sposobem, możemy dodać kolejne elementy do wektorów prosbyZony lub odpowiedziMeza i nie będziemy musieli modyfikować już nic więcej w naszym programie.  Zyskujemy w tym momencie benefit w postaci większej uniwersalności kodu.

Pętla typu FOR EACH

Pętla for posiada specyficzną postać nazywaną “for each”, czyli taką która wykona się tak wiele razy ile jest elementów w liście, a precyzyjnie – w wektorze wejściowym, przyjrzyjmy się takiej składni:


# Author: Lukasz Joksch
# Source www.joksch.pl

liczby <- c("jeden", "dwa", "trzy", "cztery", "piec")
zwierzeta <- c("pies","kot","mysz","ryba")
cyferki <- c(1,2,3,4)
wektor <- c(liczby,zwierzeta,cyferki)
dane <- data.frame(zwierzeta,cyferki)

print("---LICZBY---")
for(obieg in liczby)
{
  print(obieg)
}

print("---ZWIERZETA---")
for(obieg in zwierzeta)
{
  print(obieg)
}

print("---CYFERKI---")
for(obieg in cyferki)
{
  print(obieg)
}

print("---WEKTOR---")
for(obieg in wektor)
{
  print(obieg)
}

print("---DANE---")
for(obieg in dane)
{
  print(obieg)
}

Celowo podałem wiele przykładów, żeby pokazać jak wygodny jest to  sposób i jak działa dla różnych typów zmiennych. Na podstawie fragmentu wypisującego kolejne wartości:


print("---LICZBY---")
for(obieg in liczby)
{
print(obieg)
}

Widzimy, że po słowie in podajemy nazwę wektora wejściowego, tu: liczby, a chcąc odwołać się do kolejnego elementu używamy zmiennej obieg. Należy jednak pamiętać że w danym momencie(w danym obiegu pętli, możemy odwołać się w ten sposób wyłącznie do aktualnego(pojedynczego) elementu wektora wejściowego. W przypadku podstawowej pętli for moglibyśmy odwoływać się także do innych elementów.

Opublikowany w R

Dodaj komentarz