Bölüm 5 Fonksiyonlar
Kazanımlar
Fonksiyonların görevi, karmaşık işlemleri bir araya toplayarak, bu işlemleri tek adımda yapmamızı sağlamaktır.
Fonksiyonlar çoğu zaman, yapmak istediğimiz işlemler için bir şablon vazifesi görür.
Fonksiyonları kullanarak, bir veya birkaç adımdan oluşan işlemleri tek bir isim altında toplayabiliriz.
Fonksiyonlar rutin olarak tekrar edilen görevleri veya prosedürleri tek bir ad/çatı altında toplayan araçlardır.
R programlama dilinde fonksiyonlar fonksiyon.adi = function(parametreler){işlemler}
kuralı ile oluşturulurlar.
Hiç parametre içermeyebilirler.
Örneğin ekrana “merhaba” yazdıran fonksiyon aşağıdaki kodda verilmiştir.
= function(){
merhaba print("merhaba")
}
# oluşturulan fonksiyonu kullanabilmek için fonksiyoun
# adından sonra parantez ve varsa parametreler eklenir
merhaba()
## [1] "merhaba"
# kullanıcı adını parametre olarak alan ve
# merhaka kullanıcı adi şeklinde çıktı veren fonksiyon
= function(kullanici.adi){
merhaba2 print(paste("merhaba", kullanici.adi))
}
merhaba2("Harun")
## [1] "merhaba Harun"
= function(ogrenci.adi, ogrenci.no){
merhaba.ogrenci print(paste("merhaba", ogrenci.no, ogrenci.adi))
}
merhaba.ogrenci("Recep", "15")
## [1] "merhaba 15 Recep"
Soru1: Girilen sayının asal olup olmadığını söyleyen fonksiyonu yazınız.
Cevap:
= function(x){
asal.mi = T
sonuc for (s in 2:(x-1)){
if (x %% s == 0){
= F
sonuc # hangi sayıya bölündüğünü görmek için
# sonraki yorum satırını aktifleştirin
# print(s)
break
}
}print(sonuc)
}
asal.mi(7)
## [1] TRUE
asal.mi(21)
## [1] FALSE
asal.mi(4321)
## [1] FALSE
Soru2: Mutlak değer hesaplayan fonksiyon yazınız.
Cevap:
= function(x){
mutlak.deger = x
sonuc if(x < 0){
= x * -1
sonuc
}return(sonuc)
}
mutlak.deger(-8)
## [1] 8
mutlak.deger(0)
## [1] 0
mutlak.deger(4)
## [1] 4
2. Yol: return fonksiyonu kullanılmasa da fonksiyonun son satırındaki ifade fonksiyonun dönüş değeridir.
= function(x){
mutlak.deger = x
sonuc if(x < 0){
= x * -1
sonuc
}
sonuc
}
mutlak.deger(-8)
## [1] 8
mutlak.deger(0)
## [1] 0
mutlak.deger(4)
## [1] 4
Örnek: Basit Hesapmakinesi döngülü (repeat ile) örneğini daha kullanışlı hale getirmek için hatalı giriş yapıldığında da işlem numaraları hatırlatılabilir. Bunu doğrudan print ile alt alta ekleyebilsek de kod uzayacağından anlaşılması zorlaşır. Bu durumda fonksiyonlardan faydalanabiliriz.
Fonksiyon ile desteklenmeyen kod
print("* Hesap Makinesi *")
print("Hesap makinesinde işlem numaraları aşağıdaki gibidir.")
print("0: çıkış")
print("1: Toplama")
print("2: Çıkarma")
print("3: çarpma")
print("4: Bölme")
repeat{
= readline("İşlem numarasını giriniz: ")
islem
if (islem == "0"){
print("çıkılıyor...")
break
}
if (!islem %in% 0:4){
print("Hatalı işlem numarası. Lütfen yeniden deneyin.")
print("Hesap makinesinde işlem numaraları aşağıdaki gibidir.")
print("0: çıkış")
print("1: Toplama")
print("2: Çıkarma")
print("3: çarpma")
print("4: Bölme")
next
}# readline ile alınan değerler karakter olduğundan
# sayısal işlemlere tabi tutamayız bu yüzden önce
# girilen ifadenin sayıya dönüştürülmesi lazım
# bunun için as.numeric() fonksiyonu kullanıldı
= as.numeric(readline("İlk sayıyı giriniz: "))
sayi1 = as.numeric(readline("İkinci sayıyı giriniz: "))
sayi2
if(islem == "1"){
print(paste(sayi1, "+", sayi2, "=", sayi1 + sayi2))
else if(islem == "2"){
}print(paste(sayi1, "-", sayi2, "=", sayi1 - sayi2))
else if(islem == "3"){
}print(paste(sayi1, "*", sayi2, "=", sayi1 * sayi2))
else if(islem == "4"){
}print(paste(sayi1, "/", sayi2, "=", sayi1 / sayi2))
else{
}"hatalı işlem numarası girildiğinden işlem yapamadık"
} }
fonksiyon ile desteklenen kod
= function(){
bilgi print("* Hesap Makinesi *")
print("Hesap makinesinde işlem numaraları aşağıdaki gibidir.")
print("0: çıkış")
print("1: Toplama")
print("2: Çıkarma")
print("3: çarpma")
print("4: Bölme")
}
bilgi()
repeat{
= readline("İşlem numarasını giriniz: ")
islem
if (islem == "0"){
print("çıkılıyor...")
break
}
if (!islem %in% 0:4){
bilgi()
next
}# readline ile alınan değerler karakter olduğundan
# sayısal işlemlere tabi tutamayız bu yüzden önce
# girilen ifadenin sayıya dönüştürülmesi lazım
# bunun için as.numeric() fonksiyonu kullanıldı
= as.numeric(readline("İlk sayıyı giriniz: "))
sayi1 = as.numeric(readline("İkinci sayıyı giriniz: "))
sayi2
if(islem == "1"){
print(paste(sayi1, "+", sayi2, "=", sayi1 + sayi2))
else if(islem == "2"){
}print(paste(sayi1, "-", sayi2, "=", sayi1 - sayi2))
else if(islem == "3"){
}print(paste(sayi1, "*", sayi2, "=", sayi1 * sayi2))
else if(islem == "4"){
}print(paste(sayi1, "/", sayi2, "=", sayi1 / sayi2))
else{
}"hatalı işlem numarası girildiğinden işlem yapamadık"
} }
Örnek: Karakter verisindeki Türkçe karakterleri değiştiren fonksiyon.
# Türkçe karakterleri değiştirir
<- function(x, bosluk="", df=NULL){
degis <- gsub("ç", "c", x)
x <- gsub("Ç", "C", x)
x <- gsub("ğ", "g", x)
x <- gsub("Ğ", "G", x)
x <- gsub("ı", "i", x)
x <- gsub("İ", "I", x)
x <- gsub("ö", "o", x)
x <- gsub("Ö", "O", x)
x <- gsub("ş", "s", x)
x <- gsub("Ş", "S", x)
x <- gsub("ü", "u", x)
x <- gsub("Ü", "U", x)
x <- gsub(" ", bosluk, x)
x
if(!is.null(df)){
for(i in 1:nrow(df)){
<- gsub(df[i, 1], df[i, 2], x)
x
}
}
return(x)
}
degis("Türkçe karakterleri değiştiren fonksiyon", bosluk = "_")
## [1] "Turkce_karakterleri_degistiren_fonksiyon"
5.1 Parametreler
Fonksiyonda kullanılmak üzere oluşturulan ve genelde değerlerini dışarından alan fonksiyon değişkenleridir. Örneğin yukarıda tanımlaman degis isimli fonksiyondaki x, bosluk ve df isimleriyle belirtilen değişkenler parametrelerdir. x parametresinin dışarıdan girilmesi zorunlu iken diğer parametre değerlerinin dışarıdan girilmesine gerek yoktur.
# bosluk ve df parametrelerinin öntanımlı değerleri
# olduğundan dışarıdan veri girilmesi gerekmez
degis("Türkçe karakterleri değiştiren fonksiyon")
## [1] "Turkcekarakterleridegistirenfonksiyon"
# ama x değişkeni için bir tanımlama yapılmadığından
# x değişkeni girilmexse program hata verecektir
degis(bosluk="_")
## Error in gsub("ç", "c", x): varsayılanı olmayan "x" argümanı yok
Fonksiyon parametreler ile tanımlanıp kullanılmak istenirse aşağıdaki başlıklarda belirtilen şekilde kullanılabilir.
5.2 Sıralı (veya İsimsiz) Parametreler
Belirtilen parametre isimleri kullanılmadan sırayla argümanlar verilerek kullanılabilir.
= function(isim, soyisim, numara, sinif, sube){
ogrenci.kayit print(strrep("-", 30))
print(paste("isim : ", isim))
print(paste("soyisim : ", soyisim))
print(paste("numamra : ", numara))
print(paste("sınıf : ", paste0(sinif, "-", sube)))
print(strrep("-", 30))
}
# parametre isimleri belirtilmeden kullanılacaksa
# değerler sırasıyla yazılmalı
ogrenci.kayit("Veli", "Deli", 1234, "9", "A")
## [1] "------------------------------"
## [1] "isim : Veli"
## [1] "soyisim : Deli"
## [1] "numamra : 1234"
## [1] "sınıf : 9-A"
## [1] "------------------------------"
5.3 İsimli Parametreler
Fonksiyon kullanılırken parametre isimleri belirtildiğinde sıralama gerekli değildir.
# Eğer fonksiyon kullanılırken parametre isimleri belirtilirse
# fonksiyon tanımlanırken belirtilen parametre sırası önemini yitirir.
merhaba.ogrenci(ogrenci.no = 15, ogrenci.adi = "Recep")
## [1] "merhaba 15 Recep"
# isimleri belirtilen parametreler için sıra önemli değildir
ogrenci.kayit(num = 1234, isim = "Veli", sinif = "9", soyisim = "Deli", sube = "A")
## [1] "------------------------------"
## [1] "isim : Veli"
## [1] "soyisim : Deli"
## [1] "numamra : 1234"
## [1] "sınıf : 9-A"
## [1] "------------------------------"
Aynı anda hem isimli hem isimsiz parametre kullanılabilir bu durumda isimsiz parametrelerin yine kendi aralarında sırayla yazılması gerekir. Aksi takdirde bu durumda fonksiyon hatalı çalışacaktır.
# aynı anda hem isimli hem isimsiz parametre kullanılabilir bu durumda
# isimsiz parametrelerin yine kendi aralarında sırayla yazılması gerekir
ogrenci.kayit(numara = 1234, isim = "Veli", sinif = "9", "A", "Deli")
## [1] "------------------------------"
## [1] "isim : Veli"
## [1] "soyisim : A"
## [1] "numamra : 1234"
## [1] "sınıf : 9-Deli"
## [1] "------------------------------"
ogrenci.kayit(numara = 1234, isim = "Veli", "A", "Deli", sinif = "9")
## [1] "------------------------------"
## [1] "isim : Veli"
## [1] "soyisim : A"
## [1] "numamra : 1234"
## [1] "sınıf : 9-Deli"
## [1] "------------------------------"
Bunlara ek olarak parametre isimler diğer parametre isimleriyle çakışmayacak şekilde kısaltılabilir.
# aynı anda hem isimli hem isimsiz parametre kullanılabilir bu durumda
# isimsiz parametrelerin yine kendi aralarında sırayla yazılması gerekir
ogrenci.kayit(num = 1234, isim = "Veli", sin = "9", "Deli", "A")
## [1] "------------------------------"
## [1] "isim : Veli"
## [1] "soyisim : Deli"
## [1] "numamra : 1234"
## [1] "sınıf : 9-A"
## [1] "------------------------------"
5.4 Varsayılan Değerli Parametreler
Fonksiyon tanımlanırken parametrelere varsayılan değerler verebiliriz. Örneğin;
# Türkçe karakterleri değiştirir
<- function(x, bosluk="_", df=NULL){
degis <- gsub("ç", "c", x)
x <- gsub("Ç", "C", x)
x <- gsub("ğ", "g", x)
x <- gsub("Ğ", "G", x)
x <- gsub("ı", "i", x)
x <- gsub("İ", "I", x)
x <- gsub("ö", "o", x)
x <- gsub("Ö", "O", x)
x <- gsub("ş", "s", x)
x <- gsub("Ş", "S", x)
x <- gsub("ü", "u", x)
x <- gsub("Ü", "U", x)
x <- gsub(" ", bosluk, x)
x
if(!is.null(df)){
for(i in 1:nrow(df)){
<- gsub(df[i, 1], df[i, 2], x)
x
}
}
return(x)
}
degis("Türkçe karakterleri değiştiren fonksiyon")
## [1] "Turkce_karakterleri_degistiren_fonksiyon"
degis("Türkçe karakterleri değiştiren fonksiyon", bosluk = "/")
## [1] "Turkce/karakterleri/degistiren/fonksiyon"
5.5 Rastgele Sayıda isimli/İsimsiz Parametre Belirleme
R porgramlama dilinde fonksiyon tanımlarken rastgele sayıda parametre alınabilir.
Bunun için ...
ifadesinden yararlanılır.
...
ifadesini kullanabilmek için vektör veya liste olarak almalıyız.
örneğin python programlama dilindeki print benzeri bir fonksiyon yazmak istersek Aşağıdaki gibi yazabiliriz.
*** isimsiz parametre alma***
= function(...){
yaz # `...` değerini kullanabilmek için
# c fonksiyonuyla vektör olarak değerleri
# bir değişkene (burada ext.args) aktarıldı
= c(...)
ext.args print(paste(ext.args, collapse = " "))
}
yaz("İTÜ", "MTAL", 1:5, "9. sınıf")
## [1] "İTÜ MTAL 1 2 3 4 5 9. sınıf"
= function(...){
yaz = list(...)
ext.args
= if ("a" %in% names(ext.args)) ext.args$a else "değer girilmedi"
a print(a)
}
yaz(a="İTÜ", b="MTAL", c=1:5)
## [1] "İTÜ"
5.6 return Fonksiyonu
return
fonksiyonu, fonksiyonda yapılan işlemler sonucunda elde edilen veriyi dışarı aktarmak için kullanılır.
Örneğin;
= function(x, y){
topla return(x + y)
}
= topla(10, 15)
a print(a)
## [1] 25
Ya da fonksiyon sonunda doğrudan değeri eklemekde aynı sonuca ulaştırır.
Ama her zaman fonksiyon sonunda değer aktarması yapılmayacağından dığer durumlarda return
fonksiyonu kullanılmalıdır.
= function(x, y){
topla + y
x
}
= topla(10, 15)
a print(a)
## [1] 25
# fonksiyon sonundan önce değer aktarılıp fonksiyon sonlandırılacaksa
# return fonksiyonu kullanılmak zorundadır. Örneğin yukarıdaki "topla"
# fonksiyonuna sayısal değer hariç bir değer girilirse hataya sebep olacaktır.
# bu durumda değerlerin sayısal değer olup olmadığı kontrol edilerek de
# değer aktarılabilir
= function(x, y){
topla if(!is.numeric(x) | !is.numeric(y)){
return(NULL)
}+ y
x
}
= topla("10", 15)
s1 print(s1)
## NULL
= topla(10, 15)
s2 print(s2)
## [1] 25
5.7 İç İçe Fonksiyonlar
Bir fonksiyon tanımlanırken fonksiyon bloğunda başka bir fonksiyon tanımlanıp fonksiyon içinde kullanılabilir.
= function(x){
fonksiyon1 = function(x){
ekle + 1
x
}
while(T){
if(x==3) break
print(x)
= ekle(x)
x
}
}
fonksiyon1(1)
## [1] 1
## [1] 2
5.8 Özyinelemeli (Recursive) Fonksiyonlar
Fonksiyonlar başka fonksiyonları çağırabildiği gibi kendi kendilerini de çağırabilirler. İşte bu tür fonksiyonlara ‘kendi kendilerini yineleyen’, veya daha teknik bir dille ifade etmek gerekirse ‘özyinelemeli’ (recursive) fonksiyonlar adı verilir.
= function(x){
geri_sayim if(x == 0) return(0)
print(x)
#
# Sys.sleep(1)
geri_sayim(x - 1)
}
geri_sayim(10)
## [1] 10
## [1] 9
## [1] 8
## [1] 7
## [1] 6
## [1] 5
## [1] 4
## [1] 3
## [1] 2
## [1] 1
## [1] 0
Soru: Faktoryel hesaplayan fonksiyon yazınız.Faktoryel fonksiyonu aldığı Doğal Sayı değeri kendinden küçük sıfırdan büyük olan doğal sayılarla çarpan bir fonksiyondur. Örneğin 3! (3 faktoryel) = 3.2.1 = 6 dır. Not: sıfır faktoryel 1 dir
Cevap:
= function(x){
fkt if(x == 0) return(1)
return(x * fkt(x - 1))
}
fkt(3)
## [1] 6
Gömülü Fonksiyonlar
Programlama dillerinde halihazırda tanımlı fonksiyonlar bulunur bu fonksiyonlara gömülü fonksiyonlar denir. Örneğin sürekli kullandığımız print() ve paste() fonksiyonları bu dile ait gömülü fonksiyonlardır. Aşağıda çeşitli vektör sınıflarına ait gömülü fonksiyonlar gösterilmiştir.
Sayısal vektör sınıfları için gömülü fonksiyonlar
TABLO
Fonksiyon | Tanım |
---|---|
abs(x) | mutlak değer bulur |
sqrt(x) | karekök bulur |
ceiling(x) | yukarı yuvarlama. ceiling(3.475) = 4 |
floor(x) | aşağı yuvarlama. floor(3.475) = 3 |
trunc(x) | girilen sayının tamsayı kısmını verir. trunc(5.99) = 5 trunc(-5.1) = -5 |
round(x, digits=n) | yuvarlama. round(3.475, digits=2) = 3.48 |
signif(x, digits=n) | girilen basamak numarasına göre sayı yuvarlanır. signif(3.475, digits=2) = 3.5 |
cos(x), sin(x), tan(x) , acos(x), … | trigonometrik fonksiyonlar |
log(x) | doğal logaritma |
log10(x) | common logarithm |
Karakter Fonksiyonları
Fonksiyon | Tanım |
---|---|
substr(x, start=n1, stop=n2) | Bir karakter vektöründeki alt dizeleri ayıklar veya değiştirir. x <- “abcdef” substr(x, 2, 4) alt dizisi “bcd” dir. substr(x, 2, 4) <- “22222” şeklinde “a222ef” |
strsplit(x, split) | split ile belirtilen ifadeye göre x ile belirtilen karakter parçalarına ayrılır. strsplit(“abc”, "“) returns 3 element vector”a“,”b“,”c" |
paste(…, sep="") | karakteri birleştirmek için kullanılır paste(“x”,1:3,sep="“) returns c(”x1“,”x2" “x3”) paste(“x”,1:3,sep=“M”) returns c(“xM1”,“xM2” “xM3”) paste(“Today is”, date()) |
toupper(x) | karakterleri büyük harfe çevirir. Türkçe karakterler için uygun dönüşüm yapılamayabilir. |
tolower(x) | karakterleri küçük harfe çevirir. Türkçe karakterler için uygun dönüşüm yapılamayabilir. |
strrep(x, times) | x ile belirtilen karakterin tekrar etmesini sağlar |
İstastistiksel fonksiyonlar
Function | Description |
---|---|
mean(x, trim=0, na.rm=FALSE) | x nesnesne ait ortalamayı bulur # trimmed mean, removing any missing values and # 5 percent of highest and lowest scores mx <- mean(x,trim=.05,na.rm=TRUE) |
sd(x) | x nesnesine ait standart sapmayı bulur |
median(x) | median |
range(x) | minimum ve maksimum bulur |
sum(x) | toplam |
diff(x, lag=1) | lagged differences, with lag indicating which lag to use |
min(x) | minimum |
max(x) | maksimum |
scale(x, center=TRUE, scale=TRUE) | column center or standardize a matrix. |
Yukarıda R programlama dilinde dahili olarak gelen bazı fonksiyonlar gösterilmiştir.
Bunların dışında hali hazırda paket olarak gelen fonsiyonlar, sınıflar, … da vardır.
Ek olarak bağımsız geliştiriciler tarafından sunulan paketler de vardır ve indirlip kurularak kullanıma hazır hale getirilebilirler.
Bu paketlere ulaşmak için library
fonksiyonundan yararlanılır.
Örneğin çeşitli tarih fonksiyonlarını barındıran lubridate adlı paketi R programımıza dahil etmek için aşağıdaki kodu kullanmamız gerekir.
library(lubridate)
Eğer dışarıdan paket kurmak istersek install.packages
fonksiyonunu kullanmamız gerekir.
Örneğin ggplot2 isimli grafik oluşturma paketini yüklemek için aşağıdaki kodu kullanabiliriz.
install.packages("ggplot2")
Eğer daha önce yazdığımız bir R dosyasındaki fonksiyonlara erişmek istersek source
fonksiyonundan yararlanabiliriz:
# daha önce oluşturduğumuz fonksiyon dosyamız
# D:/betik/fonksiyon.R adresinde ise
source("D:/betik/fonksiyon.R", encoding = "utf-8")
# encoding ile belirtilen parametre dosyanın
# hangi kodlama sistemiyle yazıldığını belitir
# windows için varsayılan kodlama sistemi cp1254 dür
# linux için ise utf-8 dir.
#
# istenirse Rstudio ayarlarından bu kayıt türü
# istenilen şekilde değiştirilebilir
Sorular
Dikdörtgen alanı hesaplayan fonksiyonu yazınız.
Ekrana ilk olarak “Yıldız üçgen çiziliyor :” mesajını getiren, ardından her satıra bir döngü ile “*” işareti koyarak üçgen çizen fonksiyonu yazınız.
Ekrana çarpım tablosunu yazan fonksiyonu yazınız.
2 sınav ve bir sözlü notunu parametre olarak alan ve ortalamayı bulup 50 ve üstü notlar için “Geçti” , tersi için kaldı yanıtı veren fonksiyonu yazınız.
Girilen sayının tam bölünlerini bulup vektör olarak gösteren fonksiyonu yazınız.
Fibonacci dizisinin ilk 20 elemanını yazdıran bir özyinelemeli fonksiyonuyazınız.
Cevaplar
= function(a, b){
dikdortgen.alan return(a * b)
}
dikdortgen.alan(4, 5)
## [1] 20
= function(x){
yildiz.ciz print("Yıldız çizdiriliyor")
for (i in 1:x){
print(strrep("*", i))
}
}
yildiz.ciz(10)
## [1] "Yıldız çizdiriliyor"
## [1] "*"
## [1] "**"
## [1] "***"
## [1] "****"
## [1] "*****"
## [1] "******"
## [1] "*******"
## [1] "********"
## [1] "*********"
## [1] "**********"
= function(){
carpim.tablosu for(i in 1:10){
print(strrep("=", 30))
for(j in 1:10){
print(paste(i, "x", j, "=", i*j))
}
}
}
carpim.tablosu()
# sonucunu bilgisayarınızda gözlemleyebilirsiniz.
= function(yazili1, yazili2, sozlu, gecme.notu=50){
ortalama = (yazili1 + yazili2 + sozlu) / 3
sonuc if (sonuc > gecme.notu){
print("geçti")
else{
}print("Kaldı")
}
}
ortalama(45,75,70)
## [1] "geçti"
ortalama(45,75,70,70) # gecme.notu 70 ise
## [1] "Kaldı"
= function(x){
tam.bolen.bul = c()
bolenler
for (i in 1:x){
if(x %% i == 0){
= c(bolenler, i)
bolenler
}
}
bolenler
}
tam.bolen.bul(5) # 5 in bölenleri
## [1] 1 5
tam.bolen.bul(15) # 15 in bölenleri
## [1] 1 3 5 15
= function(n){
fibonacci if(n == 1){
return(1)
else if (n == 2){
}return(1)
else{
}return(fibonacci(n-1) + fibonacci(n-2) )
}
}
for(i in 1:20)
print(fibonacci(i))
## [1] 1
## [1] 1
## [1] 2
## [1] 3
## [1] 5
## [1] 8
## [1] 13
## [1] 21
## [1] 34
## [1] 55
## [1] 89
## [1] 144
## [1] 233
## [1] 377
## [1] 610
## [1] 987
## [1] 1597
## [1] 2584
## [1] 4181
## [1] 6765