R Dilinde Loop (Döngü) İşlemleri

R programalam dili ile ilgili yazılar, basit örnekler dahilinde loop konusuna (repetitive execution) değinerek devam ediyorum.

AA

R dilinde döngüler (loop construction) for (for (name in expr_1) expr_2), repeat (repeat expr) ve while (while (condition) expr) ile oluşturulur. loop, cycling ya da iterating hangi tanımı kullandığınız önemli değil. Temelde, çok adımlı bir süreci, eylem dizilerini ve toplu işlemleri organize etmek ve tekrarlanmasını sağlamak amacıyla kullanılan en temel işlemlerden biri olduğunuz bilmeniz yeterli. Herhangi bir programlama diline aşinalığınız varsa zaten daha öncesinde kullanmış ya da en azından örneklerde rastlamışsınızdır. R dilinde de döngülerin işleme biçimleri dilin bağlamı haricinde aynı. İlk olarak for döngüsü ile başlayalım. Ancak öncesinde oldukça basit bir işlem oluşturalım ve bu işlemi döngülerle yeniden kurgulayalım.

print(paste("Number is", 1)) # Number is 1
print(paste("Number is", 2)) # Number is 2
print(paste("Number is", 3)) # Number is 3
print(paste("Number is", 4)) # Number is 4
print(paste("Number is", 5)) # Number is 5

For Loop

For döngüsü belirli bir kod bloğunu (name) belirtilen sayıda (expr_1, vector expression1. Örneğin, 1:20) ve peş peşe çalıştırmak (expr_2, grouped expression) (belirtilen i. değerden belirten j. değerine kadar) için kullanılır.

for (name in _expr_1_) _expr_2_

Yukarıdaki kullanımı hatırlayalım. Aşağıdaki uygulamamızın ilk satırında yer alan c(1:5) vektör içeriğini (1,2,3,4,5, first_value:1, end_value:5) number’a atıyoruz. Ekrana yazdırdığımız ikinci satırda paste içeriğinde “Number is” string ifadesini de dahil ederek sayımızı sırasıyla ekrana basıyoruz ve çıktımız yukarıda el yordamı ile satır satır yazdığımız Number is x dökümü ile aynı oluyor.

for (number in c(1:5)){
  print(paste("Number is", number))
}

Elbette yukarıdaki for’un işlevini daha net anlamak adına print(c(1:5)) kodunu ayrıca uygulayabilirsiniz. Alacağınız karşılık [1] 1 2 3 4 5 olacaktır. Ayrıca bir de şu örneği deneyebilirsiniz:

for(number in c(1:5)){
  print(c(1:number))
}

Yukarıdaki örnek, expr_1 içeriğini sırayla number’a atayacak, print ise 1:number değer aralıklarını gökecektir. Ek olarak aşağıdaki örneği uygulayarak print içeriğindeki farklılığı daha net görebilirsiniz.

for(number in c(1:5)){
  print(number)
}

Son bir örnekle for döngüsünü noktalayabiliriz.

for (number in 1:5){
  print(paste(number, "^2:", number^2))
}

While Loop

While döngüsü belirlenen koşul (condition) sağlandığı sürece işlemi (expr) uygulayan temel döngü yapılarından bir tanesidir. BAsitliği ile tercih edilen while temel yapısı şu şekildedir.

while (condition) _expr_

Yine yazının başındaki örnek üzerinden devam edeceğim.

number <- 1
while (number <= 5){
    print(paste("Number is", number))
    number <- number + 1
}

Yukarıdaki örnekte number değerine 1 sayısını atıyoruz. while tanımlanan condition sağlandığı sürece number <= 5 ekrana print içeriğini dökecektir. Print sonrasındaki number içeriğimiz bir önceki içeriğe +1 ekleyerek condition boyunca döngüyü sürdürecektir. Örnekteki number <- number + 1 satırını print üzerine ekleyerek kodu tekrar çalıştırdığınızda sonucun değiştiğini görebilirsiniz. Son olarak, repeatörneklerinden bahsedeceğim ve sonrasında iç içe döngüler, break ve next kullanımlarıyla yazısı sonlandıracağım.

Repeat Loop

Repeat, belirtilen expr if...else... ile belirtilen condition durumuna bağlı olarak tekrar edilecektir. En temel kullanım şekli şöyle:

repeat _expr_

Öncelikle aşağıda herhangi bir condition barındırmayan bir repeat işlemi uygulayalım.

number <- 1
repeat {
  print(paste("Number is", number))
  number = number+1
}

Göreceğiniz üzere print aksi belirtilmediği ve işlem sonlandırılmadığı sürece değer dökecektir. Şimdi, bir condition ekleyelim ve print içeriğinin 5'ten büyük number > 5 olduğu durumda basılmamasını, break ile repeat işleminin durdurulmasını belirtelim2.

number <- 1 repeat { print(paste("Number is", number)) number = number+1 if (number > 5){
    break
  }
}

Hazır if...else... condition içeriğinde break işlemine değişmişken bir sonraki başlığıma geçebiliriz.

R Dilinde Next ve Break Kullanımı

Özellikle döngülerde sıklıkla denk gelebileceğiniz break ve next kullanımını yine örnekler üzerinden açıklayayım. En temel kullanım biçimini aşağıda iletiyorum.

repeat{
  _expr_
  if(condition){
    break
  }
}

Önce break işlevinden bahsedeyim. İçeriğinde (scope) yer aldığı condition sağlandığı durumda bağlı olduğu döngü ve/veya fonksiyonunu durduracaktır. Bir sonraki scope içeriğindeki sonraki işleme geçilecektir.

number <- 1
while(number < 10) { print(number); number <- number + 1; if (number == 3) break; }

next ise içeriğinde yer aldığı condition sağlandığında bir sonraki adıma geçecektir.

number <- 1
while(number < 5) { number <- number + 1; if (number == 3) next; print(number); }

En temel kullanım biçimlerini bu şekilde özetleyebileceğimiz break ve next'in ardından son olarak iç içe döngülere değinelim.

R Dilinde İç İçe Döngüler

number <- matrix(1:6, 2, 3)
for(i in seq_len(nrow(number))) {
  for(j in seq_len(ncol(number))) {
    print(c(number[i, j])) # print(number[i, j])
  }
}

Örnekte 2 adet for döngüsü görmektesiniz. seq fonksiyonuna ayrıca başka bir yazıda değineceğim. Basitçe açıklamak gerekirse seq fonksiyonu3 düzenli diziler oluşturmamızı seq.int, seq_along, seq_len sağlar. İlk for i içeriğine oluşturduğumuz matrix'in sütun değerini atayacaktır. İkinci for satır değerini j içeriğine atayacaktır ve ekrana döngüyle eşleşen satır-sütun değerleri i-j basılacaktır.

[1] 1
[1] 3
[1] 5
[1] 2
[1] 4
[1] 6

Bir diğer örnekte de farklı bir iç içe döngü (nested) ile aşağıdaki çıktığı nasıl oluşturabileceğimize bakalım.

1
2 2
3 3 3
...

Yukarıdaki çıktı için öncelikle bir vector oluşturalım.

vector <- c()
for(i in 1:10) { 
  for(j in 1:i) {
    vector <- c(vector, i)
  }
}

Bu döndünün çıktısı şu şekilde olacaktır.

 [1]  1  2  2  3  3  3  4  4  4  4  5  5  5  5  5  6  6  6  6  6  6  7  7  7  7  7  7  7  8
[30]  8  8  8  8  8  8  8  9  9  9  9  9  9  9  9  9 10 10 10 10 10 10 10 10 10 10

Görüldüğü gibi her sayı kendi tekrarını oluşturmakta. Artık bu çıktıyı tekrar bir döngüye sokabiliriz.

n <- 1
for(n in n:10){
  x = (n * (n - 1)) / 2 + 1
  y = (n * (n + 1)) / 2
  print(vector[x:y])
}

Basit örneklerle açıklamaya çalıştığım döngülerle ilgili daha kapsamlı kullanımları diğer R yazılarım içerisinde görebilirsiniz.

Unutmadan ekleyeyim. Genelde R programlama dili ile yoğun bir şekilde çalışan geliştiriciler for ve while işlemleri veri miktarına bağlı olarak değerlendirilmesi gerektiğini, veri miktarı arttıkça çözümün apply ailesinin daha iyi performans göstereceğini belirtmekteler4 5.