Istnieją dwie ważne właściwości pętli for. Po pierwsze, wyniki nie są wypisywane wewnątrz pętli, chyba że jawnie wywołasz funkcję print(). Po drugie, zmienna indeksująca używana w pętli for będzie zmieniana po kolei po każdej iteracji. Ponadto, aby zatrzymać iterację, możesz użyć słowa kluczowego break, a aby przejść do następnej iteracji, możesz użyć następnego polecenia. W pierwszym przykładzie tworzymy wektor znaków o nazwie words i iterujemy przez każdy z jego elementów w kolejności, używając składni for (słowo w słowach). Spowoduje to pobranie pierwszego elementu z words, przypisanie go do word i przekazanie go przez wyrażenie zdefiniowane w bloku zdefiniowanym przez nawiasy klamrowe, które w tym przypadku wypisują słowo do konsoli, jako a także liczbę znaków w słowie. Po zakończeniu iteracji słowo zostanie zaktualizowane następnym słowem, a pętla będzie powtarzana w ten sposób, aż wszystkie słowa zostaną użyte:
words <- c(„Hello”, „there”, „dear”, „reader”)
for (word in words){
print(word)
print(nchar(word))
}
#> [1] “Hello”
#> [1] 5
#> [1] “there”
#> [1] 5
#> [1] “deare”
#> [1] 4
#> [1] “reader”
#> [1] 6
Ciekawe zachowanie można osiągnąć, używając zagnieżdżonych pętli for, które są pętlami for wewnątrz innych pętli for. W tym przypadku obowiązuje ta sama logika, kiedy napotkamy pętlę for, wykonujemy ją aż do zakończenia. Rezultat takiego zachowania łatwiej jest zobaczyć, niż go wyjaśnić, więc spójrz na zachowanie następującego kodu:
for (i in 1:5) {
print(i)
for (j in 1:3) {
print(paste)(„ „ , j))
}
}
#> [1] 1
#> [1] “1”
#> [1] “2”
#> [1] “3”
#> [1] 2
#> [1] “1”
#> [1] “2”
#> [1] “3”
#> [1] 3
#> [1] “1”
#> [1] “2”
#> [1] “3”
#> [1] 4
#> [1] “1”
#> [1] “2”
#> [1] “3”
#> [1] 5
#> [1] “1”
#> [1] “2”
#> [1] “3”
Używanie takich zagnieżdżonych pętli for jest sposobem, w jaki ludzie wykonują operacje podobne do macierzy, gdy używają języków, które nie oferują operacji wektoryzowanych. Na szczęście możemy użyć składni przedstawionej w poprzednich sekcjach, aby wykonać te operacje bez konieczności samodzielnego używania zagnieżdżonych pętli for, co czasami może być trudne. Teraz zobaczymy, jak używać funkcji sapply() i lapply(), aby zastosować funkcję dla każdego elementu wektora. W tym przypadku wywołamy funkcję nchr() na każdym z elementów w wektorze słów, który utworzyliśmy wcześniej. Różnica między funkcjami sapply() i lapply() polega na tym, że pierwsza zwraca wektor, a druga zwraca listę. Na koniec zwróć uwagę, że jawne używanie którejkolwiek z tych funkcji nie jest konieczne, ponieważ, jak widzieliśmy wcześniej, funkcja nchar() jest już dla nas zwektoryzowana:
sapply(words, nchar)
#> Witam drogi czytelniku
#> 5 5 4 6
slapply(words, nchar)
#> [[1]]
#> [1] 5
#>
#> [[2]]
#> [1] 5
#>
#> [[3]]
#> [1] 4
#>
#> [[4]]
#> [1] 6
nchar(words)
#> [1] 5 5 4 6
Kiedy masz funkcję, która nie została wektoryzowana, jak nasza funkcja distance(). Nadal można go używać w sposób zwektoryzowany, korzystając z funkcji, o których właśnie wspomnieliśmy. W tym przypadku zastosujemy go do listy x, która zawiera trzy różne wektory numeryczne. Użyjemy funkcji lapply(), przekazując jej listę, po której nastąpi funkcja, którą chcemy zastosować do każdego z jej elementów (w tym przypadku distance(). Zwróć uwagę, że w przypadku, gdy funkcja, której używasz, otrzyma inne argumenty oprócz tego, który zostanie pobrany z x i który zostanie przekazany jako pierwszy argument do takiej funkcji, możesz przekazać je po nazwie funkcji, tak jak robimy to tutaj argumenty c(1,1,1) i l1_norm, które zostaną odebrane przez funkcję distance() jako argumenty y i norm, i pozostają ustalone dla wszystkich elementów listy x:
x <- list (c(1,2,3), c(4,5,6), c(7,8,9)
lapply(x ,distance ,c(1,1,1), l1_norm)
#> [[1]]
#> [1] 3
#>
#> [[2]]
#> [1] 12
#>
#> [[3]]
#> [1] 21