FONKSİYONLAR

Fonksiyonlar function() kullanılarak tanımlanır ve diğer her şey gibi R nesneleri olarak saklanır. Özellikle, “function” sınıfının R nesneleridirler.

  • İşte hiçbir argüman almayan ve hiçbir şey yapmayan basit bir fonksiyon:
f <- function() {
        ## Bu boş bir fonksiyondur
}
## Fonksiyonların kendi sınıfları vardır
class(f)  
## [1] "function"
## Bu işlevi çalıştırın
f()       
## NULL
f <- function() {
        cat("Merhaba!\n")
}
f()
## Merhaba!
  • Bu temel fonksiyon için, konsola kaç kez “Merhaba!” yazdırılacağını belirleyen bir argüman ekleyebiliriz:
f<- function(num){
        for(i in seq_len(num)){
          cat("Merhaba!\n")
        }
}

f(5)
## Merhaba!
## Merhaba!
## Merhaba!
## Merhaba!
## Merhaba!
  • Sıradaki fonksiyon konsola yazdırılan toplam karakter sayısını döndürür:
f<- function(tekrar){
        Merhaba<- "Merhaba!\n"
        for(i in seq_len(tekrar)){
          cat(Merhaba)
        }
    karaktersayisi<- nchar(Merhaba)*tekrar
    karaktersayisi
}
f(5)
## Merhaba!
## Merhaba!
## Merhaba!
## Merhaba!
## Merhaba!
## [1] 45
  • Bu fonksiyondaki tekrar argümanı için varsayılan değer atama:
f <- function(tekrar = 1) {
        Merhaba <- "Merhaba!\n"
         for(i in seq_len(tekrar)) {
                 cat(Merhaba)
         }
         chars <- nchar(Merhaba) * tekrar
         chars
 }
 f()    ## 'tekrar' için varsayılan değeri kullan
## Merhaba!
## [1] 9
 f(2)   ## Kullanıcı tarafından belirtilen değeri kullan
## Merhaba!
## Merhaba!
## [1] 18

Çoklu Veri Seti Oluşturma

İstenilen sayıda veri seti oluşturan bir fonksiyon yazalım. Satır ve sütun sayısını argüman olarak tanımlayalım. Oluşturacak olan her bir veri setinin her bir sütunu standart normal dağılıma uygun olacak şekilde üretilsin. Oluşturulan veri setlerinden ilki “veri_1.xlsx” şeklinde çalışma alanına yazdırılsın.

fonksiyonum<-function(sayi=1, satir=c(5), sutun=c(10)) {
  data<-data.frame(matrix(0,nrow = satir, ncol=sutun))
    writexl::write_xlsx(data,"veri_1.xlsx")
}
fonksiyonum(sayi=1,satir=c(5),sutun=c(10))

Şimdi ise bu fonksiyonu çoklu dosya yazımına uygun hale getirelim.

fonksiyonum <-function(sayi=3,satir=c(5,5,5),sutun=c(10,10,10)){
   
  liste <- list() ## her bir veri setinin atanacağı yeni nesne
    
    for( i in 1:sayi){
    liste[[i]] <- data.frame(matrix(0,nrow=satir[i], ncol=sutun[i])) # veri seti istenilen ozelliklerde olusturulur
     for(j in 1:sutun[i]){
     liste[[i]][,j] <- round(rnorm(satir[i],0,1),2) #  her bir veri setinin her bir sütunu standart normal dağılıma uygun uretilir
           writexl::write_xlsx(liste[[i]],paste("veri",i,".xlsx", sep=""))

     }}
  
}
fonksiyonum(sayi=5,satir=c(5,4,3,5,5),
              sutun=c(10,5,4,3,4))

Sıra Sizde

Geometrik ortalama hesaplama:

geometrik_ortalama <- function(x) {
  # Matematiksel formül ile hesaplama
  mat_formul <- prod(x)^(1/length(x))
  
  # Logaritmik yöntem ile hesaplama
  log_formul <- exp(mean(log(x)))
  
  # Sonuçların yazdırılması
  cat("Matematiksel formül ile hesaplanan geometrik ortalama: ", mat_formul, "\n")
  cat("Logaritmik yöntem ile hesaplanan geometrik ortalama: ", log_formul, "\n")
}

data <- 200:250

geometrik_ortalama(data)
## Matematiksel formül ile hesaplanan geometrik ortalama:  224.5172 
## Logaritmik yöntem ile hesaplanan geometrik ortalama:  224.5172

Döngü Fonksiyonları

lapply()

  • lapply(), bir liste üzerindeki her eleman için yazdığımız belirli bir fonksiyonun uygulanmasını sağlar ve sonuçları bir liste olarak döndürür.

  • Örneğin; bir listedeki her bir eleman için rastgele sayılar üretebiliriz:

# Her eleman için 10 rastgele sayı
liste1 <- list(a = 5, b = 10, c = 15)

sonuc <- lapply(liste1, function(x) runif(x, min = 0, max = 100))

print(sonuc)
## $a
## [1] 45.73645 26.24459 87.10406 37.41812 11.36687
## 
## $b
##  [1] 91.116175 81.398871 82.695765 48.742895 85.912914 18.862215 90.790509
##  [8] 24.809827 14.614524  7.105838
## 
## $c
##  [1] 81.4026895  4.8562095 67.2691014 39.9003901  4.6746944 44.8441581
##  [7] 95.7366388  0.5655306 54.3968477 17.2219079 71.1223527 39.5131337
## [13] 17.4392289 34.2263273 23.0772553
lapply(sonuc, length)
## $a
## [1] 5
## 
## $b
## [1] 10
## 
## $c
## [1] 15

sapply()

  • sapply(), lapply() ile benzer şekilde çalışır ancak sonucu basitleştirir.
  • lapply() işlevinin sonucu, her öğesinin uzunluğu 1 olan bir liste olduğundan,sapply() işlevi çıktıyı, genellikle bir listeden daha kullanışlı olan sayısal bir vektöre daraltır.
  • Örneğin, yukarıdaki liste1 elemanlarının toplamın, ortalaasını almak için sapply() kullanabiliriz.
sapply(sonuc, sum)
##        a        b        c 
## 207.8701 546.0495 596.2465
sapply(sonuc, mean)
##        a        b        c 
## 41.57402 54.60495 39.74976

veri setini bölme

head(mtcars)

Silindir sayılarına (cyl) göre gruplandırarak her grup için belirli değişkenlerin (yakıt tüketimi=mpg, motor gücü=hp, aracın ağırlığı=wt) ortalamalarını hesaplayalım.

# silindir sayısına göre veri setini bölme
s <- split(mtcars, mtcars$cyl)
str(s)
## List of 3
##  $ 4:'data.frame':   11 obs. of  11 variables:
##   ..$ mpg : num [1:11] 22.8 24.4 22.8 32.4 30.4 33.9 21.5 27.3 26 30.4 ...
##   ..$ cyl : num [1:11] 4 4 4 4 4 4 4 4 4 4 ...
##   ..$ disp: num [1:11] 108 146.7 140.8 78.7 75.7 ...
##   ..$ hp  : num [1:11] 93 62 95 66 52 65 97 66 91 113 ...
##   ..$ drat: num [1:11] 3.85 3.69 3.92 4.08 4.93 4.22 3.7 4.08 4.43 3.77 ...
##   ..$ wt  : num [1:11] 2.32 3.19 3.15 2.2 1.61 ...
##   ..$ qsec: num [1:11] 18.6 20 22.9 19.5 18.5 ...
##   ..$ vs  : num [1:11] 1 1 1 1 1 1 1 1 0 1 ...
##   ..$ am  : num [1:11] 1 0 0 1 1 1 0 1 1 1 ...
##   ..$ gear: num [1:11] 4 4 4 4 4 4 3 4 5 5 ...
##   ..$ carb: num [1:11] 1 2 2 1 2 1 1 1 2 2 ...
##  $ 6:'data.frame':   7 obs. of  11 variables:
##   ..$ mpg : num [1:7] 21 21 21.4 18.1 19.2 17.8 19.7
##   ..$ cyl : num [1:7] 6 6 6 6 6 6 6
##   ..$ disp: num [1:7] 160 160 258 225 168 ...
##   ..$ hp  : num [1:7] 110 110 110 105 123 123 175
##   ..$ drat: num [1:7] 3.9 3.9 3.08 2.76 3.92 3.92 3.62
##   ..$ wt  : num [1:7] 2.62 2.88 3.21 3.46 3.44 ...
##   ..$ qsec: num [1:7] 16.5 17 19.4 20.2 18.3 ...
##   ..$ vs  : num [1:7] 0 0 1 1 1 1 0
##   ..$ am  : num [1:7] 1 1 0 0 0 0 1
##   ..$ gear: num [1:7] 4 4 3 3 4 4 5
##   ..$ carb: num [1:7] 4 4 1 1 4 4 6
##  $ 8:'data.frame':   14 obs. of  11 variables:
##   ..$ mpg : num [1:14] 18.7 14.3 16.4 17.3 15.2 10.4 10.4 14.7 15.5 15.2 ...
##   ..$ cyl : num [1:14] 8 8 8 8 8 8 8 8 8 8 ...
##   ..$ disp: num [1:14] 360 360 276 276 276 ...
##   ..$ hp  : num [1:14] 175 245 180 180 180 205 215 230 150 150 ...
##   ..$ drat: num [1:14] 3.15 3.21 3.07 3.07 3.07 2.93 3 3.23 2.76 3.15 ...
##   ..$ wt  : num [1:14] 3.44 3.57 4.07 3.73 3.78 ...
##   ..$ qsec: num [1:14] 17 15.8 17.4 17.6 18 ...
##   ..$ vs  : num [1:14] 0 0 0 0 0 0 0 0 0 0 ...
##   ..$ am  : num [1:14] 0 0 0 0 0 0 0 0 0 0 ...
##   ..$ gear: num [1:14] 3 3 3 3 3 3 3 3 3 3 ...
##   ..$ carb: num [1:14] 2 4 3 3 3 4 4 4 2 2 ...
# Her grup için belirli değişkenlerin ortalamasını hesaplama
sonuc_lapply <- lapply(s, function(x) {
  colMeans(x[, c("mpg", "hp", "wt")])
})

print(sonuc_lapply)
## $`4`
##       mpg        hp        wt 
## 26.663636 82.636364  2.285727 
## 
## $`6`
##        mpg         hp         wt 
##  19.742857 122.285714   3.117143 
## 
## $`8`
##        mpg         hp         wt 
##  15.100000 209.214286   3.999214

lapply yerine sapply kullanarak sonuçları daha okunabilir bir formatta elde edelim.

sonuc_sapply <- sapply(s, function(x) {
  colMeans(x[, c("mpg", "hp", "wt")])
})

print(sonuc_sapply)
##             4          6          8
## mpg 26.663636  19.742857  15.100000
## hp  82.636364 122.285714 209.214286
## wt   2.285727   3.117143   3.999214
# ortalama hesaplama (NA'ları göz ardı ederek)
genel_ortalamalar <- colMeans(mtcars[, c("mpg", "hp", "wt")], na.rm = TRUE)

print(genel_ortalamalar)
##       mpg        hp        wt 
##  20.09062 146.68750   3.21725

tapply()

  • tapply() fonksiyonun temel görevi verileri belirlenen grup veya faktör değişkenine göre özetlemektir.

  • Fonksiyonda bulunan x argümanı vektör, veri seti ve liste şeklindeki nesneleri, index argümanı “x” nesnesinin alt boyut, grup veya faktör değişkenini, FUN argümanı ise uygulanacak fonksiyonu belirtir.

str(tapply)
## function (X, INDEX, FUN = NULL, ..., default = NA, simplify = TRUE)
  • Örneğin, mtcars veri setinde silindir sayısına göre yakıt tüketimi ortalamalarını hesaplayalım:
ortalama_mpg <- tapply(mtcars$mpg, mtcars$cyl, mean)

print(ortalama_mpg)
##        4        6        8 
## 26.66364 19.74286 15.10000
tapply(mtcars$mpg, mtcars$cyl, sort, decreasing=TRUE)
## $`4`
##  [1] 33.9 32.4 30.4 30.4 27.3 26.0 24.4 22.8 22.8 21.5 21.4
## 
## $`6`
## [1] 21.4 21.0 21.0 19.7 19.2 18.1 17.8
## 
## $`8`
##  [1] 19.2 18.7 17.3 16.4 15.8 15.5 15.2 15.2 15.0 14.7 14.3 13.3 10.4 10.4

by()

  • Bir veri setini gruplara ayırıp, her grup için belirli bir işlemi (ör. ortalama alma, toplam hesaplama) ayrı ayrı uygulamak için by() fonksiyonu kullanılır.
boy <- c(152, 160, 165, 172, 167, 175)
cinsiyet <- factor(c("erkek", "kadın", "kadın", "kadın", "erkek", "erkek"))
veri <- data.frame(boy = c(152, 160, 165, 172, 167, 175), cinsiyet = cinsiyet)

by(veri$boy, veri$cinsiyet, sort, decreasing=TRUE) 
## veri$cinsiyet: erkek
## [1] 175 167 152
## ------------------------------------------------------------ 
## veri$cinsiyet: kadın
## [1] 172 165 160

apply()

  • apply() fonksiyonu, bir dizinin kenar boşlukları üzerinde bir fonksiyonu (genellikle anonim bir fonksiyon) değerlendirmek için kullanılır. Çoğunlukla bir matrisin (sadece 2 boyutlu bir dizi) satırlarına veya sütunlarına bir fonksiyon uygulamak için kullanılır. Ancak, örneğin bir dizi matrisin ortalamasını almak gibi genel dizilerde de kullanılabilir. apply() kullanmak bir döngü yazmaktan gerçekten daha hızlı değildir, ancak tek satırda çalışır ve oldukça kompakttır.
str(apply)
## function (X, MARGIN, FUN, ..., simplify = TRUE)
data(mtcars)
mtcars_matrix <- as.matrix(mtcars)

# apply fonksiyonu ile her sütunun ortalamasını hesaplayalım
apply(mtcars_matrix, 2, mean)
##        mpg        cyl       disp         hp       drat         wt       qsec 
##  20.090625   6.187500 230.721875 146.687500   3.596563   3.217250  17.848750 
##         vs         am       gear       carb 
##   0.437500   0.406250   3.687500   2.812500
  • Matrislerin sütun/satır toplamları ve sütun/satır ortalamalarının özel durumları için bazı kullanışlı kısa yollarımız vardır.
# colMeans fonksiyonu ile her sütunun ortalamasını hesaplayalım
colMeans(mtcars_matrix)
##        mpg        cyl       disp         hp       drat         wt       qsec 
##  20.090625   6.187500 230.721875 146.687500   3.596563   3.217250  17.848750 
##         vs         am       gear       carb 
##   0.437500   0.406250   3.687500   2.812500
  • mean() fonksiyonunu “mtcars_matrix” nesnesinin her bir sütununa uygulanarak sütunların ortalamasını alalım:
apply(mtcars_matrix, 2, mean) # Fonksiyonun ikinci girdisi olan 2  sütun elamanlarını temsil etmektedir.
##        mpg        cyl       disp         hp       drat         wt       qsec 
##  20.090625   6.187500 230.721875 146.687500   3.596563   3.217250  17.848750 
##         vs         am       gear       carb 
##   0.437500   0.406250   3.687500   2.812500
  • summary() fonksiyonunu “mtcars_matrix” nesnesinin her bir sütununa uygulayalım:
apply(mtcars_matrix, 2, summary)
##              mpg    cyl     disp       hp     drat      wt     qsec     vs
## Min.    10.40000 4.0000  71.1000  52.0000 2.760000 1.51300 14.50000 0.0000
## 1st Qu. 15.42500 4.0000 120.8250  96.5000 3.080000 2.58125 16.89250 0.0000
## Median  19.20000 6.0000 196.3000 123.0000 3.695000 3.32500 17.71000 0.0000
## Mean    20.09062 6.1875 230.7219 146.6875 3.596563 3.21725 17.84875 0.4375
## 3rd Qu. 22.80000 8.0000 326.0000 180.0000 3.920000 3.61000 18.90000 1.0000
## Max.    33.90000 8.0000 472.0000 335.0000 4.930000 5.42400 22.90000 1.0000
##              am   gear   carb
## Min.    0.00000 3.0000 1.0000
## 1st Qu. 0.00000 3.0000 2.0000
## Median  0.00000 4.0000 2.0000
## Mean    0.40625 3.6875 2.8125
## 3rd Qu. 1.00000 4.0000 4.0000
## Max.    1.00000 5.0000 8.0000
  • summary() fonksiyonunu “mtcars_matrix” nesnesinin her bir satırına uygulayalım:
apply(mtcars_matrix, 1, summary)
##         Mazda RX4 Mazda RX4 Wag Datsun 710 Hornet 4 Drive Hornet Sportabout
## Min.      0.00000       0.00000    1.00000        0.00000           0.00000
## 1st Qu.   3.26000       3.38750    1.66000        2.00000           2.50000
## Median    4.00000       4.00000    4.00000        3.21500           3.44000
## Mean     29.90727      29.98136   23.59818       38.73955          53.66455
## 3rd Qu.  18.73000      19.01000   20.70500       20.42000          17.86000
## Max.    160.00000     160.00000  108.00000      258.00000         360.00000
##           Valiant Duster 360 Merc 240D  Merc 230 Merc 280 Merc 280C Merc 450SE
## Min.      0.00000      0.000   0.00000   0.00000     0.00   0.00000    0.00000
## 1st Qu.   1.88000      3.105   2.59500   2.57500     3.68   3.68000    3.00000
## Median    3.46000      4.000   4.00000   4.00000     4.00   4.00000    4.07000
## Mean     35.04909     59.720  24.63455  27.23364    31.86  31.78727   46.43091
## 3rd Qu.  19.16000     15.070  22.20000  22.85000    18.75  18.35000   16.90000
## Max.    225.00000    360.000 146.70000 140.80000   167.60 167.60000  275.80000
##         Merc 450SL Merc 450SLC Cadillac Fleetwood Lincoln Continental
## Min.          0.00        0.00            0.00000             0.00000
## 1st Qu.       3.00        3.00            2.96500             3.00000
## Median        3.73        3.78            5.25000             5.42400
## Mean         46.50       46.35           66.23273            66.05855
## 3rd Qu.      17.45       16.60           14.19000            14.11000
## Max.        275.80      275.80          472.00000           460.00000
##         Chrysler Imperial Fiat 128 Honda Civic Toyota Corolla Toyota Corona
## Min.              0.00000  1.00000     1.00000        1.00000       0.00000
## 1st Qu.           3.11500  1.60000     1.80750        1.41750       1.73250
## Median            5.34500  4.00000     4.00000        4.00000       3.70000
## Mean             65.97227 19.44091    17.74227       18.81409      24.88864
## 3rd Qu.          16.06000 25.93500    24.46000       26.90000      20.75500
## Max.            440.00000 78.70000    75.70000       71.10000     120.10000
##         Dodge Challenger AMC Javelin Camaro Z28 Pontiac Firebird Fiat X1-9
## Min.             0.00000     0.00000    0.00000          0.00000   1.00000
## 1st Qu.          2.38000     2.50000    3.36500          2.50000   1.46750
## Median           3.52000     3.43500    4.00000          3.84500   4.00000
## Mean            47.24091    46.00773   58.75273         57.37955  18.92864
## 3rd Qu.         16.18500    16.25000   14.35500         18.12500  23.10000
## Max.           318.00000   304.00000  350.00000        400.00000  79.00000
##         Porsche 914-2 Lotus Europa Ford Pantera L Ferrari Dino Maserati Bora
## Min.          0.00000      1.00000        0.00000      0.00000       0.00000
## 1st Qu.       2.07000      1.75650        3.58500      3.19500       3.55500
## Median        4.43000      4.00000        5.00000      6.00000       8.00000
## Mean         24.77909     24.88027       60.97182     34.50818      63.15545
## 3rd Qu.      21.35000     23.65000       15.15000     17.60000      14.80000
## Max.        120.30000    113.00000      351.00000    175.00000     335.00000
##         Volvo 142E
## Min.       1.00000
## 1st Qu.    2.39000
## Median     4.00000
## Mean      26.26273
## 3rd Qu.   20.00000
## Max.     121.00000

mapply()

  • mapply() fonksiyonu, bir dizi argüman üzerinde paralel olarak bir fonksiyon uygulayan bir tür çok değişkenli uygulamadır. lapply() ve arkadaşlarının yalnızca tek bir R nesnesi üzerinde yineleme yaptığını hatırlayın. Peki ya birden fazla R nesnesi üzerinde paralel olarak yineleme yapmak isterseniz? İşte mapply() bunun içindir.
str(mapply)
## function (FUN, ..., MoreArgs = NULL, SIMPLIFY = TRUE, USE.NAMES = TRUE)
  • Örneğin, aşağıdakileri yazmak sıkıcıdır:

    list(rep(1, 4), rep(2, 3), rep(3, 2), rep(4, 1))

    Bunun yerine mapply() ile şunları yapabiliriz:

 mapply(rep, 1:4, 4:1)
## [[1]]
## [1] 1 1 1 1
## 
## [[2]]
## [1] 2 2 2
## 
## [[3]]
## [1] 3 3
## 
## [[4]]
## [1] 4
  • Bu, rep()in ilk argümanına 1:4 dizisini ve ikinci argümanına 4:1 dizisini geçirir.

NOT: apply() ailesi gerçekten çok kullanışlı, birçok işlemi daha az kod yazarak daha kolay yapmayı sağlıyor. Ancak bu fonksiyonlara hakim olmak zaman alacak gibi. Bir kod yazmamız gerektiğinde ilk aklımıza gelen adım adım gittiğimiz uzunca kodlar oluyor, bu kodları apply() ailesindeki fonksiyonları kullanarak zaman içinde daha kısa ve şık hallerini yazabilmeyi gerçekten çok istiyorum.