R Fonksiyonlar

Dr. Kubra Atalay Kabasakal

Kasim 2021

Fonksiyon Nedir-1

Fonksiyon Nedir-2

Fonksiyon Nedir-3

Neden Fonksiyon Yazarız-1

Neden Fonksiyon Yazarız-2

Neden Fonksiyon Yazarız-3

Neden Fonksiyon Yazarız-4

Fonksiyonun Yapısı

Fonksiyona İsim Verme

Argümanlar

Argümanlar

Govde

Govde

return

Environment

Calisma Alanı

Fonksiyonlar, kendi çalışma alanını oluştururlar!!!

Calisma Alanı

Yazim Asamaları

Fonksiyon yazmak kadar iyi bir fonksiyon yazmak da önemlidir.

Fonksiyonlara Mesaj Ekleme

Bazı fonksiyonlar bazı durumlarda stop() fonksiyonu ile durdurabilir, bazı durumlarda message(), print(), cat() fonksiyonu ile kullanıcıya mesaj verilebilir. Ayrıca assertive paketi ile de uyarı mesajları sağlanabilir.

library(assertive)
## Warning: package 'assertive' was built under R version 4.0.5
## 
## Attaching package: 'assertive'
## The following objects are masked from 'package:magrittr':
## 
##     is_greater_than, is_less_than
 bolme <- function(x){
  assert_is_numeric(x)
  1/x }
  bolme(3)
## [1] 0.3333333

Ornek_Adım1

Öğrencileri sözlüye kaldırmak için random seçen fonksiyon yazma

ogrenci <- c("ARIF ARSLAN","ASLI YORUK","ATA CANTURK DOGRUL",
             "AYBUKE DOGAC","AYSE TUNA","BURCAK GONUL AYDIN",
             "CAGATAY COSKUN","EMRE GONEN","FEYZI GUNES",
             "FURKAN ATMACA", "HARUN DILEK","KORKUT KOCAK",
             "MEHMET YILMAZ","RAMAZAN SOYUK",
             "SEMIH TOPUZ","SINEM COSKUN")
sample(ogrenci,1)
## [1] "AYSE TUNA"

Ornek_Adım2

Önce bir taslak oluşturun.

# taslak hazırlama
random_secici <- function() {
### burası fonksiyon kodlarının yazılacagı alan
}

Ornek_Adım3

Daha önce yaptığınız işlemleri taslağa yapıstırın.

random_secici <- function() {
ogrenci <- c("ARIF ARSLAN","ASLI YORUK","ATA CANTURK DOGRUL",
             "AYBUKE DOGAC","AYSE TUNA","BURCAK GONUL AYDIN",
             "CAGATAY COSKUN","EMRE GONEN","FEYZI GUNES",
             "FURKAN ATMACA", "HARUN DILEK","KORKUT KOCAK",
             "MEHMET YILMAZ","RAMAZAN SOYUK",
             "SEMIH TOPUZ","SINEM COSKUN")
sample(ogrenci,1)
}

Fonksiyonu çalıştırın.

random_secici()
## [1] "RAMAZAN SOYUK"

Ornek_Adım4

Bu fonksiyonun hangi argümanlara ihtiyacı var onu düşünün.

random_secici <- function() {
ogrenci <- c("ARIF ARSLAN","ASLI YORUK","ATA CANTURK DOGRUL",
             "AYBUKE DOGAC","AYSE TUNA","BURCAK GONUL AYDIN",
             "CAGATAY COSKUN","EMRE GONEN","FEYZI GUNES",
             "FURKAN ATMACA", "HARUN DILEK","KORKUT KOCAK",
             "MEHMET YILMAZ","RAMAZAN SOYUK",
             "SEMIH TOPUZ","SINEM COSKUN")
sample(ogrenci,1)
}

Ornek_Adım5

Bu fonksiyonun hangi argümanlara ihtiyacı var onu düşünün.

random_secici <- function(x,n) {
sample(x,n) 
  }

Fonksiyonu ilk yazdığınız özel durum için çalıştırma.

random_secici <- function(x,n) {
sample(x,n) 
  }
random_secici(ogrenci,1)
## [1] "BURCAK GONUL AYDIN"

Fonksiyon Okuma

harf_not() fonksiyonunun işlevini açıklayabilir misiniz?

harf_not <- function(x, n, na.rm, labels, interval_type) {
  probs <- seq(0, 1, length.out = n + 1)
  qtiles <- quantile(x, probs, na.rm = na.rm, names = FALSE)
  right <- switch(interval_type, "(lo, hi]" = TRUE, "[lo, hi)" = FALSE)
cut(x, qtiles, labels = labels, right = right, include.lowest = TRUE)
}

Default argumanlar-1

harf_not() fonksiyonunun n argümanını default olarak tanımlayınız. Fonksiyonu buna göre yeniden düzenleyip çalıştırınız.

{r}
harf_not <- function(x, n, na.rm, labels, interval_type) {
  probs <- seq(0, 1, length.out = n + 1)
  qtiles <- quantile(x, probs, na.rm = na.rm, names = FALSE)
  right <- switch(interval_type, "(lo, hi]" = TRUE, "[lo, hi)" = FALSE)
cut(x, qtiles, labels = labels, right = right, include.lowest = TRUE)
}
## Error in harf_not(x, n, na.rm, labels = c("very low", "low", "medium", : could not find function "harf_not"

Default argumanlar-2

harf_not() fonksiyonunun na.rm argümanını default olarak tanımlayınız. Fonksiyonu buna göre yeniden düzenleyip çalıştırınız.

harf_not <- function(x, n = 5, na.rm, labels, interval_type) {
  probs <- seq(0, 1, length.out = n + 1)
  qtiles <- quantile(x, probs, na.rm = na.rm, names = FALSE)
  right <- switch(interval_type, "(lo, hi]" = TRUE, "[lo, hi)" = FALSE)
  cut(x, qtiles, labels = labels, right = right, include.lowest = TRUE)
}

Default argumanlar-3

harf_not() fonksiyonunun labels argumanını NULL olarak tanımlayınız. Fonksiyonu buna göre yeniden düzenleyip çalıştırınız.

harf_not <- function(x, n = 5, na.rm = FALSE, labels, interval_type) {
  probs <- seq(0, 1, length.out = n + 1)
  qtiles <- quantile(x, probs, na.rm = na.rm, names = FALSE)
  right <- switch(interval_type, "(lo, hi]" = TRUE, "[lo, hi)" = FALSE)
  cut(x, qtiles, labels = labels, right = right, include.lowest = TRUE)
}

harf_not(
  x,
  labels = c("F", "D", "C", "B", "A"),
  interval_type = "(lo, hi]"
)

Default argumanlar-4

harf_not() fonksiyonunun interval type değerleri de argümanın içinde tanımlanırsa daha kullanışlı olur.

x <- sample(0:100,30)
harf_not <- function(x, n = 5, na.rm = FALSE, labels = NULL, 
                            interval_type = c("(lo, hi]", "[lo, hi)")) {
  interval_type <- match.arg(interval_type)
  probs <- seq(0, 1, length.out = n + 1)
  qtiles <- quantile(x, probs, na.rm = na.rm, names = FALSE)
  right <- switch(interval_type, "(lo, hi]" = TRUE, "[lo, hi)" = FALSE)
  cut(x, qtiles, labels = labels, right = right, include.lowest = TRUE)
}

harf_not(x)
##  [1] (28.8,45.6] (45.6,71.4] (71.4,85.6] [0,28.8]    (85.6,96]   [0,28.8]   
##  [7] [0,28.8]    (28.8,45.6] (71.4,85.6] (85.6,96]   (85.6,96]   [0,28.8]   
## [13] (71.4,85.6] (45.6,71.4] (71.4,85.6] (71.4,85.6] (28.8,45.6] (28.8,45.6]
## [19] (28.8,45.6] (85.6,96]   (45.6,71.4] (85.6,96]   (45.6,71.4] (45.6,71.4]
## [25] (85.6,96]   (71.4,85.6] [0,28.8]    (28.8,45.6] [0,28.8]    (45.6,71.4]
## Levels: [0,28.8] (28.8,45.6] (45.6,71.4] (71.4,85.6] (85.6,96]

Fonskiyon Yazma -Harmonik ortalama

\[ \frac{n}{\frac{1}{x_{1}}+\frac{1}{x_{2}}+ ... +\frac{1}{x_{n}}} \]

formulden de anlaşılacağı üzere, işlemler birbirine bağlı gerçekleşmektedir.

y <- 1:5
length(y)/sum(1/y) #ortalama işleminin tersi
## [1] 2.189781
harmonik_ort <- function() {
  
  
}

Fonskiyon Yazma -Harmonik ortalama

tersal <- function(x) {
    1/x
}
y <- 1:5
# harmonik ortalama hesaplama

y %>% tersal() %>% mean() %>% tersal
## [1] 2.189781
harmonik_ort <- function(x) {
    x%>% 
    tersal() %>% 
    mean() %>%
    tersal
  
}
harmonik_ort(y)
## [1] 2.189781

Fonskiyon Yazma -Harmonik ortalama

S&P 500 borsa endeksi veri kullanılarak fiyat/kazanç oranı (pe_ratio) değişkenin bir bir sektor için ayrı ayrı harmonik ortalamasını hesaplayalım.

sp500 <- readRDS("sp500.rds")

sp500 %>% 
  group_by(sector) %>% 
  summarise(hmean_pe_ratio = harmonik_ort(pe_ratio))
## # A tibble: 11 x 2
##    sector                 hmean_pe_ratio
##    <chr>                           <dbl>
##  1 Communication Services           NA  
##  2 Consumer Discretionary           NA  
##  3 Consumer Staples                 NA  
##  4 Energy                           NA  
##  5 Financials                       NA  
##  6 Health Care                      NA  
##  7 Industrials                      NA  
##  8 Information Technology           NA  
##  9 Materials                        NA  
## 10 Real Estate                      32.5
## 11 Utilities                        NA

Fonskiyon Yazma -Harmonik ortalama

Eksik verileri çıkararak ortalama almak için, fonksiyona default değeri ile eksik veri silme argümanını ekleyelim.

harmonik_ort <- function(x,na.rm=FALSE) {
    x%>% 
    tersal() %>% 
    mean(na.rm=na.rm) %>%
    tersal()
  
}
sp500 %>%
  group_by(sector) %>% 
  summarise(hmean_pe_ratio = harmonik_ort(pe_ratio,na.rm=TRUE))
## # A tibble: 11 x 2
##    sector                 hmean_pe_ratio
##    <chr>                           <dbl>
##  1 Communication Services           17.5
##  2 Consumer Discretionary           15.2
##  3 Consumer Staples                 19.8
##  4 Energy                           13.7
##  5 Financials                       12.9
##  6 Health Care                      26.6
##  7 Industrials                      18.2
##  8 Information Technology           21.6
##  9 Materials                        16.3
## 10 Real Estate                      32.5
## 11 Utilities                        23.9

Fonskiyon Yazma -Harmonik ortalama

Argüman atlama … argüman kullanmada esneklik sağlamak için eklebilenecek argümanlar yerine … (three dots ellipsis (…) ) kullanılabilir.

harmonik_ort <- function(x,...) {
    x%>% 
    tersal() %>% 
    mean(...) %>%
    tersal()
  
}

sp500 %>%
  group_by(sector) %>% 
  summarise(hmean_pe_ratio = harmonik_ort(pe_ratio,na.rm=TRUE))
## # A tibble: 11 x 2
##    sector                 hmean_pe_ratio
##    <chr>                           <dbl>
##  1 Communication Services           17.5
##  2 Consumer Discretionary           15.2
##  3 Consumer Staples                 19.8
##  4 Energy                           13.7
##  5 Financials                       12.9
##  6 Health Care                      26.6
##  7 Industrials                      18.2
##  8 Information Technology           21.6
##  9 Materials                        16.3
## 10 Real Estate                      32.5
## 11 Utilities                        23.9

Fonskiyon Yazma - Harmonik ortalama

Kullanıcıların argüman değerlerini yanlış girmesi durumunda,hata mesajlari ile uyarı sağlanabilir.

library(assertive)

harmonik_ort <- function(x,...) {
    assert_is_numeric(x)
    x%>% 
    tersal() %>% 
    mean(...) %>%
    tersal()
  
}

# karakter deger girildiğinde
harmonik_ort(sp500$sector)
## Error in harmonik_ort(sp500$sector): is_numeric : x is not of class 'numeric'; it has class 'character'.

Fonskiyon Yazma - Harmonik ortalama

assert_*()fonksiyonlari isteilen uyarıyı sağlamadığında, koşulara bağlı olarak geliştirici hata mesajı ekleyebilir.

harmonik_ort <- function(x,...) {
    assert_is_numeric(x)
    if(any(is_non_positive(x), na.rm = TRUE)) {
    # Throw an error
    stop("x negatif degerler icermektedir..")
    }
    x%>% 
    tersal() %>% 
    mean(...) %>%
    tersal()
  
}

# karakter deger girildiğinde
harmonik_ort(sp500$pe_ratio -50)
## Error in harmonik_ort(sp500$pe_ratio - 50): x negatif degerler icermektedir..

Çoklu çıktılarda düzenleme

mod <- lm(mpg ~ wt + qsec, data = mtcars)

str(mod)
## List of 12
##  $ coefficients : Named num [1:3] 19.746 -5.048 0.929
##   ..- attr(*, "names")= chr [1:3] "(Intercept)" "wt" "qsec"
##  $ residuals    : Named num [1:32] -0.8151 -0.0482 -2.5273 -0.1806 0.5039 ...
##   ..- attr(*, "names")= chr [1:32] "Mazda RX4" "Mazda RX4 Wag" "Datsun 710" "Hornet 4 Drive" ...
##  $ effects      : Named num [1:32] -113.65 -29.116 -9.103 0.357 0.503 ...
##   ..- attr(*, "names")= chr [1:32] "(Intercept)" "wt" "qsec" "" ...
##  $ rank         : int 3
##  $ fitted.values: Named num [1:32] 21.8 21 25.3 21.6 18.2 ...
##   ..- attr(*, "names")= chr [1:32] "Mazda RX4" "Mazda RX4 Wag" "Datsun 710" "Hornet 4 Drive" ...
##  $ assign       : int [1:3] 0 1 2
##  $ qr           :List of 5
##   ..$ qr   : num [1:32, 1:3] -5.657 0.177 0.177 0.177 0.177 ...
##   .. ..- attr(*, "dimnames")=List of 2
##   .. .. ..$ : chr [1:32] "Mazda RX4" "Mazda RX4 Wag" "Datsun 710" "Hornet 4 Drive" ...
##   .. .. ..$ : chr [1:3] "(Intercept)" "wt" "qsec"
##   .. ..- attr(*, "assign")= int [1:3] 0 1 2
##   ..$ qraux: num [1:3] 1.18 1.05 1.08
##   ..$ pivot: int [1:3] 1 2 3
##   ..$ tol  : num 1e-07
##   ..$ rank : int 3
##   ..- attr(*, "class")= chr "qr"
##  $ df.residual  : int 29
##  $ xlevels      : Named list()
##  $ call         : language lm(formula = mpg ~ wt + qsec, data = mtcars)
##  $ terms        :Classes 'terms', 'formula'  language mpg ~ wt + qsec
##   .. ..- attr(*, "variables")= language list(mpg, wt, qsec)
##   .. ..- attr(*, "factors")= int [1:3, 1:2] 0 1 0 0 0 1
##   .. .. ..- attr(*, "dimnames")=List of 2
##   .. .. .. ..$ : chr [1:3] "mpg" "wt" "qsec"
##   .. .. .. ..$ : chr [1:2] "wt" "qsec"
##   .. ..- attr(*, "term.labels")= chr [1:2] "wt" "qsec"
##   .. ..- attr(*, "order")= int [1:2] 1 1
##   .. ..- attr(*, "intercept")= int 1
##   .. ..- attr(*, "response")= int 1
##   .. ..- attr(*, ".Environment")=<environment: R_GlobalEnv> 
##   .. ..- attr(*, "predvars")= language list(mpg, wt, qsec)
##   .. ..- attr(*, "dataClasses")= Named chr [1:3] "numeric" "numeric" "numeric"
##   .. .. ..- attr(*, "names")= chr [1:3] "mpg" "wt" "qsec"
##  $ model        :'data.frame':   32 obs. of  3 variables:
##   ..$ mpg : num [1:32] 21 21 22.8 21.4 18.7 18.1 14.3 24.4 22.8 19.2 ...
##   ..$ wt  : num [1:32] 2.62 2.88 2.32 3.21 3.44 ...
##   ..$ qsec: num [1:32] 16.5 17 18.6 19.4 17 ...
##   ..- attr(*, "terms")=Classes 'terms', 'formula'  language mpg ~ wt + qsec
##   .. .. ..- attr(*, "variables")= language list(mpg, wt, qsec)
##   .. .. ..- attr(*, "factors")= int [1:3, 1:2] 0 1 0 0 0 1
##   .. .. .. ..- attr(*, "dimnames")=List of 2
##   .. .. .. .. ..$ : chr [1:3] "mpg" "wt" "qsec"
##   .. .. .. .. ..$ : chr [1:2] "wt" "qsec"
##   .. .. ..- attr(*, "term.labels")= chr [1:2] "wt" "qsec"
##   .. .. ..- attr(*, "order")= int [1:2] 1 1
##   .. .. ..- attr(*, "intercept")= int 1
##   .. .. ..- attr(*, "response")= int 1
##   .. .. ..- attr(*, ".Environment")=<environment: R_GlobalEnv> 
##   .. .. ..- attr(*, "predvars")= language list(mpg, wt, qsec)
##   .. .. ..- attr(*, "dataClasses")= Named chr [1:3] "numeric" "numeric" "numeric"
##   .. .. .. ..- attr(*, "names")= chr [1:3] "mpg" "wt" "qsec"
##  - attr(*, "class")= chr "lm"

Çoklu çıktılarda düzenleme

library(broom)
## Warning: package 'broom' was built under R version 4.0.5
list(
  # Get model-level values
  model = glance(mod),
  # Get coefficient-level values
  coefficients = tidy(mod),
  # Get observation-level values
  observations = augment(mod)
)
## $model
## # A tibble: 1 x 12
##   r.squared adj.r.squared sigma statistic  p.value    df logLik   AIC   BIC
##       <dbl>         <dbl> <dbl>     <dbl>    <dbl> <dbl>  <dbl> <dbl> <dbl>
## 1     0.826         0.814  2.60      69.0 9.39e-12     2  -74.4  157.  163.
## # ... with 3 more variables: deviance <dbl>, df.residual <int>, nobs <int>
## 
## $coefficients
## # A tibble: 3 x 5
##   term        estimate std.error statistic  p.value
##   <chr>          <dbl>     <dbl>     <dbl>    <dbl>
## 1 (Intercept)   19.7       5.25       3.76 7.65e- 4
## 2 wt            -5.05      0.484    -10.4  2.52e-11
## 3 qsec           0.929     0.265      3.51 1.50e- 3
## 
## $observations
## # A tibble: 32 x 10
##    .rownames    mpg    wt  qsec .fitted  .resid   .hat .sigma .cooksd .std.resid
##    <chr>      <dbl> <dbl> <dbl>   <dbl>   <dbl>  <dbl>  <dbl>   <dbl>      <dbl>
##  1 Mazda RX4   21    2.62  16.5    21.8 -0.815  0.0693   2.64 2.63e-3    -0.325 
##  2 Mazda RX4~  21    2.88  17.0    21.0 -0.0482 0.0444   2.64 5.59e-6    -0.0190
##  3 Datsun 710  22.8  2.32  18.6    25.3 -2.53   0.0607   2.60 2.17e-2    -1.00  
##  4 Hornet 4 ~  21.4  3.22  19.4    21.6 -0.181  0.0576   2.64 1.05e-4    -0.0716
##  5 Hornet Sp~  18.7  3.44  17.0    18.2  0.504  0.0389   2.64 5.29e-4     0.198 
##  6 Valiant     18.1  3.46  20.2    21.1 -2.97   0.0957   2.58 5.10e-2    -1.20  
##  7 Duster 360  14.3  3.57  15.8    16.4 -2.14   0.0729   2.61 1.93e-2    -0.857 
##  8 Merc 240D   24.4  3.19  20      22.2  2.17   0.0791   2.61 2.18e-2     0.872 
##  9 Merc 230    22.8  3.15  22.9    25.1 -2.32   0.295    2.59 1.59e-1    -1.07  
## 10 Merc 280    19.2  3.44  18.3    19.4 -0.185  0.0358   2.64 6.55e-5    -0.0728
## # ... with 22 more rows

BONUS - 1

BONUS -2

Kaynaklar

Atar, B., Atalay Kabasakal, K, Ünsal Özberk, E. B., Özberk, E. H. Ve Kıbrıslıoğlu Uysal, N. (2020).R ile Veri Analizi ve Psikometri Uygulamaları, Editör, Pegem Akademi, Ankara.

Garcia, S. (2012). Introduction to Creating Functions in R [html]. Erişim adresi https://rpubs.com/Sergio_Garcia/introduction_functions_R