Bu ödevin amacı programlama kodları ile ilgili öğrendiklerimi özetlemektir.
Bir fonksiyonun temel bileşenlerini anlamak, hem R’ın kütüphanelerindeki mevcut fonksiyonları etkin bir şekilde kullanmak hem de kendi çözümlerimizi geliştirmek için önemlidir.
Standart normal dağılımdan rastgele sayılar üreten rnorm fonksiyonunu bir örnek olarak kullanarak bir R fonksiyonunun temel yapısını inceleyelim:
rnorm(n, mean = 0, sd = 1)
rnorm fonksiyonu için formal argümanlar n, mean ve
sd’dir. Bu argümanlar kullanıcının hangi parametreleri
ayarlayabileceğini belirtir.
Default değerler fonksiyon tanımında bir argümana atanan başlangıç
değerleridir. mean = 0 ve sd = 1 gibi
varsayılan değerler buna örnektir. Kullanıcı bu değerleri
belirtmediğinde fonksiyon bu varsayılan değerlerle çalışır. Örneğin,
rnorm(n = 5) , mean ve sd argümanları belirtilmediği için
otomatik olarak mean = 0 ve sd = 1 değerlerini kullanır.
Bir fonksiyonun argümanlarını, varsayılan değerlerini ve kullanım
amacını tam olarak anlamanın en güvenilir yolu, R’ın yardım
dokümantasyonuna başvurmaktır. Konsola ?rnorm yazarak
erişilebilen bu dokümanlar, bir fonksiyonun nasıl çalıştığını anlamak
için önemli ve incelenmesi gereken bir kaynaktır.
Argüman isimleri belirtilmediğinde, R, fonksiyonun değerlerini fonksiyon tanımındaki argüman sırasına göre atar. İlk değer ilk argümana, ikinci değer ikinci argümana atanır ve bu şekilde devam eder. Bunun yanında kullanıcı argümanların isimlerini ve değerlerini yazarak kendisi bir sıralama da belirleyebilir.
Tekrarlanan görevleri otomatikleştirmek, karmaşık iş akışlarını basitleştirmek ve analizleri standartlaştırmak için özel fonksiyonlar yazmak, R programlamanın temel yetkinliklerinden biridir. Kendimizi sürekli olarak aynı kod bloklarını kopyalayıp yapıştırırken buluyorsak bu genellikle bir fonksiyon yazmanız gerektiğine işaret eder. Aşağıda fonksiyon yazma adımları yer almaktadır:
Bir fonksiyon, function() komutu kullanılarak oluşturulur ve bir R nesnesi olarak değişkene atanır.
Fonksiyon gövdesine ({ } arasına) R komutları eklenerek fonksiyona işlevsellik kazandırılır.
Fonksiyonun esnekliğini artırmak için argümanlara varsayılan değerler atanabilir. Bu, kullanıcının bu argüman için bir değer girmemesi durumunda fonksiyonun standart bir davranış sergilemesini sağlar.
R’da fonksiyonlar, birinci sınıf nesneler (first-class objects)
olarak kabul edilir. Bu onların diğer R nesneleri (vektörler, listeler
vb.) gibi ele alınabileceği anlamına gelir. Bu özelliğin en önemli
pratik sonuçları, fonksiyonların başka fonksiyonlara argüman olarak
aktarılabilmesi (lapply() gibi döngü fonksiyonlarında) ve
bir fonksiyonun içinde başka bir fonksiyonun tanımlanabilmesidir (iç içe
fonksiyonlar).
R’daki ... (üç nokta) argümanı, özellikle mevcut
fonksiyonların yeteneklerini genişletmek veya kullanıcıdan ne kadar
girdi geleceği bilinmeyen durumları yönetmek için kullanılır. Kendi
yazdığımız fonksiyon, argüman olarak aldığı ... içindeki
tüm ek girdileri doğrudan başka bir fonksiyona aktarır. Bazı
fonksiyonlar ise kaç adet argüman alacaklarını önceden bilemezler.
Örneğin paste() veya cat() fonksiyonları,
birleştirilecek veya yazdırılacak eleman sayısını sınırlamaz;
... argümanı, bu tür fonksiyonların istenilen sayıda
girdiyi kabul etmesini sağlar. ... argümanını kullanmanın
potansiyel hata kaynağı, ...’dan sonra gelen argümanların
kullanım şeklidir. Bu argümanlar, konumlarına göre veya kısmi isimlerle
eşleştirilemezler dolayısıyla açıkça ve tam olarak isimlendirilmeleri
gerekir.
Örneğin paste() fonksiyonunda sep argümanı
...’dan sonra gelir:
DOĞRU: ‘sep’ argümanı tam olarak isimlendirilmiş
paste("a", "b", sep = ":")
## [1] "a:b"
YANLIŞ: Kısmi eşleştirme (‘se’) çalışmaz, ‘se = “:”’ ifadesi ‘…’ içinde bir karakter olarak yorumlanır
paste("a", "b", se = ":")
## [1] "a b :"
Fonksiyonun ne yapacağını, hangi girdileri (argümanları) alacağını ve ne tür bir çıktı üreteceğini netleştirin.
Fonksiyonun mantığını, sabit değerler veya örnek bir veri seti kullanarak doğrudan R konsolunda adım adım çalıştırın ve test edin.
Çalışan komut satırlarınızı
fonksiyon_adi <- function() { ... } yapısının içine
kopyalayın.
Kodunuzdaki sabit değerleri, fonksiyonun argümanları olarak tanımlayın ve bu argümanları kodun ilgili yerlerine yerleştirin.
Aşağıda, bu ilkeleri uygulayan iki uygulama bulunmaktadır.
Uygulama 1: hesapla_geometrik_ortalama_v2
Bu fonksiyon, bir vektörün geometrik ortalamasını hesaplar ve sonuçları karşılaştırır.
hesapla_geometrik_ortalama_v2 <- function(x) {
# Hata Kontrolü: Geometrik ortalama için girdilerin pozitif olması gerekir.
if (any(x <= 0)) {
stop("Geometrik ortalama hesaplanacak tüm değerler pozitif olmalıdır.")
}
n <- length(x)
# 1. Doğrudan Çarpım Yöntemi
g_mean_carpim <- prod(x)^(1/n)
# 2. Logaritmik Yöntem (Sayısal olarak daha kararlı)
g_mean_log <- exp(mean(log(x)))
# 3. Harici Paketlerle Sonuçların Karşılaştırılması
g_mean_psych <- psych::geometric.mean(x)
# Sonuçları düzenli bir veri çerçevesi olarak oluşturma
sonuclar <- data.frame(
Yontem = c("Doğrudan Çarpım", "Logaritmik", "psych::geometric.mean()"),
Geometrik_Ortalama = c(g_mean_carpim, g_mean_log, g_mean_psych),
row.names = NULL # Temiz bir çıktı için varsayılan satır isimlerini engeller
)
print(sonuclar)
# Sonucu atama imkanı sunarken konsola tekrar yazdırmamak için 'invisible' kullanılır.
return(invisible(sonuclar))
}
x_test <- 200:250
hesapla_geometrik_ortalama_v2(x_test)
## Yontem Geometrik_Ortalama
## 1 Doğrudan Çarpım 224.5172
## 2 Logaritmik 224.5172
## 3 psych::geometric.mean() 224.5172
Uygulama 2: Çoklu veri seti oluşturma ve dışa aktarma
Bu örnek, iç içe for döngüleri, sonuçları geçici olarak saklamak için
list kullanımı (df_list) ve dinamik dosya
adları oluşturmak için paste() fonksiyonunun nasıl bir
arada kullanılabileceğini göstermektedir. Bu tür bir fonksiyon, manuel
olarak yapılması saatler sürebilecek tekrarlı bir görevi tek bir komutla
gerçekleştirir.
fonksiyon_adi <- function(sayi=3, satir=c(5,5,5), sutun=c(10,10,10)){
# Veri setlerini geçici olarak saklamak için boş bir liste oluşturulur
df_list <- list()
# Dış döngü, oluşturulacak her bir veri seti için çalışır
for(i in 1:sayi){
# Belirtilen boyutlarda sıfırlardan oluşan bir veri çerçevesi oluşturulur
df_list[[i]] <- data.frame(matrix(0, nrow=satir[i], ncol=sutun[i]))
# İç döngü, veri çerçevesinin sütunlarını doldurur
for(j in 1:sutun[i]){
# Her sütun standart normal dağılıma uygun rastgele sayılarla doldurulur
df_list[[i]][,j] <- round(rnorm(satir[i], 0, 1), 2)
}
# DİKKAT: Dosya yazma işlemi, ilgili veri çerçevesi tamamen oluşturulduktan sonra, yani dış döngünün sonunda yapılmalıdır.
# Bu, gereksiz ve yavaş disk işlemlerini önler.
writexl::write_xlsx(df_list[[i]], paste("veri", i, ".xlsx", sep=""))
}
}
Bu örnekleri asla bakmadan yazamam ama belki bir gün bakmadan yazarsam ve bu cümlemi görürsem aşırı mutlu olurum.
Koşullu ifadeler analizlerin belirli kriterlere veya veri özelliklerine göre adapte olmasını sağlayan bir mekanizmadır.
if-else
if, else ve else if
kombinasyonu, R’da bir koşulu test etmek ve testin sonucuna göre belirli
bir kod bloğunu çalıştırmak için kullanılır.
if: Yalnızca koşul doğru olduğunda bir işlem gerçekleştirir.
if-else: Koşul doğruysa bir işlemi, yanlışsa başka bir işlemi gerçekleştirir.
if-else if-else: Birden fazla koşulu sıralı olarak test eder.
Bu yapının pratik uygulamasını bir öğrenci not değerlendirme örneği
üzerinden inceleyebiliriz. Geçme notunu bir değişkende saklayalım.
Örneğin 75 alan bir öğrencinin durumu basit bir if
ifadesiyle belirlenebilir:
not <- 75
gecme_notu <- 65
if (not >= gecme_notu) {
print("Basarılı") # print sadece kategorik/karakter değer yazdırır. cat () ise nesne değeri de yazdırır
}
## [1] "Basarılı"
Not 60 olduğunda, yukarıdaki kod bir çıktı üretmez. Bu durumu
yönetmek için else eklenir:
not <- 60
gecme_notu <- 65
if (not >= gecme_notu) {
print("Basarılı")
} else {
print("Basarisiz")
}
## [1] "Basarisiz"
Daha karmaşık ve çok kategorili senaryolarda else if
zinciri kullanılır. Bu yapı, not aralıklarına göre harf notu ataması
gibi durumlar için idealdir ve tüm not aralıklarını kapsayacak şekilde
genişletilebilir:
x <- 75
if (x >= 90) {
print("AA")
} else if (x >= 80) {
print("BA")
} else if (x >= 70) {
print("BB")
} else if (x >= 65) {
print("CB")
} else if (x >= 60) {
print("CC")
} else if (x >= 50) {
print("DD")
} else if (x >= 30) {
print("FD")
} else {
print("FF")
}
## [1] "BB"
all ()- any ()
Standart bir if ifadesi, tek bir mantıksal değer (TRUE
veya FALSE) bekler. Bu durum, birden fazla eleman içeren vektörlerle
çalışırken bir zorluk teşkil eder. R, bu sorunu çözmek için
all() ve any() fonksiyonlarını sunar.
all(): Bir vektördeki tüm elemanların
belirtilen koşulu karşılayıp karşılamadığını test eder. Eğer tüm
elemanlar koşulu sağlıyorsa TRUE, aksi takdirde FALSE döndürür.
x <- c(1, 2, -3, 4)
if (all(x > 0)) {
print("tum sayilar 0'dan buyuktur")
} else {
print("tum sayilar 0'dan buyuk degildir")
}
## [1] "tum sayilar 0'dan buyuk degildir"
any(): Bir vektördeki elemanlardan en
az birinin belirtilen koşulu karşılayıp karşılamadığını test eder. Eğer
en az bir eleman koşulu sağlıyorsa TRUE, aksi takdirde FALSE
döndürür.
x <- c(1, 2, -3, 4)
if (any(x < 0)) {
print("nesne en az bir negatif sayi icerir")
} else {
print("nesne negatif sayi icermez")
}
## [1] "nesne en az bir negatif sayi icerir"
ifelse()
ifelse() fonksiyonu, standart if-else yapısının vektörel
karşılığıdır. Vektör girdilerini işlemek ve sonuç olarak bir vektör
çıktısı üretmek üzere özel olarak tasarlanmıştır.
Genel sözdizimi şöyledir:
ifelse(koşul, Doğru İfade, Yanlış İfade)
for Döngüsü: for döngüsü, R’da bir dizi
(örneğin bir vektör, liste veya matris) üzerindeki elemanlar arasında
yineleme yapmak için kullanılan en yaygın mekanizmadır. Belirlenen
sayıda tekrar gerçekleştirir ve her adımda bir ara değişkene dizinin
sıradaki elemanını atar. for döngüsünün içinde 1:length(x)
de kullanabilirsiniz, seq_along (x) de;
seq_along fonksiyonu nesnenin uzunluğunca yazdırır.
Döngüler özellikle sonuçların her adımda birikimli olarak hesaplanması gereken görevler için kritik öneme sahiptir. Örneğin, bir matrisin her bir satırının toplamını hesaplamak ve sonucu yeni bir vektörde saklamak için, for döngüsü her bir satır üzerinde sıralı olarak gezinmek ve toplama işlemini gerçekleştirmek için kullanılabilir:
X <- cbind(a = 1:5, b = 2:6)
Y <- array()
for (i in 1:nrow(X)) {
Y[i] <- X[i, 1] + X[i, 2]
}
print (Y)
## [1] 3 5 7 9 11
while Döngüsü: while döngüsü başlamadan
önce bir koşulu test eder ve bu koşul doğru TRUE olduğu sürece kod
bloğunu çalıştırmaya devam eder. Koşul FALSE olduğunda döngü sona erer.
Aşağıdaki örnek, bir sayacı 10’dan küçük olduğu sürece artıran basit bir
while döngüsünü göstermektedir:
count <- 0
while (count < 10) {
print(count)
count <- count + 1
}
## [1] 0
## [1] 1
## [1] 2
## [1] 3
## [1] 4
## [1] 5
## [1] 6
## [1] 7
## [1] 8
## [1] 9
while döngüleri düzgün yazılmazsa sonsuz döngülere neden olabilir. Koşulun bir noktada FALSE olmasını sağlayacak bir nokta içermesi oldukça önemlidir.
break ve next Komutları:
break ve next, döngülerin yürütülmesi üzerinde daha hassas kontrol
sağlamak için kullanılan temel komutlardır.
next: Bu komut, mevcut iterasyonun geri kalanını atlar ve döngünün bir sonraki iterasyonuna geçer. Örneğin, 1’den 6’ya kadar olan sayıları yazdırırken 3’ü atlamak için kullanılabilir.
break: Bu komut, belirli bir koşul karşılandığında döngüyü tamamen sonlandırır. Örneğin, 12 kez tekrarlanması planlanan bir döngü, i değeri 3’e ulaştığında durdurulabilir.
İç İçe Döngüler: İç içe döngüler bir döngünün başka bir döngü içine yerleştirilmesiyle oluşturulur. Bu yapı matrisler gibi çok boyutlu veya hiyerarşik veri yapılarının işlenmesi için temel bir tekniktir. Aşağıdaki örnek, 2x3 boyutunda bir matrisin her bir elemanını sırayla yazdırır:
x <- matrix(1:6, 2, 3)
for (i in seq_len(nrow(x))) {
for (j in seq_len(ncol(x))) {
print(x[i, j])
}
}
## [1] 1
## [1] 3
## [1] 5
## [1] 2
## [1] 4
## [1] 6
lapply(): Bir liste üzerinde döngü
kurar ve her elemana bir fonksiyon uygular, sonuç olarak bir liste
döndürür.
sapply(): lapply() ile
aynı işlevi görür ancak çıktıyı mümkün olduğunca basitleştirir (vektör
veya matris gibi).
apply(): Bir matris veya dizinin
satır ya da sütunları üzerinde bir fonksiyon çalıştırır.
tapply(): Bir vektörü faktörlere
göre gruplara ayırır ve her grup üzerinde bir fonksiyon
uygular.
mapply(): lapply()
fonksiyonunun çok değişkenli versiyonudur, birden fazla veri yapısı
üzerinde paralel olarak çalışır.
split(): Veri yapılarını bir
faktöre göre alt kümelere ayırmak için kullanılan bir yardımcı
fonksiyondur. (Psikolojide de bu anlamda kullanılıyor, örneğin kişiliğin
alter kişiliklere bölünmesi gibi - dissosiasyon)
Bu kısa bilgilerden sonra her fonksiyona daha detaylı bakalım:
lapply(): lapply fonksiyonunun çalışma
prensibi oldukça basittir: Bir liste (x) alır, listedeki her bir elemana
belirtilen fonksiyonu uygular ve sonuçları içeren yeni bir liste
döndürür. Aşağıdaki örnekte iki farklı eleman içeren bir listenin her
elemanının ortalamasını alıyoruz:
x <- list(a = 1:5, b = rnorm(10))
lapply(x, mean)
## $a
## [1] 3
##
## $b
## [1] 0.1412257
x$a
## [1] 1 2 3 4 5
x$b
## [1] -1.8032663 1.1180193 -1.3378644 0.8158406 1.1571149 0.2515800
## [7] 0.7245854 0.5537014 -0.3076721 0.2402188
Bu örnekte dikkat edilmesi gereken önemli bir nokta, mean
fonksiyonunun lapply’e parantez olmadan yani bir nesne gibi argüman
olarak geçirilmesidir. Bu durum, R’daki fonksiyonların birinci sınıf
nesneler olmasının bir sonucudur. lapply, x listesindeki
her bir elemanı (önce 1:5 vektörünü, sonra rnorm(10) vektörünü) alır ve
bu elemanı mean fonksiyonuna birinci argüman olarak geçirir.
lapply, uygulanan fonksiyona ek parametreler aktarmak
için ... argümanını kullanır. Aşağıdaki örnekte
runif fonksiyonuna min ve max
argümanları lapply üzerinden iletilmektedir:
x <- 1:4
lapply(x, runif, min = 0, max = 10)
## [[1]]
## [1] 5.925041
##
## [[2]]
## [1] 5.652907 6.451986
##
## [[3]]
## [1] 2.3142448 0.7904008 5.4908682
##
## [[4]]
## [1] 4.802843 4.174071 1.034231 4.269380
İsimsiz/anonim fonksiyonlar lapply gibi fonksiyonlarla
birlikte kullanıldığında büyük bir esneklik sağlar. Bu fonksiyonlar bir
isimle tanımlanmadan doğrudan lapply çağrısı içinde anında oluşturulur
ve sadece o anki işlem için kullanılır. Aşağıdaki örnekte, iki matris
içeren bir listenin her bir matrisinden sadece ilk sütunu çıkaran anonim
bir fonksiyon kullanılmıştır:
x <- list(a = matrix(1:4, 2, 2), b = matrix(1:6, 3, 2))
lapply(x, function(elt) { elt[,1] })
## $a
## [1] 1 2
##
## $b
## [1] 1 2 3
sapply(): sapply fonksiyonu,
lapply’nin bir uzantısı olarak düşünülebilir. Temel amacı
lapply ile aynı işlemi yapmak ancak sonuçları mümkün
olduğunca daha kullanışlı bir veri yapısına (genellikle bir vektör veya
matris) basitleştirmektir. sapply veri setindeki her sütunda istediğimiz
şeyi uygular. NA olduğunda ne yapacağını bilemez.
sapply’nin basitleştirme algoritması şu kurallara
dayanır:
Eğer sonuç, her elemanı 1 uzunluğunda olan bir liste ise vektör döndürür.
Eğer sonuç, her elemanı aynı uzunlukta (>1) vektörler olan bir liste ise matris döndürür.
Bu kurallar uygulanamıyorsa, lapply gibi bir liste döndürür.
Aşağıdaki kod lapply ve sapply arasındaki
farkı net bir şekilde göstermektedir. Her iki fonksiyon da aynı veri
üzerinde çalıştırılarak geçerli bir karşılaştırma yapılır:
x <- list(a = 1:4, b = rnorm(10), c = rnorm(20, 1), d = rnorm(100, 5))
# lapply çıktısı
lapply(x, mean)
## $a
## [1] 2.5
##
## $b
## [1] 0.01396625
##
## $c
## [1] 0.9715022
##
## $d
## [1] 5.013248
x$a
## [1] 1 2 3 4
x$b
## [1] -0.49226030 -0.06392351 0.78021473 1.15500022 -0.05036885 0.30407561
## [7] -0.18118498 -1.80760641 -0.60520118 1.10091717
x$c
## [1] -0.05971664 0.85176400 1.30702987 0.22578095 0.55102634 2.04928272
## [7] 1.39246844 -0.17649720 1.57598152 1.96481590 -0.13283627 0.66535616
## [13] 0.99505836 0.29508474 2.17886080 0.37179991 0.53655292 2.58845796
## [19] 1.19632093 1.05345275
x$d
## [1] 5.537001 5.305254 6.053580 4.251660 3.683680 5.415274 6.991016 4.485191
## [9] 5.423172 5.917712 5.115880 6.702921 4.517690 5.822840 5.507308 3.759658
## [17] 5.423304 4.676342 5.826799 5.685579 5.463887 4.188835 4.789117 5.194599
## [25] 6.227388 4.837814 4.532059 3.137714 4.576625 5.296899 6.541633 3.831409
## [33] 5.504963 6.658999 5.939947 4.853988 3.499069 5.072516 5.638252 4.928784
## [41] 6.280831 6.332559 4.971662 4.976141 4.332640 3.971132 2.488610 4.232301
## [49] 3.457664 6.307306 2.815280 5.873478 4.415726 6.009798 4.740273 5.178686
## [57] 4.160577 6.377033 5.249920 4.486004 7.358989 4.332710 4.974997 3.966184
## [65] 6.125716 6.537541 5.138973 4.469182 3.494731 6.900159 3.786910 4.703171
## [73] 4.155066 3.144329 6.226345 3.508729 6.038548 4.602794 6.118706 3.020241
## [81] 4.904680 4.783315 5.458609 5.299040 3.538304 5.771802 4.839185 5.287712
## [89] 4.565974 5.805470 4.428336 4.353514 5.528330 4.972386 5.464552 5.931597
## [97] 4.854560 5.697585 3.661877 4.099965
# sapply çıktısı (basitleştirilmiş vektör)
sapply(x, mean)
## a b c d
## 2.50000000 0.01396625 0.97150221 5.01324794
Bunun bu kadar uzun olmaması gerekiyordu ama silemiyorum.
Bu kısmın devamındaki fonksiyonları derste uygulamadık ama anladığım kadarıyla yazacağım.
split(): split fonksiyonunun temel
görevi, bir vektör veya veri çerçevesini bir faktör değişkenine göre
gruplara ayırarak bir liste oluşturmaktır. Her liste elemanı faktörün
bir seviyesine karşılık gelen veri alt kümesini içerir.
set.seed(10)
x <- c(rnorm(10), runif(10), rnorm(10, 5)) # 30 elemanlı vektor
f <- gl(3, 10) # 3 kategorili bagimsiz değişken
split(x, f)
## $`1`
## [1] 0.01874617 -0.18425254 -1.37133055 -0.59916772 0.29454513 0.38979430
## [7] -1.20807618 -0.36367602 -1.62667268 -0.25647839
##
## $`2`
## [1] 0.8647212 0.6153524 0.7751099 0.3555687 0.4058500 0.7066469 0.8382877
## [8] 0.2395891 0.7707715 0.3558977
##
## $`3`
## [1] 5.089347 4.045056 4.804850 5.925521 5.482979 4.403689 2.814713 4.325134
## [9] 2.880939 3.734802
# Her grubun ortalamasını hesapla
lapply(split(x, f), mean)
## $`1`
## [1] -0.4906568
##
## $`2`
## [1] 0.5927795
##
## $`3`
## [1] 4.350703
tapply(): tapply fonksiyonu, split ve
lapply kombinasyonunun daha doğrudan ve kompakt bir alternatifidir.
Temel amacı, bir vektörü (x) bir faktöre göre gruplamak ve her gruba
belirtilen fonksiyonu uygulamaktır.
Yukarıdaki split + lapply örneğinin
tapply ile tek satırda nasıl yazılabileceğini görelim:
x <- c(rnorm(10), runif(10), rnorm(10, 1))
f <- gl(3, 10)
tapply(x, f, mean)
## 1 2 3
## -0.4447055 0.4161593 0.9242280
tapply özellikle veri çerçeveleri üzerinde çalışırken
oldukça kullanışlıdır. Aşağıdaki örnekte bir veri çerçevesindeki (df)
boy verileri, cinsiyet faktörüne göre gruplanarak hem ortalaması hem de
sıralanmış boy listesi hesaplanmıştır:
# Örnek veri çerçevesi
isim <- c("Ali","Elif","Su","Deniz","Aras","Berk","Can","Ece","Efe","Arda")
boy <- c(160,165,170,155,167,162,169,158,160,164)
cinsiyet <- factor(c("erkek","kadin","kadin","kadin","erkek", "erkek","erkek","kadin","erkek","erkek"))
df <- data.frame(isim=isim, boy=boy, cinsiyet=cinsiyet)
# Cinsiyete göre boy ortalaması
tapply(df$boy, df$cinsiyet, mean)
## erkek kadin
## 163.6667 162.0000
# Cinsiyete göre sıralanmış boy listesi
tapply(df$boy, df$cinsiyet, sort)
## $erkek
## [1] 160 160 162 164 167 169
##
## $kadin
## [1] 155 158 165 170
MARGIN: apply fonksiyonu üç temel argüman alır: x (bir
matris veya dizi), MARGIN (işlemin uygulanacağı boyut) ve
uygulanacak fonksiyon.
MARGIN = 1: İşlemin satırlar üzerinde yapılacağını
belirtir. Fonksiyon, matrisin her bir satırına ayrı ayrı
uygulanır.
MARGIN = 2: İşlemin sütunlar üzerinde yapılacağını
belirtir. Fonksiyon, matrisin her bir sütununa ayrı ayrı
uygulanır.
Aşağıda 20 satır ve 10 sütundan oluşan rastgele bir matris oluşturalım:
x <- matrix(rnorm(200), 20, 10)
Bu matrisin her bir sütununun ortalamasını hesaplamak için
MARGIN = 2 kullanılır:
apply(x, 2, mean)
## [1] 0.150394922 -0.002591708 0.043601703 -0.006161931 0.045354753
## [6] -0.375514332 0.234989071 -0.318744293 0.038555223 -0.086109213
Benzer şekilde, her satırın toplamını hesaplamak için
MARGIN = 1 kullanılır:
apply(x, 1, sum)
## [1] -1.83942979 0.13164053 -2.13465796 -0.80746484 -2.10147527 -2.27627352
## [7] -3.45299000 -0.66254558 -2.54248474 0.43311997 0.00681385 -0.37519585
## [13] -1.30682914 2.10514899 1.42161755 4.58688317 4.73222962 -2.06794500
## [19] 2.26313786 -1.63781592
apply’ın gücü, sadece mean veya
sum gibi basit fonksiyonlarla sınırlı değildir.
summary gibi daha karmaşık ve birden çok değer döndüren
fonksiyonlarla da kullanılabilir. Aşağıdaki örnek Matris1 adlı matrisin
her bir sütunu için özet istatistikleri hesaplar:
set.seed(12)
S1 <- sample(rnorm(10000, 50, 5), 100, replace=TRUE)
Matris1 <- matrix(S1, nrow=20, ncol=5)
apply(Matris1, 2, summary)
## [,1] [,2] [,3] [,4] [,5]
## Min. 39.00080 40.23309 39.04749 39.32974 37.74364
## 1st Qu. 45.21933 48.44165 45.57123 47.36401 43.71252
## Median 49.31295 52.24410 49.49029 51.08794 47.62144
## Mean 48.20485 52.13701 49.38658 50.61689 48.60479
## 3rd Qu. 52.40540 55.97719 52.70180 54.36235 53.32016
## Max. 55.24910 63.33272 58.88203 59.93019 60.51715
apply ile sıkça yapılan satır/sütun toplamları ve
ortalamaları gibi temel işlemler için R, daha hızlı çalışan ve daha
okunabilir olan optimize edilmiş fonksiyonlar sunar.
rowSums(x) eşdeğeri
apply(x, 1, sum)
rowMeans(x) eşdeğeri
apply(x, 1, mean)
colSums(x) eşdeğeri
apply(x, 2, sum)
colMeans(x) eşdeğeri
apply(x, 2, mean)
mapply(): mapply fonksiyonunun temel
amacı, bir fonksiyonu birden fazla argüman listesi veya vektörü üzerinde
paralel olarak uygulamaktır. lapply’den farklı olarak, mapply’de
uygulanacak fonksiyon ilk argüman olarak belirtilir ve ardından üzerinde
işlem yapılacak veri yapıları gelir.
Örneğin, rep(1, 4), rep(2, 3), rep(3, 2) ve rep(4, 1) gibi bir dizi çağrıyı tek tek yazmak yerine, mapply ile bu işlemi kolaylıkla tek satırda 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
n = 5
for _ in range(n):
print("* " * n)
## * * * * *
## * * * * *
## * * * * *
## * * * * *
## * * * * *
n <- 5
for (i in 1:n) {
cat(rep("* ", n), "\n")
}
## * * * * *
## * * * * *
## * * * * *
## * * * * *
## * * * * *
n <- 5
for (i in 1:n) {
for (j in 1:n) {
if (i == 1 || i == n || j == 1 || j == n) {
cat("*")
} else {
cat(" ")
}
}
cat("\n")
}
## *****
## * *
## * *
## * *
## *****
n = 5
for i in range(n):
for j in range(n):
if i == 0 or i == n-1 or j == 0 or j == n-1:
print("*", end="")
else:
print(" ", end="")
print()
## *****
## * *
## * *
## * *
## *****
n <- 5
for (i in 1:n) {
cat(rep("* ", i), "\n")
}
## *
## * *
## * * *
## * * * *
## * * * * *
n = 5
for i in range(1, n+1):
print("* " * i)
## *
## * *
## * * *
## * * * *
## * * * * *
n <- 5
for (i in 1:n) {
spaces <- paste(rep(" ", n - i), collapse = "")
stars <- paste(rep("*", 2*i - 1), collapse = "")
cat(spaces, stars, "\n", sep = "")
}
## *
## ***
## *****
## *******
## *********
n = 5
for i in range(1, n+1):
spaces = " " * (n - i)
stars = "*" * (2*i - 1)
print(spaces + stars)
## *
## ***
## *****
## *******
## *********
n <- 5
for (i in 0:(n-1)) {
cat(paste(rep(" ", i), collapse = ""), "*\n", sep = "")
}
## *
## *
## *
## *
## *
n = 5
for i in range(n):
print(" " * i + "*")
## *
## *
## *
## *
## *
n <- 5
for (k in 1:2) {
for (i in 0:(n-1)) {
cat(paste(rep(" ", i), collapse = ""), "*\n", sep = "")
}
}
## *
## *
## *
## *
## *
## *
## *
## *
## *
## *
n = 5
for _ in range(2):
for i in range(n):
print(" " * i + "*")
## *
## *
## *
## *
## *
## *
## *
## *
## *
## *
📍 console– ls() çalışma nesnelerini görmek için,
rm () fonksiyonu ile nesne silebilirsin
📍rm (list=ls()) tüm nesneleri siler
📍rm ("nesne1","nesne2") istediklerini seçip silmek için
kullanılır
📍 getwd () setwd () *Files-more’dan da
ayarlanabilir
📍setwd(dirname(rstudioapi::getActiveDocumentContext()$path))
çalıştığın dosya neyse çalışma dizinini o yapıyor
📍 save.image () fonksiyonu oluşan tüm nesneleri
kaydeder, yanlışlıkla kaydetmeden kapatmayı önler
📍 session – restart R
📍 packet::function – paket çakışmaları için
📍 list () istatistiksel fonksiyonşarın tutulduğu biçim;
çok büyük dosyaları filtleyerek save () fonksiyonuyla
kaydedebilirsin. load () fonksiyonuyla yüklenebilir
📍 save.Rds () ile kaydet, load.Rds () ile
yükle
📍 chunk ayarlarında echo=TRUE, prompt= FALSE, collapse = TRUE yapınca konsoldaki görünüm gibi yazdırıyor
📍 while, for’dan farklı olarak bir koşula
bağlı olarak çalışır (bkz. madde tepki kuramları). for kaç
defa çalışacağını bildiğimiz durumlar içindir. Eğer fonksiyonun default
değerinde bir sınır varsa örneğin 1000 iterasyon sayısına sabit bir
sınır koyulduysa yakınsama olmadan durur ve uyarı verir. Böyle bir
durumda iterasyon sayısını 1000’den örneğin 2000’e çıkarıp çalıştırmaya
devam etmek gerekir.
Aşağıdaki kodda derste hata yapmıştım. Unutmamak için buraya ekliyorum:
set.seed(987)
sayilar <- sample(-10:10,27,replace=TRUE)
sayilar
## [1] 4 3 4 2 1 7 -10 5 6 -8 7 -3 9 7 -9 10 4 -1 -8
## [20] 8 -3 0 4 5 8 1 3
ifelse(sayilar> 0, "pozitif" ,
ifelse (sayilar < 0, "negatif", "sifir"))
## [1] "pozitif" "pozitif" "pozitif" "pozitif" "pozitif" "pozitif" "negatif"
## [8] "pozitif" "pozitif" "negatif" "pozitif" "negatif" "pozitif" "pozitif"
## [15] "negatif" "pozitif" "pozitif" "negatif" "negatif" "pozitif" "negatif"
## [22] "sifir" "pozitif" "pozitif" "pozitif" "pozitif" "pozitif"
Bu örnekler de kalsın:
X <- cbind(1:5, 21:25)
X
## [,1] [,2]
## [1,] 1 21
## [2,] 2 22
## [3,] 3 23
## [4,] 4 24
## [5,] 5 25
for (i in 1:nrow(X)){
cat(i,"1 satirdaki degerlerin carpimi", X[i,1]* X[i,2], "olarak hesaplanmistir.\n")
}
## 1 1 satirdaki degerlerin carpimi 21 olarak hesaplanmistir.
## 2 1 satirdaki degerlerin carpimi 44 olarak hesaplanmistir.
## 3 1 satirdaki degerlerin carpimi 69 olarak hesaplanmistir.
## 4 1 satirdaki degerlerin carpimi 96 olarak hesaplanmistir.
## 5 1 satirdaki degerlerin carpimi 125 olarak hesaplanmistir.
if (interactive()) { # örerken bu kısımda hata verdi, kodu interaktif kullandığım için örmemiş gpt2ye göre. if (interactive ()) ile denememi önerdi ve oldu
n <- as.numeric(readline(prompt="kare matrisin boyutu kac olsun"))
}
matris <- matrix (0,n,n) # yukarıdaki fonksiyonu çalıştırınca konsola sayı yazmadan durmaz
for (i in 1:n) {
for (j in 1:n) {
matris [i,j] <- i*j
}
}
if (nrow(matris) <= 10){
matris
} else {
matris [17:10, 1:10]
}
## [,1] [,2] [,3] [,4] [,5]
## [1,] 1 2 3 4 5
## [2,] 2 4 6 8 10
## [3,] 3 6 9 12 15
## [4,] 4 8 12 16 20
## [5,] 5 10 15 20 25
#readline konsola yazılan sayıyı nesnenin içine alıyor. prompt ise konsola yazı yazdırmak için kullanılıyor. Konsola yazdığımız sayıyı karakter olarak okumasın diye kodun başına as.numeric yazdık.
Konsola sayı yazmadan durmayacağını biliyordum ve bir süre durmasını bekledim 🤦🏻♀️ sonrasında 7 yazdığım anlaşılıyordur.
Fibonacci dizisini for ve while ile inceleyelim:
fib <- c ()
for (i in 3:20) {# ilk iki eleman 1 olduğu için diziye dahil etmedik, 3'ten başladık. n-1, n-2
fib [1] <- 1
fib [2] <- 1
fib [i] <- fib [i-1] + fib [i-2]
}
fib
## [1] 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610
## [16] 987 1597 2584 4181 6765
fib <- c ()
i = 3
while (i <=20) {
fib [1] <- 1
fib [2] <- 1
fib [i] <- fib [i-1] + fib [i-2]
i=i+1
}
fib
## [1] 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610
## [16] 987 1597 2584 4181 6765