# Örnek bir matris oluşturalım.
notlar <- matrix(
c(70, 80, 90,
60, 75, 85,
50, 65, 95),
nrow = 3,
byrow = TRUE
)
notlar [,1] [,2] [,3]
[1,] 70 80 90
[2,] 60 75 85
[3,] 50 65 95
R’de veri analizi yaparken aynı işlemi birden fazla eleman, satır, sütun, grup veya liste bileşeni üzerinde tekrarlamak çok sık karşılaşılan bir ihtiyaçtır. Örneğin bir veri setindeki bütün sayısal değişkenlerin ortalamasını almak, bir listenin her elemanına aynı fonksiyonu uygulamak, bir değişkeni gruplara göre özetlemek veya iki farklı vektörün karşılıklı elemanları üzerinde işlem yapmak isteyebiliriz.
Bu tür işlemler döngülerle yapılabilir. Ancak R, bu tekrar eden işlemleri daha kısa, daha okunabilir ve çoğu zaman daha güvenli biçimde gerçekleştirmek için apply ailesi olarak bilinen bir fonksiyon grubu sunar.
Apply ailesi tek bir fonksiyondan oluşmaz. R’de farklı veri yapıları ve farklı çıktı beklentileri için farklı apply fonksiyonları vardır. Bu bölümde özellikle şu fonksiyonlar ele alınacaktır:
apply()lapply()sapply()vapply()tapply()mapply()Bu fonksiyonların hepsi aynı temel fikre dayanır:
Bir veri yapısının parçaları üzerinde aynı fonksiyonu tekrar tekrar uygula.
Ancak her biri farklı veri yapıları ve farklı kullanım amaçları için tasarlanmıştır. Bu nedenle apply ailesini anlamak yalnızca fonksiyon isimlerini ezberlemek değildir; hangi durumda hangi fonksiyonun daha uygun olduğunu kavramaktır.
Apply ailesi, döngülerin yerine geçmek zorunda değildir. Asıl amaç, tekrar eden işlemleri daha açık, daha düzenli ve veri yapısına uygun biçimde yazabilmektir.
Programlama öğrenirken tekrar eden işlemler için genellikle önce for döngüleri öğrenilir. Bu doğrudur; çünkü döngüler programlamanın temel yapı taşlarından biridir. Ancak R, veri analizi odaklı bir dil olduğu için birçok tekrar eden işlem vektörler, matrisler, listeler ve veri çerçeveleri üzerinde yapılır. Apply ailesi bu veri yapılarına uygun bir tekrar mantığı sağlar.
Örneğin elimizde bir matris olsun ve her sütunun ortalamasını hesaplamak isteyelim.
# Örnek bir matris oluşturalım.
notlar <- matrix(
c(70, 80, 90,
60, 75, 85,
50, 65, 95),
nrow = 3,
byrow = TRUE
)
notlar [,1] [,2] [,3]
[1,] 70 80 90
[2,] 60 75 85
[3,] 50 65 95
Bu matrisin sütun ortalamalarını döngüyle hesaplayabiliriz.
# Sonuçları saklamak için boş bir vektör oluşturuyoruz.
sutun_ortalamalari <- numeric(ncol(notlar))
# Her sütun için ortalama hesaplıyoruz.
for (i in 1:ncol(notlar)) {
sutun_ortalamalari[i] <- mean(notlar[, i])
}
sutun_ortalamalari[1] 60.00000 73.33333 90.00000
Aynı işlemi apply() ile daha kısa ve doğrudan yazabiliriz.
# 2 değeri sütunlar üzerinde işlem yapılacağını belirtir.
apply(notlar, 2, mean)[1] 60.00000 73.33333 90.00000
Buradaki fark yalnızca daha az kod yazmak değildir. apply() ifadesi doğrudan şunu söyler:
Bu matrisin sütunlarına
mean()fonksiyonunu uygula.
Yani kodun niyeti daha açık hale gelir.
Apply ailesi genellikle “daha hızlı” olduğu için değil, kodun niyetini daha açık ifade ettiği için tercih edilir.
Apply ailesindeki fonksiyonların çoğu üç temel soruya cevap verir:
Bu mantık özellikle başlangıçta karmaşık görünebilir. Ancak birkaç örnekten sonra oldukça doğal hale gelir.
Aşağıdaki tablo temel apply fonksiyonlarının kullanım alanlarını özetlemektedir.
| Fonksiyon | Temel kullanım alanı | Tipik çıktı |
|---|---|---|
apply() |
Matris veya array üzerinde satır/sütun işlemleri | vektör, matris veya liste |
lapply() |
Liste veya veri çerçevesinin elemanları üzerinde işlem | liste |
sapply() |
lapply() gibi çalışır, sonucu basitleştirmeye çalışır |
vektör, matris veya liste |
vapply() |
sapply() benzeri; çıktı tipi önceden belirtilir |
güvenli ve belirli tipte çıktı |
tapply() |
Bir vektörü gruplara göre özetlemek | vektör, array veya liste |
mapply() |
Birden fazla nesne üzerinde eş zamanlı işlem | vektör, matris veya liste |
Bu tabloyu ezberlemek yerine bölüm boyunca örnekler üzerinden anlamak daha faydalıdır.
apply() Fonksiyonuapply() fonksiyonu genellikle matrisler veya çok boyutlu diziler üzerinde satır ya da sütun bazında işlem yapmak için kullanılır.
Temel söz dizimi şöyledir:
apply(X, MARGIN, FUN, ...)Buradaki argümanlar şunlardır:
X: Üzerinde işlem yapılacak matris veya array.MARGIN: İşlemin hangi boyutta yapılacağını belirtir.FUN: Uygulanacak fonksiyon....: Fonksiyona aktarılacak ek argümanlar.MARGIN argümanı apply() fonksiyonunun en kritik kısmıdır.
Matrislerde:
MARGIN = 1 satırlar üzerinde işlem yapar.MARGIN = 2 sütunlar üzerinde işlem yapar.# Örnek bir matris oluşturalım.
m <- matrix(1:12, nrow = 3, byrow = TRUE)
m [,1] [,2] [,3] [,4]
[1,] 1 2 3 4
[2,] 5 6 7 8
[3,] 9 10 11 12
Satır toplamlarını hesaplayalım.
# MARGIN = 1 satırları ifade eder.
apply(m, 1, sum)[1] 10 26 42
Her satır ayrı ayrı alınmış ve sum() fonksiyonu uygulanmıştır.
Satır ortalamalarını da benzer şekilde hesaplayabiliriz.
# Her satırın ortalaması
apply(m, 1, mean)[1] 2.5 6.5 10.5
Sütun toplamlarını hesaplamak için MARGIN = 2 kullanılır.
# MARGIN = 2 sütunları ifade eder.
apply(m, 2, sum)[1] 15 18 21 24
Sütun ortalamaları:
# Her sütunun ortalaması
apply(m, 2, mean)[1] 5 6 7 8
apply() fonksiyonunda MARGIN = 1 satır, MARGIN = 2 sütun anlamına gelir. Bu bilgi özellikle matris işlemlerinde temel önemdedir.
Bazı fonksiyonlar ek argümanlar alır. Örneğin mean() fonksiyonunda na.rm = TRUE argümanı eksik değerleri dikkate almadan ortalama hesaplamak için kullanılır.
# Eksik değer içeren bir matris oluşturalım.
m_na <- matrix(
c(1, 2, NA,
4, NA, 6,
7, 8, 9),
nrow = 3,
byrow = TRUE
)
m_na [,1] [,2] [,3]
[1,] 1 2 NA
[2,] 4 NA 6
[3,] 7 8 9
Eksik değerler dikkate alınmadan satır ortalamaları hesaplanabilir.
# mean() fonksiyonuna na.rm = TRUE argümanı aktarılır.
apply(m_na, 1, mean, na.rm = TRUE)[1] 1.5 5.0 8.0
Burada na.rm = TRUE doğrudan apply() fonksiyonuna değil, apply() tarafından çağrılan mean() fonksiyonuna aktarılır.
apply() içinde hazır bir fonksiyon kullanılabileceği gibi, kullanıcı tarafından o anda tanımlanan kısa fonksiyonlar da kullanılabilir. Bunlara anonim fonksiyon denir. Anonim fonksiyonlar bir isme atanmaz; doğrudan ihtiyaç duyulan yerde kullanılır.
# Her satır için maksimum ve minimum değer arasındaki farkı hesaplayalım.
apply(m, 1, function(x) max(x) - min(x))[1] 3 3 3
Burada function(x) ifadesi her satırı geçici olarak x adıyla alır ve satır içindeki en büyük değer ile en küçük değer arasındaki farkı hesaplar.
Aynı işlemi sütunlar için yapalım.
# Her sütundaki aralık değeri
apply(m, 2, function(x) max(x) - min(x))[1] 8 8 8 8
Anonim fonksiyonlar özellikle tek satırlık kısa işlemler için oldukça kullanışlıdır.
Anonim fonksiyonlar, kısa ve yalnızca bir kez kullanılacak işlemler için idealdir. Aynı işlem birçok yerde kullanılacaksa ayrı bir fonksiyon tanımlamak daha uygun olur.
apply() ve Veri Çerçeveleriapply() fonksiyonu veri çerçeveleri üzerinde de çalışabilir; ancak dikkatli kullanılmalıdır. Çünkü veri çerçeveleri farklı veri tiplerine sahip sütunlardan oluşabilir. apply() veri çerçevesini çoğu zaman matrise dönüştürür. Bu dönüşüm beklenmeyen sonuçlara yol açabilir.
df <- data.frame(
isim = c("Ali", "Ayşe", "Mehmet"),
not1 = c(70, 80, 90),
not2 = c(60, 85, 95)
)
dfBu veri çerçevesi içinde metinsel bir sütun olduğu için apply() kullanımı dikkat gerektirir.
# Sadece sayısal sütunları seçerek apply() kullanmak daha güvenlidir.
apply(df[, c("not1", "not2")], 1, mean)[1] 65.0 82.5 92.5
Veri çerçeveleri üzerinde apply() kullanırken dikkatli olunmalıdır. Veri çerçevesi matrise dönüştürüldüğünde farklı veri tipleri aynı tipe zorlanabilir.
lapply() Fonksiyonulapply() fonksiyonu listeler üzerinde işlem yapmak için kullanılır. Adındaki l, list kelimesinden gelir. Bu fonksiyon, bir listenin her elemanına aynı fonksiyonu uygular ve sonucu her zaman liste olarak döndürür.
Temel söz dizimi şöyledir:
lapply(X, FUN, ...)Burada:
X: Liste veya liste gibi elemanlardan oluşan nesne.FUN: Her elemana uygulanacak fonksiyon....: Fonksiyona aktarılacak ek argümanlar.Önce basit bir liste oluşturalım.
liste <- list(
a = 1:5,
b = 10:15,
c = c(100, 200, 300)
)
liste$a
[1] 1 2 3 4 5
$b
[1] 10 11 12 13 14 15
$c
[1] 100 200 300
Her elemanın ortalamasını hesaplayalım.
# lapply() her liste elemanına mean() uygular.
lapply(liste, mean)$a
[1] 3
$b
[1] 12.5
$c
[1] 200
Sonuç liste olarak döner.
# Çıktının sınıfını inceleyelim.
class(lapply(liste, mean))[1] "list"
Bu, lapply() fonksiyonunun en belirgin özelliğidir.
lapply()sonucu basitleştirmeye çalışmaz; daima liste döndürür.
lapply()R’de veri çerçeveleri aslında sütunlardan oluşan özel listeler olarak düşünülebilir. Bu nedenle lapply() veri çerçevesi sütunları üzerinde işlem yapmak için sık kullanılır.
# iris veri setinin ilk birkaç satırına bakalım.
head(iris)iris veri setindeki her sütunun sınıfını öğrenelim.
# Her sütuna class() fonksiyonunu uygular.
lapply(iris, class)$Sepal.Length
[1] "numeric"
$Sepal.Width
[1] "numeric"
$Petal.Length
[1] "numeric"
$Petal.Width
[1] "numeric"
$Species
[1] "factor"
Sayısal sütunların ortalamasını almak için önce sayısal sütunları seçelim.
# Sayısal sütunları seçiyoruz.
iris_sayisal <- iris[, 1:4]
# Her sayısal sütunun ortalaması
lapply(iris_sayisal, mean)$Sepal.Length
[1] 5.843333
$Sepal.Width
[1] 3.057333
$Petal.Length
[1] 3.758
$Petal.Width
[1] 1.199333
lapply() ve Anonim FonksiyonlarBir veri çerçevesindeki sayısal sütunların minimum ve maksimum değerlerini birlikte hesaplayalım.
# Her sütun için minimum ve maksimum değerleri döndürür.
lapply(iris_sayisal, function(x) c(min = min(x), max = max(x)))$Sepal.Length
min max
4.3 7.9
$Sepal.Width
min max
2.0 4.4
$Petal.Length
min max
1.0 6.9
$Petal.Width
min max
0.1 2.5
Sonuç yine listedir. Her liste elemanı, ilgili sütunun minimum ve maksimum değerlerini içerir.
Eksik değer içeren bir liste oluşturalım.
liste_na <- list(
a = c(1, 2, NA, 4),
b = c(10, NA, 30),
c = c(5, 6, 7)
)
liste_na$a
[1] 1 2 NA 4
$b
[1] 10 NA 30
$c
[1] 5 6 7
Eksik değerleri dışarıda bırakarak ortalama hesaplayalım.
# na.rm = TRUE argümanı mean() fonksiyonuna aktarılır.
lapply(liste_na, mean, na.rm = TRUE)$a
[1] 2.333333
$b
[1] 20
$c
[1] 6
sapply() Fonksiyonusapply() fonksiyonu lapply() fonksiyonuna benzer. Temel fark, sapply() fonksiyonunun çıktıyı mümkünse daha basit bir yapıya dönüştürmeye çalışmasıdır. Buradaki s, simplify kelimesinden gelir.
# lapply() liste döndürür.
lapply(liste, mean)$a
[1] 3
$b
[1] 12.5
$c
[1] 200
# sapply() sonucu basitleştirmeye çalışır.
sapply(liste, mean) a b c
3.0 12.5 200.0
İlk çıktı listedir. İkinci çıktı ise isimlendirilmiş bir vektördür.
Bu davranış pratikte kullanışlıdır; ancak bazen beklenmeyen çıktı tiplerine neden olabilir.
sapply() Ne Zaman Kullanışlıdır?Eğer her elemandan tek bir değer dönmesini bekliyorsak sapply() oldukça pratiktir.
# Her elemanın uzunluğunu hesaplayalım.
sapply(liste, length)a b c
5 6 3
Veri çerçevesindeki sütun sınıflarını daha okunabilir biçimde görmek için de kullanılabilir.
sapply(iris, class)Sepal.Length Sepal.Width Petal.Length Petal.Width Species
"numeric" "numeric" "numeric" "numeric" "factor"
simplify = FALSEsapply() fonksiyonu varsayılan olarak sonucu basitleştirir. Bu davranışı kapatmak için simplify = FALSE kullanılabilir.
# simplify = FALSE kullanıldığında sonuç liste olarak kalır.
sapply(liste, mean, simplify = FALSE)$a
[1] 3
$b
[1] 12.5
$c
[1] 200
Bu kullanım pratikte lapply() ile benzer sonuç verir.
sapply() çıktı yapısını otomatik olarak basitleştirdiği için bazı durumlarda beklenmeyen sonuçlar üretebilir. Çıktı tipinin kesin olması gerekiyorsa vapply() daha güvenlidir.
vapply() Fonksiyonuvapply() fonksiyonu, sapply() fonksiyonunun daha güvenli bir versiyonu olarak düşünülebilir. Temel fark, vapply() fonksiyonunda beklenen çıktı tipi ve uzunluğu önceden belirtilir.
Temel söz dizimi şöyledir:
vapply(X, FUN, FUN.VALUE, ...)Burada:
X: Üzerinde işlem yapılacak nesne.FUN: Uygulanacak fonksiyon.FUN.VALUE: Her işlemden beklenen çıktı tipi ve uzunluğu....: Ek argümanlar.Örneğin her liste elemanından tek bir sayısal değer bekliyorsak:
# Her elemanın ortalamasını bekliyoruz.
vapply(liste, mean, numeric(1)) a b c
3.0 12.5 200.0
Buradaki numeric(1) ifadesi şunu söyler:
Her elemandan uzunluğu 1 olan sayısal bir çıktı bekliyorum.
Eğer fonksiyon beklenen yapıda çıktı üretmezse vapply() hata verir. Bu davranış özellikle daha güvenli ve tahmin edilebilir kod yazmak için faydalıdır.
# Bu örnekte her elemandan iki değer döndüğü için numeric(1) beklentisi bozulur.
vapply(liste, function(x) c(min(x), max(x)), numeric(1))Error in vapply(liste, function(x) c(min(x), max(x)), numeric(1)): values must be length 1,
but FUN(X[[1]]) result is length 2
Doğru kullanım:
# Her elemandan iki sayısal değer beklediğimizi belirtiyoruz.
vapply(liste, function(x) c(min = min(x), max = max(x)), numeric(2)) a b c
min 1 10 100
max 5 15 300
Paket veya fonksiyon geliştirirken vapply() daha güvenli bir tercih olabilir. Çünkü çıktı yapısını açık biçimde belirtmenizi sağlar.
tapply() Fonksiyonutapply() fonksiyonu bir vektörü bir veya daha fazla gruba göre özetlemek için kullanılır. Adındaki t, tarihsel olarak table veya tapply yapısına gönderme yapar. Pratikte tapply() fonksiyonunu gruplandırılmış özet işlemleri için düşünebiliriz.
Temel söz dizimi şöyledir:
tapply(X, INDEX, FUN, ...)Burada:
X: Özetlenecek vektör.INDEX: Grupları belirleyen factor veya factor listesi.FUN: Her gruba uygulanacak fonksiyon....: Ek argümanlar.Basit bir örnek oluşturalım.
# Öğrencilerin bölümleri ve notları
bolum <- c("İstatistik", "İstatistik", "Matematik", "Matematik", "İstatistik")
not <- c(80, 70, 60, 90, 85)
# Bölüme göre ortalama not
tapply(not, bolum, mean)İstatistik Matematik
78.33333 75.00000
Burada not vektörü bolum değişkenine göre gruplanmış ve her grup için ortalama hesaplanmıştır.
tapply()Birden fazla gruplama değişkeni de kullanılabilir.
cinsiyet <- c("Kadın", "Erkek", "Kadın", "Erkek", "Kadın")
# Bölüm ve cinsiyete göre ortalama not
tapply(not, list(bolum, cinsiyet), mean) Erkek Kadın
İstatistik 70 82.5
Matematik 90 60.0
Sonuç iki boyutlu bir tablo gibi görünür.
not_na <- c(80, 70, NA, 90, 85)
# Eksik değerleri dışarıda bırakarak ortalama
tapply(not_na, bolum, mean, na.rm = TRUE)İstatistik Matematik
78.33333 90.00000
tapply() özellikle base R ile gruplara göre özet istatistik üretmek için kullanışlıdır. dplyr paketindeki group_by() ve summarise() mantığına geçmeden önce bu yapı iyi anlaşılmalıdır.
mapply() Fonksiyonumapply() fonksiyonu, bir fonksiyonu birden fazla nesnenin karşılıklı elemanları üzerinde uygulamak için kullanılır. Adındaki m, multivariate veya multiple fikrine işaret eder.
Basit bir örnekle başlayalım.
# İki vektör oluşturalım.
x <- c(1, 2, 3)
y <- c(10, 20, 30)
# Karşılıklı elemanları toplayalım.
mapply(sum, x, y)[1] 11 22 33
Bu işlem şu hesaplamaları yapar:
sum(1, 10)sum(2, 20)sum(3, 30)mapply()Bir vektördeki değerleri farklı üslerle yükseltelim.
taban <- c(2, 3, 4)
us <- c(2, 3, 2)
# Her tabanı karşılık gelen üsse yükseltir.
mapply(function(a, b) a^b, taban, us)[1] 4 27 16
mapply()ad <- c("Ali", "Ayşe", "Mehmet")
not <- c(80, 90, 75)
# Her öğrenci için etiket oluşturalım.
mapply(function(a, n) paste(a, "notu:", n), ad, not) Ali Ayşe Mehmet
"Ali notu: 80" "Ayşe notu: 90" "Mehmet notu: 75"
Bu tür kullanım, raporlama ve dinamik metin üretimi için faydalıdır.
Bir fonksiyonun birden fazla girdisi varsa ve bu girdilerin karşılıklı elemanları üzerinde işlem yapmak istiyorsanız mapply() iyi bir seçenektir.
Apply ailesi bazen “döngü kullanmadan işlem yapmak” şeklinde anlatılır. Bu ifade kısmen doğrudur; ancak eksiktir. Çünkü apply fonksiyonları da arka planda tekrar eden işlemler gerçekleştirir. Fark, bu tekrar mantığının daha yüksek seviyeli ve veri yapısına uygun biçimde ifade edilmesidir.
Aşağıdaki iki kod aynı amaca hizmet eder.
# Döngü ile sütun ortalamaları
sonuc_for <- numeric(ncol(iris_sayisal))
for (i in 1:ncol(iris_sayisal)) {
sonuc_for[i] <- mean(iris_sayisal[[i]])
}
sonuc_for[1] 5.843333 3.057333 3.758000 1.199333
# sapply ile sütun ortalamaları
sonuc_apply <- sapply(iris_sayisal, mean)
sonuc_applySepal.Length Sepal.Width Petal.Length Petal.Width
5.843333 3.057333 3.758000 1.199333
İkinci kullanımda kod daha kısa ve niyet daha açıktır. Ancak bazı durumlarda for döngüsü daha okunabilir olabilir. Özellikle karmaşık işlemler, ara kontroller veya birden fazla adım içeren süreçlerde döngü kullanmak daha anlaşılır olabilir.
Apply ailesi döngülerin düşmanı değildir. Döngüler ve apply fonksiyonları farklı durumlarda farklı avantajlar sağlar.
Aşağıdaki tablo karar vermeyi kolaylaştırabilir.
| İhtiyaç | Uygun fonksiyon |
|---|---|
| Matrisin satır veya sütunlarına işlem uygulamak | apply() |
| Listenin her elemanına işlem uygulamak | lapply() |
| Liste sonucunu vektör/matris gibi daha basit yapıya çevirmek | sapply() |
| Çıktı tipini güvence altına almak | vapply() |
| Bir vektörü gruplara göre özetlemek | tapply() |
| Birden fazla vektörün karşılıklı elemanlarıyla işlem yapmak | mapply() |
Bu tablo kesin kurallar değil, pratik yönlendirmeler sunar. Gerçek kullanımda veri yapısı, beklenen çıktı ve kodun okunabilirliği birlikte değerlendirilmelidir.
apply() Fonksiyonunu Her Veri Çerçevesinde Güvenle KullanmakVeri çerçeveleri farklı veri tiplerine sahip olabilir. apply() veri çerçevesini matrise dönüştürebileceği için sayısal olmayan sütunlar sonucu etkileyebilir.
df_hata <- data.frame(
grup = c("A", "B", "C"),
x = c(10, 20, 30),
y = c(5, 15, 25)
)
# Bu kullanım veri tipleri nedeniyle beklenmeyen sonuçlar verebilir.
apply(df_hata, 2, class) grup x y
"character" "character" "character"
Daha güvenli kullanım:
# Sayısal sütunları seçerek işlem yapmak daha uygundur.
apply(df_hata[, c("x", "y")], 2, mean) x y
20 15
sapply() Çıktısını Her Zaman Aynı Sanmaksapply() sonucu otomatik basitleştirmeye çalışır. Her elemandan farklı uzunlukta çıktı dönerse sonuç liste olabilir.
karisik <- list(
a = 1:3,
b = 1:5
)
sapply(karisik, function(x) x[1:2]) a b
[1,] 1 1
[2,] 2 2
Ancak farklı uzunlukta çıktı üretildiğinde yapı değişebilir.
sapply(karisik, function(x) x)$a
[1] 1 2 3
$b
[1] 1 2 3 4 5
Çıktı tipinin kesin olması gerekiyorsa vapply() düşünülmelidir.
MARGIN Değerini Karıştırmakapply() fonksiyonunda MARGIN = 1 satır, MARGIN = 2 sütun anlamına gelir. Bu karışıklık sık görülür.
m [,1] [,2] [,3] [,4]
[1,] 1 2 3 4
[2,] 5 6 7 8
[3,] 9 10 11 12
# Satır toplamları
apply(m, 1, sum)[1] 10 26 42
# Sütun toplamları
apply(m, 2, sum)[1] 15 18 21 24
# na.rm = TRUE mean() fonksiyonuna aktarılır.
apply(m_na, 1, mean, na.rm = TRUE)[1] 1.5 5.0 8.0
Burada na.rm = TRUE, apply() fonksiyonunun değil, mean() fonksiyonunun argümanıdır.
Aşağıdaki egzersizler apply ailesinin temel kullanımını pekiştirmek için hazırlanmıştır.
apply() ile hesaplayınız.apply() ile hesaplayınız.lapply() ile hesaplayınız.sapply() ile yapınız ve çıktı farkını inceleyiniz.iris veri setindeki sayısal sütunların ortalamasını sapply() ile hesaplayınız.vapply() ile yapınız.tapply() ile özetleyiniz.mapply() ile dinamik etiketler üretiniz.apply() fonksiyonunda MARGIN = 1 ve MARGIN = 2 farkını kendi örneğinizle açıklayınız.# 1. Matris oluşturma
mat <- matrix(1:20, nrow = 4, byrow = TRUE)
mat [,1] [,2] [,3] [,4] [,5]
[1,] 1 2 3 4 5
[2,] 6 7 8 9 10
[3,] 11 12 13 14 15
[4,] 16 17 18 19 20
# 2. Satır toplamları
apply(mat, 1, sum)[1] 15 40 65 90
# 3. Sütun ortalamaları
apply(mat, 2, mean)[1] 8.5 9.5 10.5 11.5 12.5
# 4. Liste oluşturma ve lapply kullanımı
ornek_liste <- list(
a = 1:5,
b = letters[1:3],
c = c(TRUE, FALSE, TRUE, TRUE)
)
lapply(ornek_liste, length)$a
[1] 5
$b
[1] 3
$c
[1] 4
# 5. Aynı işlemi sapply ile yapma
sapply(ornek_liste, length)a b c
5 3 4
# 6. iris veri setindeki sayısal sütunların ortalaması
iris_sayisal <- iris[, 1:4]
sapply(iris_sayisal, mean)Sepal.Length Sepal.Width Petal.Length Petal.Width
5.843333 3.057333 3.758000 1.199333
# 7. Aynı işlem vapply ile
vapply(iris_sayisal, mean, numeric(1))Sepal.Length Sepal.Width Petal.Length Petal.Width
5.843333 3.057333 3.758000 1.199333
# 8. Bölüme göre not ortalaması
bolum <- c("A", "A", "B", "B", "A")
not <- c(70, 80, 60, 90, 85)
tapply(not, bolum, mean) A B
78.33333 75.00000
# 9. mapply ile etiket üretimi
ad <- c("Ali", "Ayşe", "Mehmet")
puan <- c(75, 90, 60)
mapply(function(a, p) paste(a, "-", p, "puan"), ad, puan) Ali Ayşe Mehmet
"Ali - 75 puan" "Ayşe - 90 puan" "Mehmet - 60 puan"
# 10. MARGIN farkı
mat [,1] [,2] [,3] [,4] [,5]
[1,] 1 2 3 4 5
[2,] 6 7 8 9 10
[3,] 11 12 13 14 15
[4,] 16 17 18 19 20
# Satır bazında maksimum değerler
apply(mat, 1, max)[1] 5 10 15 20
# Sütun bazında maksimum değerler
apply(mat, 2, max)[1] 16 17 18 19 20
Apply ailesi, R’de tekrar eden işlemleri veri yapısına uygun biçimde ifade etmeyi sağlayan önemli bir fonksiyon grubudur. Bu bölümde apply(), lapply(), sapply(), vapply(), tapply() ve mapply() fonksiyonları ele alındı.
apply() daha çok matris ve array yapılarında satır veya sütun bazlı işlemler için kullanılır. lapply() liste elemanları üzerinde işlem yapar ve her zaman liste döndürür. sapply() benzer şekilde çalışır; ancak çıktıyı basitleştirmeye çalışır. vapply() beklenen çıktı tipini önceden belirterek daha güvenli bir yapı sunar. tapply() gruplara göre özetleme yapmak için kullanılır. mapply() ise birden fazla nesnenin karşılıklı elemanları üzerinde işlem yapmayı sağlar.
Apply ailesini öğrenirken önemli olan hangi fonksiyonun hangi veri yapısı ve hangi çıktı beklentisi için uygun olduğunu anlamaktır. Bu fonksiyonlar döngülerin yerine geçmek zorunda değildir; ancak birçok veri analizi probleminde kodu daha kısa, daha düzenli ve daha okunabilir hale getirir.