Bölüm5 Fonksiyonlar
Fonksiyonlar, R programlama dilinin en kuvvetli özelliklerinden biridir. Aslında şu ana kadar birkaç kez fonksiyonlarını kullandık. Örneğin print()
fonksiyonu ile yazdırmak istediğimiz şeyleri yazdırdık. Fonksiyonlar aslında “kara kutu” ilkesi ile çalışır. Bu sistemlerde bir girdi sağlanır, girdi “kara kutu”da işlenir ve bir çıktı oluşur.
Yukarıdaki örnekte 1, 5, 6 ve 7 sayılarından oluşan bir vektörün standart sapmasının sd()
fonksiyonu ile hesaplanma işlemini görüyorsunuz. R sd
fonksiyonunu “kara kutu”su içinde kullanarak bu sayı dizisinin standart sapmasını hesaplayıp raporladı.
Fonksiyonların kullanımında argümanların girdiler olarak tanımlanması esastır ve tüm argümanlar fonksiyon parantezinde tanımlanır. Yukarıdaki örneğin R kodunu hali aşağıda görebilirsiniz
sd(c(1,5,6,7))
## [1] 2.63
Burada 4 sayıdan oluşan bir vektör tek argüman olarak sd()
fonksiyonuna tanımlanmıştır. Aynı işlemi bu vektörü bir değişken olarak tanımlayıp da yapabiliriz:
sayilar <- c(1,5,6,7)
sd(sayilar)
## [1] 2.63
Fonksiyonun kendisini de değişken olarak tanımlamak mümkündür. işlemi yapıp değişkeni çağırdığımızda aynı sonuç ortaya çıkar.
benim_sayilar <- sd(sayilar)
benim_sayilar
## [1] 2.63
5.1 Fonksiyon Açıklamaları
R ve R paketleri binlerce fonksiyon barındırdığından, tüm bu fonksiyonların kullanımında gerekli argümanların hepsini bilmek mümkün değildir. Bu yüzden kullanmak istediğimiz fonksiyonun argümanlarını ilgili fonksiyonun yardım dökümanını inceleyerek öğrenebiliriz. Bu işlemi sd()
için gerçekleştirmek istediğimizde
help(sd)
veya
?sd
yazılması gerekir. Bu komut yazıldığında RStudio içinde “Help” kısmında yardım dökümanı açılır. Yardım dökümanlarının içindeki “Usage” başlığı fonksiyonların gerekli argümanlarını içerir. Bu işlemi sd()
için yaptığımında “Usage” altında
sd(x, na.rm = FALSE)
ifadesini görürüz. Buradan sd()
fonksiyonun iki argümanı olduğunu görürüz: Birincisi “x” ve ikincisi “na.rm=FALSE”. Buradaki “x” sd()
fonksiyonuna koymak istediğiniz değerleri ifade etmektedir ve R bu girdiyi fonksiyondaki pozisyonuna göre algılar. Bu örnekte parantezde ilk olarak girilen değer R için “x” olarak algılanır. Yardım dökümanının “Arguments” kısmı incelendiğinde “na.rm” argümanının ise incelenen veri seti içindeki kayıp verinin/boş hücrelerin (missing value), R tarafından nasıl işleneceğine dair olan karar ile alakalı olduğu anlaşılır: Bu veriler analizden kaldırılmalı mı yoksa analiz bu şekilde devam mı etmeli?.
Bu durumu vektörümüze bir “NA/kayıp veri” ekleyerek inceleyelim.
sayilar <- c(1, 5, 6, NA)
sd(sayilar)
## [1] NA
R bu kodun sonucunu “NA” olarak yani, hesaplayamadan raporladı çünkü R kayıp veri “NA” yı hesaplamalardan çıkarmadan bu kodu çalıştırdı. “NA” değerinin kaldırılmadan hesap yapılıyor olması R için sd()
fonksiyonunun varsayılan değerlerinin (default) bu şekilde tanımlanmasından kaynaklanmaktadır (Bu durum “Usage” kısmında belirtilmektedir). Bu durumu aşmak için bu argümanın değerini değiştirmek gerekir. Aşağıda bu işlemi gerçekleştiren kodu bulabilirsiniz.
sd(sayilar, na.rm=TRUE)
## [1] 2.65
Fonksiyonların argümanları eksik yazıldığında aşağıdakine benzer hata mesajları oluşur:
sd() Error in is.data.frame(x) : argument “x” is missing, with no default
Eğer bir fonksiyonun default değerleri önceden tanımlanmamışsa (ki buradaki örnekte “x” tanımlanmamış ama “na.rm” tanımlanmış durumdadır) R kullanıcıdan bu değeri (bizim örneğimizde “x”) tanımlamasını bekler, tanımlanmış olanı ise kendisi işleme otomatik sokar.
Fonsiyonlarım tüm yardım dökümanlarını okumadan args()
fonksiyonunu kullanarak, bir fonksiyona ait argümanları görebiliriz:
args(sd)
## function (x, na.rm = FALSE)
## NULL
5.2 Fonksiyonların Kullanımı
Fonksiyonlar anlaşılmadan R’dan tam anlamıyla faydalanmak olası değildir. Bundan sonraki örneklerde ortalma hesaplamaya yarayan mean()
fonksiyonunu deteylı bir şekilde inceleyeceğiz.
mean()
fonksiyonunun yardım dosyasına ulaşmak için aşağıdaki kodları çalıştırıp RStudio ekranında çıkan bilgileri inceleyiniz.
?mean
#veya
help(mean)
mean()
fonksiyonlarının argümanları için ise args()
fonksiyonunu kullanalım
args(mean)
## function (x, ...)
## NULL
Yukarıdaki bilgilerden mean()
fonksiyonu hakkında
mean()
fonksiyonunun aritmetik ortalama hesaplamak için kullanıldığını,- “x” ve “…” gibi birden fazla argümana sahip olduğunu, ve
- “x” argümanının nümerik, mantıksal veya zaman formunda bir vektör olması gerektiğini
anlıyoruz.
Gençlerbirliği ve Ankaragücü’nün geçen hafta attığı golleri hatırlayalım. Her iki takımın da ortalamalarını hesaplayıp “ort_gen” ve “ort_ank” isimli iki ayrı vektör olarak tanımlamak istediğimizde aşağıdaki kodu yazabiliriz.
ort_gen <- mean(genclerbirligi)
ort_ank <- mean(ankaragucu)
ort_gen
## [1] 2.14
ort_ank
## [1] 2
mean
yardım dosyasında trim
ve na.rm
agümanlarının olduğunu da görmüştük. trim
argümanı “x” vektörünün her iki ucundaki, eğer varsa, uç değerlerin ortalama hesabından çıkartılması için kullanılır ve 0 ila 0.5 arasında bir değer alır. Bu argümana 0.2 değerini verip ortalamaları tekrar hesaplayalım ve sonucunu inceleyelim.
ort_gen_t <- mean(genclerbirligi, trim = 0.2)
ort_ank_t <- mean(ankaragucu, trim = 0.2)
ort_gen_t
## [1] 2
ort_ank_t
## [1] 1.8
trim
komutu ilgili vektörlerin başta ve sonda blunan değerlerini hesaba katmadan ortalamayı hesapladığımızda farklı bir sonuç elde ettik.
na.rm
ise daha önce de değindiğimiz gibi vektörlerdeki kayıp veriler hakkında ne yapılacağına dair bir argümandır. Gençlerbirliği’ne ait vektörde bazı haftalara ait bilgilerin bulunmadığını varsayalım ve na.rm
argümanını kullanmadan ve kullanarak ortalama alındığında neyin değiştine bir göz atalım
genclerbirligi_na <- c(4, 3, NA, 2, 0, NA, 1)
mean(genclerbirligi_na)
## [1] NA
mean(genclerbirligi_na, na.rm=TRUE)
## [1] 2
Görüldüğü gibi R ilk ortalama hesabını yapamadı, ikincisinde ise kayıp veriyi hesaplamadan çıkarmasını na.rm=TRUE
olarak tanımladığımızda işlemi gerçekleştirdi.
Fonksiyonların bir özelliği de iç içe kullanılabilmesidir. Aşağıdaki kodu inceleyin
mean(abs(genclerbirligi-ankaragucu))
## [1] 1.29
yukarıdaki kod abs
fonksiyonunu kullanarak ilk önce Gençlerbiliği ve Ankaragücü arasındaki haftalık gol farkını mutlak değer cinsinden (absolute value) buldu ve aynı anda bu farkın ortalamasını mean
fonksiyonu ile hesapladı.
5.3 Fonksiyon Yazımı
R, kullanıcılarına kendi fonksiyonlarını yaratma olanağını da tanımaktadır. Yani istediğinizde kendi fonksiyonlarınızı yazarak başka paketlere gereksinim olmadan istediğiniz işlemleri yapabilirsiniz.
Fonksiyonların temel yazım ilkesi aşağıdaki gibidir.
fonksiyonum <- function(argüman1, argüman2) {
esas_işlem
}
Koddaki <-
işaretine dikkat ediniz. Bu işaretten R’ın fonksiyonları sanki bir R nesnesi gibi algıladığını anlıyoruz. Fonksiyonu yazdıktan sonra fonksiyonum
çalışma alanımıza bir R nesnesi gibi yerleşecektir.
Nümerik bir değerin karesini alan “kare” adında bir fonksiyon yazıp, 12 değeri ile çalıştırıp sınayalım
kare <- function(x){
x*x
}
kare(12)
## [1] 144
Şimdi ise iki argümanı olan ve toplama işlemi yapan “topla” isimli bir fonksiyon yazalım
topla <- function(x, y){
x+y
}
topla(-2,3)
## [1] 1
Kimi zaman fonksiyonlara argüman tanımlanmaz. Örneğin zar atan bir fonksiyon tanımlayalım
zar <- function(){
sayi <- sample(1:6, size = 1)
sayi
}
zar()
## [1] 6
Fonksiyonumuzu çalıştırdığımızda 4 sayısını üretti. Tekrar tekrar deneyip fonksiyonun ürettiği sayılara göz atın.
Daha önce incelediğimiz fonksiyonlarda bazı argümanların önceden tanımlı değerlerinin olduğunu görmüştük. Kendi yazdığımız fonksiyonlarda da önceden tanımlı değerleri (default) kullanabiliriz. Aşağıdaki kodu kontrol edin
fonksiyonum <- function(arg1, arg2 = deger) {
esas_işlem
}
Girdiğimiz değeri 3 ile çarpan ama bu işi sadece x değerini kullanarak yapan ve sonucuda farklı bir şekilde raporlayan bir fonksiyon yazalım. Bu işlem için daha önceden öğrendiğimiz if
koşulunu kullanacağız.
carpi3 <- function (x, yazdir=TRUE){
z <- x*3
if(yazdir){
print(paste("Bu fonksiyon bize", z, "sayısını verir"))
}
return(z)
}
carpi3(8)
## [1] "Bu fonksiyon bize 24 sayisini verir"
## [1] 24
Fonksiyonumuz çalıştığında önceden tanımlı default değeri TRUE
olduğundan, tanımladığımız metin şeklinde sonucu raporladı. Aynı fonksiyonu şimdi de default değerini yani TRUE
argümanını FALSE
yaparak deneyelim
carpi3(8, FALSE)
## [1] 24
Gördüğünüz gibi fonksiyon sadece default değerde metin olarak ifade sonucunu üretmek üzere yazıldığından, argümanı FALSE
olarak tanımladığımızda sadece nümerik değeri raporladı.
Aşağıdaki kodu inceleyelim
uckati <- function(x) {
x <- 3*x
x
}
a <- 5
uckati(a)
## [1] 15
a
## [1] 5
uckati
fonksiyonuna daha önceden “a” objesi olarak tanımladığımız 5 değerini yerleştirdiğimizde 15 sonucunu elde ediyoruz. Ancak “a” nesnesini kendi başına çağırdığımızda ise orjinal değeri olan 5 raporlanıyor. Buradan şunu anlıyoruz: fonksiyonlar dışında tanımlanmış R nesneleri orjinal değerlerini korurlar. Yani R argümanları değerleri ile kullanır.
Fonksiyon bilgimizi biraz daha derinleştirelim. Gençlerbirliği’ne ve Ankaragücü’ne ait golleri hafta bazında analiz eden bir fonksiyon yazalım. Fonksiyonumuzun “goller” adı altında tek argümanı olsun, eğer “goller” argümanı 1 den büyükse “Gelsin goller!” 1 veya daha az ise “Daha fazla gol lazım” yazdırsın ve bu işlemi her iki takım için de yapsın.
analiz <- function(goller){
if (goller > 1){
print("Gelsin goller!")
return(goller)
} else {
print("Daha fazla gol lazım")
return(goller)
}
}
Şimdi fonksiyonu vektörler içindeki haftaları []
ile seçerek çalıştıralım. Örneğin üçüncü hafta için
#Fonksiyonu çalıştıralım
analiz(genclerbirligi[3])
## [1] "Daha fazla gol lazim"
## [1] 0
analiz(ankaragucu[3])
## [1] "Daha fazla gol lazim"
## [1] 0
Bir de ilk haftaya bakalım
#Fonksiyonu çalıştıralım
analiz(genclerbirligi[1])
## [1] "Gelsin goller!"
## [1] 4
analiz(ankaragucu[1])
## [1] "Gelsin goller!"
## [1] 5
Yukarıdaki fonksiyonumuz tek bir hafta ile ilgili bilgi sağlıyor. Tüm haftaları (tüm vektörü) ve hatta içinden bazı özel haftaları incelemek istediğimizde fonksiyonumuzu aşağıdaki gibi güncelleyebiliriz.
analiz_tum <- function (toplam_gol, butun_goller=TRUE){
goller1 <- 0
for (g in toplam_gol){
goller1 <- goller1 + analiz(g)
}
if (butun_goller){
return(goller1)
} else{
return(NULL)
}
}
Şimdi kodumuzu çalıştıralım
analiz_tum(genclerbirligi)
## [1] "Gelsin goller!"
## [1] "Gelsin goller!"
## [1] "Daha fazla gol lazim"
## [1] "Gelsin goller!"
## [1] "Daha fazla gol lazim"
## [1] "Gelsin goller!"
## [1] "Daha fazla gol lazim"
## [1] 15
analiz_tum(ankaragucu)
## [1] "Gelsin goller!"
## [1] "Daha fazla gol lazim"
## [1] "Daha fazla gol lazim"
## [1] "Gelsin goller!"
## [1] "Gelsin goller!"
## [1] "Gelsin goller!"
## [1] "Daha fazla gol lazim"
## [1] 14
5.4 R Fonksiyon Paketleri
Sizlerin de farkettiği gibi aslında bizim yazmadığımız bazı fonksiyonları, -sd()
ve print()
gibi- şu ana kadar birkaç kez kullandık. Bu fonksiyonlar R’ın temel kurulumunun içinde bulunan tanımlı paketlerin fonksiyonlarıdır. Paketler R dünyasının vazgeçilmez bileşkeleridir. Dünyadaki milyonlarca R kullanıcısı her gün farklı işlemler için farklı fonksiyonları bir araya getiren paketleri üretip R kullanıcıları ile paylaşmaktadır. R kullanıcıları da, çoğunlukla, işlemlerini yerine getirmek için hazır yazılmış bu paketleri kullanırlar. Paketleri incelemek için “CRAN: Comprehensive R Archive Network” adresini ziyaret edebilirsiniz.
R’ı ilk kurduğumuzda içinde tanımlı paketlerden biri base()
paketidir. Örneğin mean()
fonksiyonu bu paketin bir parçasıdır. Farklı işlemler için gerekli olan paketleri Internet üzerinden yapacağınız araştırma ile bulabilir ve kullanmak istediğiniz R paketini bilgisayarınıza indirebilirsiniz.
Paketleri kullanmak için iki aşamalı bir işlem yapmamız gerekiyor: ilk başta paketi indirmek sonra da aktif R oturumuna yüklemek. ilk indirme işlemini R içinden yapmak istediğimizde install.packages()
fonksiyonunu kullanırız. Örneğin çok kullanılan bir grafik paketi olan “ggvis” paketini R içinde kullanmak istediğimizde
install.packages("ggvis")
komutunu yazarız.
ikinci aşama için library()
komutu kullanılır.
library(ggvis)
Açık R oturumunda hangi paketlerin kullanımda olduğunu search()
komutu ile görebilirsiniz. Bu komutu yazdığınızda göreceksiniz ki R siz söylemeden bazı paketleri hali hazırda içinde yüklenmiş olarak barındırmaktadır. Bu noktada require()
fonksiyonundan da bahsetmek gerekir. require()
da aynı library()
fonksiyonu gibi istediğiniz paketi kullanmak içindir. Arasındaki fark require()
kullanmak istediğiniz paket bilgisayarınıza yüklenmemişse (dikkat! indirmek değil yüklemek) ilk başta bu işlemi gerçekleştirir. Bir başka deyişle library()
fonksiyonuna iyi bir alternatiftir.
5.5 apply
Fonksiyon Ailesi
apply
fonksiyon ailesi daha önce öğrendiğimiz loop
fonksiyonlarının yaratılmasını bir hayli kolaylaştırır. Daha önce kullandığımız Ankara’nın semtlerini içerin vektörümüzü hatırlayalım.
semtler <- c("Yeni Doğan", "Solfasol", "çankaya", "Dikmen", "Esat", "Cebeci")
Bu vektör üzerinde “for” döngüsü içerisinde nchar()
fonksiyonunu kullanarak semtlerin kaçar harf içerdiğini incelemiştik. Bu işlemi daha kolay hale getiren lapply()
fonksiyonunun kullanımı aşağıdaki gibidir
lapply(semtler, nchar)
## [[1]]
## [1] 10
##
## [[2]]
## [1] 8
##
## [[3]]
## [1] 7
##
## [[4]]
## [1] 6
##
## [[5]]
## [1] 4
##
## [[6]]
## [1] 6
Gördüğünüz gibi lapply()
sonucu bir liste halinde bize sundu. bu fonksiyonun sonuçları hep list
formatında raporlanır. Eğer sonuçları bir vektör haline getirmek istersek lapply()
ın başına unlist()
fonksiyonunu yazabiliriz.
unlist(lapply(semtler, nchar))
## [1] 10 8 7 6 4 6
lapply()
fonksiyonunu kendi yazdığımız fonksiyonlar içinde de kullanabiliriz.Benzin fiyatlarını içeren benzin_fiyat
vektörü üzerinde, istediğimiz bir çarpan ile
benzin_fiyat <- list(5.37, 5.49, 5.18, 5.22, 5.47, 5.32)
zam <- function(x, oran) {
x * oran
}
#Fonksiyonu 2 oran ile çalıştıralım ve "o2" vektörü olarak tanımlayalım
sonuc1 <- lapply(benzin_fiyat, zam, oran=2)
o2 <- unlist(sonuc1)
o2
## [1] 10.7 11.0 10.4 10.4 10.9 10.6
#Fonksiyonu 0.5 oran ile çalıştıralım ve "o3" vektörü olarak tanımlayalım
sonuc2 <- lapply(benzin_fiyat, zam, oran=0.5)
o3 <- unlist(sonuc2)
o3
## [1] 2.68 2.75 2.59 2.61 2.73 2.66
Görüldüğü üzere bir vektörün üzerinde toplu bir işlem yapılması gerektiğinde lapply()
fonksiyonu bu işe kolaylıkla gerçekleştirmektedir.
Eğer üstünde çalıştığımız bir liste değil de, içeriği aynı türden oluşan bir vektör ise işleri daha da kolaylaştıran sapply()
fonksiyonunu kullanabiliriz. Semtlerden oluşan vektörümünüz yapısını str()
(structure) fonksiyonunu kullanarak inceleyelim.
str(semtler)
## chr [1:6] "Yeni Dogan" "Solfasol" "çankaya" "Dikmen" "Esat" "Cebeci"
Görüldüğü üzere bu vektörde bulunan elemanların hepsi chr
yani character türünde. Şimdi sapply()
fonksiyonu ile her semt isminin kaç karakterden oluştuğuna bakalım.
sapply(semtler, nchar)
## Yeni Dogan Solfasol çankaya Dikmen Esat Cebeci
## 10 8 7 6 4 6
Gördüğünüz gibi lapply()
dan farklı olarak sonuç otomatik olarak bir vektör halinde raporlandı. Hatta sonuçlara semtlerin isimleri de eklendi. Eğer isimleri istemezsek fonksiyonun USE.NAMES
argümanını FALSE
a çevirmemiz gerekir. (Bu bilgiyi sapply()
fonksiyonunun yardım dosyasından öğrendim)
sapply(semtler, nchar, USE.NAMES = FALSE)
## [1] 10 8 7 6 4 6
apply
ailesinin bir diğer fonksiyonu ise vapply()
dır. Bu fonksiyonda sapply
dan farklı olarak parantez içerisinde uygulanan fonksiyonun çıktısı için bir koşul belirlenir. Böylece çıktılarda oluşabilecek hataların önüne geçilir. Aşağıdaki örnekte ilk başta “h1” adında bir liste oluşturacağız. Bu liste geçtiğimiz 5 günde her gün için 7 kez ölçülen hava sıcaklıklarını içeriyor.
ol1 <- c(3,6,4,1,5,-3,3)
ol2 <- c(7,8,9,4,7,5,6)
ol3 <- c(9,12,3,7,9,8,4)
ol4 <- c(6,13,-1,2,4,8,4)
ol5 <- c(-1,5,-3,2,2,4,1)
h1 <- list(ol1,ol2,ol3,ol4,ol5)
apply
fonksiyon ailesinin en önemli özellği bize istediğimiz veriyi özetleyerek sunmasıdır. Örneğin yukarıdaki listeden vapply()
fonksiyonunu kullanarak her gün için en yüksek, en düşük ve ortalama sıcaklıkları bir hamlede hesaplayabiliriz. ilk olarak bu üç hesaplamayı yapacak fonksiyonumuzu yazalım:
sicaklik <- function (x){
c(en_dusuk=min(x), ortalama= mean(x), en_yuksek=max(x))
}
Şimdi de bu fonksiyonu vapply()
içine yerleştirelim. Burada kritik olan şey, çıktının 3 nümerik değer taşıyor olmasıdır: en düşük değer, ortalama değer ve en yüksek değer. Bu durum fonksiyon içine aşağıdaki şekilde tanımlanır
vapply(h1, sicaklik, numeric(3))
## [,1] [,2] [,3] [,4] [,5]
## en_dusuk -3.00 4.00 3.00 -1.00 -3.00
## ortalama 2.71 6.57 7.43 5.14 1.43
## en_yuksek 6.00 9.00 12.00 13.00 5.00
Gördüğünüz gibi R listedeki her bir vektör için istediğimiz hesplamaları yapıp raporladı
5.6 Bazı Sık Kullanılan Fonksiyonlar
Şu ana kadar birçok fonksiyon kullanarak çeşitli işlemler gerçekleştirdik. Bu son bölümde bazı sıkça kullanılan fonksiyonlardan bahsedecğiz.
Matematiksel işlemlerin yer aldığı fonksiyonlar sık kullanılan fonksiyonların başında gelir. Aşağıdaki örneğe bir göz atalım:
v1 <- c(2.3, -5.3, 3.8, -9.7)
v2 <- c(-2.7, 5.3, 8.8, -10.0)
mean(c(sum(round(abs(v1))), sum(round(abs(v2)))))
Bu örnekte birden fazla matematiksel işlem v1 ve v2 adında iki vektör üzerinde uygulanıyor. işlemleri en iç parantezden başlayarak anlamaya çalışalım: R ilk başta v1 ve v2 vektörlerinde bulunan değerlerin abs()
fonksiyonu ile mutlak değerlerini alacak, sonra round()
fonksiyonu ile tam sayıya yuvarlayacak, sonra sum()
fonksiyonu ile bu vektörleri toplayacak ve en son olarak mean()
fonksiyonu ile iki vektörün ortalamasını bulacak. Koddaki “c” (birleştir) yazımına dikkat ediniz. Sonuç aşağıda
## [1] 24
Matematiksel fonksiyonlar gibi data şekillendirmek için kullanılan bir grup sıkça kullanılan fonksiyondan bahsedilebilir. Aşağıda list()
ile oluşturulmuş ve içinde farklı tipte değişkenler içeren liste datasını inceleyelim
liste1 <- list(man = TRUE,
kar = "Gençlerbirliği",
ara_vek = sort(rep(seq(12, 0, by = -3), times = 3)))
Yukarıdaki liste üç farklı değişkenden oluşuyor. ilki “man” adı altında ve “TRUE” değerini alan mantıksal bir değişken, ikincisi “kar” adı altında karakterlerden oluşan (yani metin formunda) bir değişken, üçüncüsü ise bir formül yoluyla ve “ara_vek” adı ile tanımlanmış bir değişken. Şimdi bu üçüncü değişkeni inceleyelim. Burada kullanıla seq()
fonksiyonu (sequence/ardışık) belli aralıklara sahip bir sayı dizisi yaratacak. Formülün içeriğinden bu ardışık dizinin “12” ile başlayıp “0” a kadar gideceğini ve üçer üçer azalacağını anlıyoruz. Daha sonra oluşan bu vektör rep()
(repeat/tekrarla) fonksiyonu ile “3” kez tekrarlanacak ve en sonunda sort()
(sort/sırala) fonksiyonu ile küçükten büyüğe sıralanacak. Aşağıda bu işlemleri gözlemleyelim:
# 1. aşama
seq(12, 0, by = -3)
## [1] 12 9 6 3 0
# 2. aşama
rep(seq(12, 0, by = -3), times = 3)
## [1] 12 9 6 3 0 12 9 6 3 0 12 9 6 3 0
# 3. aşama
sort(rep(seq(12, 0, by = -3), times = 3))
## [1] 0 0 0 3 3 3 6 6 6 9 9 9 12 12 12
Şimdi tüm listemizin durumuna bakalım
liste1 <- list(man = TRUE,
kar = "Gençlerbirliği",
ara_vek = sort(rep(seq(12, 0, by = -3), times = 3)))
liste1
## $man
## [1] TRUE
##
## $kar
## [1] "Gençlerbirligi"
##
## $ara_vek
## [1] 0 0 0 3 3 3 6 6 6 9 9 9 12 12 12
Son olarak append()
(append/ekle) fonksiyonuna bakalım. Kimi zaman birden fazla data yapısını (matris, vektör veya liste) birbirine ekleyerek kullanmak isteriz. Aşağıdaki örnek Gençlerbirliği’nin gollerini “liste2”" adı altında ilk başta kaydediyor daha sonra append()
fonksiyonu ile ilk oluşturduğumuz “liste1” listesine ekleyip “birlesik_liste”" adı ile kaydediyor:
liste2 <- list (goller = c(genclerbirligi))
birlesik_liste <- append(liste2, liste1)
birlesik_liste
## $goller
## [1] 4 3 0 2 0 5 1
##
## $man
## [1] TRUE
##
## $kar
## [1] "Gençlerbirligi"
##
## $ara_vek
## [1] 0 0 0 3 3 3 6 6 6 9 9 9 12 12 12
Kurallı ifadeler (Regular Expressions/regex) özellikle karakter/metin değişkenleri üzerinde işlem yapmaya yarayan bir grup fonksiyona verilen isimdir. Bu fonksiyon ailesi metinler içinde gizli örüntüleri bulmaya ve istenirse bu örüntüleri değiştirmeye yarar ve özellikle web datası kullanımında işleri hayli kolaylaştırır. Birçok regex fonskiyonu olsa da bu kısımda grepl()
, sub()
ve gsub()
fonksiyonlarından bahsedeceğiz. Regex fonksiyonlarının genel yazımı aşağıdaki gibidir.
grepl(pattern = <regex>, x = <string>)
Burada “pattern” aradığımız örüntüyü, “x” ise bu örüntüyü nerede aradığımızı ifade eder. Örneğimiz için e-posta adreslerinden oluşan bir vektör tanımlayalım ve grepl()
ile “org” uzantılı siteleri bulmaya çalışalım:
eposta <- c("kizilkara@genclerbirligi.org", "robin.warner@london.com", "kiss.organizasyon@abc.com", "crosscheck@darts.org", "oy@gecersiz.org" )
#grepl() kullanımı
grepl("org", eposta)
## [1] TRUE FALSE TRUE TRUE TRUE
Görüldüğü üzere R “org” ifadesinin bulunduğu vektör elemanlarını “TRUE” olarak raporladı. Bir nokta dikkatinizi çekmiş olmalı: aslında biz “org” uzantılı eposta adreslerini çekmek isterken, üçüncü eposta adresinin ismi de, uzantısı .org olmamasına rağmen içinde bulunan “org” parçası yüzünden “TRUE” olarak işaretlendi. Bu sorunu aşmak için grepl()
yardım dosyasına baktığımızda “^” karakterini kullanarak aradığımız örüntüyü karakterlerin başında ve “$” karakterini kullanarak ise karakterlerin sonunda arayabileceğimizi görürüz. Örneğin:
grepl("^k", eposta)
## [1] TRUE FALSE TRUE FALSE FALSE
kodunda “k” ile başlayan 2 e posta adresi olduğunu anlarız. Bunların hangi eposta adresleri olduğunu anlamak için önce grepl()
işlemini bir vektör altında tanımlayıp sonra bu vektörü orjinal vektörden çıkararak (subset) bakmamız gerekir:
k_harfi <- grepl("^k", eposta)
eposta[k_harfi]
## [1] "kizilkara@genclerbirligi.org" "kiss.organizasyon@abc.com"
Fakat grepl()
içinde bizim işimizi kolaylaştıran başka bir argüman bulunuyor: isteğimizi \\.org$
şeklinde yazarsak R “.” yı artık bir karakter olarak algılayacak ve “$” işareti yüzünden metinlerin sonuna bakacaktır:
k_harfi <- grepl("\\.org$", eposta)
eposta[k_harfi]
## [1] "kizilkara@genclerbirligi.org" "crosscheck@darts.org"
## [3] "oy@gecersiz.org"
grepl()
ile aradığımız örüntünün var olup olmadığını kontrol ederken sub()
ve gsub()
fonksiyonları ile bu örüntülerin yerlerine başka ifadeler yerleştirebiliriz. Bu fonksiyonların yazımı aşağıdaki gibidir:
sub(pattern = <regex>, replacement = <str>, x = <str>)
Bu koddaki “replacement” aradığımız kalıbın yerine ne yazmak istediğimizi tanımladığımız alandır. Örnek olarak eposta adreslerindeki .com uzantıların hepsini “.info” yapmaya çalışalım.
sub(pattern = "\\.com", replacement = ".info", x = eposta)
## [1] "kizilkara@genclerbirligi.org" "robin.warner@london.info"
## [3] "kiss.organizasyon@abc.info" "crosscheck@darts.org"
## [5] "oy@gecersiz.org"