tidyverse
ve
dplyr
R ile veri manipülasyonu yapmanın birçok yolu vardır, ancak modern R
yaklaşımında bu işin kalbinde tidyverse
adı verilen bir
felsefe ve paketler topluluğu yatar.
tidyverse
Nedir?
tidyverse
, Hadley Wickham ve ekibi tarafından geliştirilen,
veri biliminin her aşaması için tasarlanmış ve birbiriyle uyum içinde
çalışan R paketlerinden oluşan bir koleksiyondur (The Tidyverse Team,
n.d.). Bu paketlerin ortak bir felsefesi vardır: Kodu daha okunabilir,
daha sezgisel ve daha insancıl hale getirmek.
Bu ekosistemin veri manipülasyonu için kullandığı İsviçre çakısı ise
dplyr
paketidir (Wickham vd., 2023).
dplyr
: Veri için Bir Gramerdplyr
, veri manipülasyonunu birkaç temel “fiil” (verb)
üzerine kurarak karmaşık işlemleri basitleştirir. Her bir fiil, çok
spesifik ve kolay anlaşılır bir görevi yerine getirir. İşte en temel
dplyr
fiilleri:
select()
: Bir tablodan istediğimiz
sütunları seçmemizi sağlar. Tıpkı bir Excel tablosunda
ilgilendiğimiz sütunları bırakıp diğerlerini gizlemek gibi.
filter()
: Belirttiğimiz bir veya
birden fazla koşulu sağlayan satırları seçmemizi, yani
veriyi süzmemizi sağlar. Örneğin, sadece belirli bir şehirde yaşayan
müşterileri veya fiyatı 100 TL’den yüksek olan ürünleri listelemek
gibi.
mutate()
: Mevcut sütunları
kullanarak yeni sütunlar oluşturmamızı veya mevcutları
değiştirmemizi sağlar. Örneğin, “Doğum Yılı” sütununu kullanarak “Yaş”
adında yeni bir sütun hesaplamak gibi.
arrange()
: Tablomuzdaki
satırları bir veya daha fazla sütuna göre küçükten
büyüğe veya büyükten küçüğe doğru sıralamamızı
sağlar.
summarise()
: Veri setimizi tek bir
satıra indirgeyerek özet istatistikler (ortalama, toplam, standart sapma
vb.) hesaplamamızı sağlar. Bu fiil, asıl gücünü bir sonraki fiil ile
birleştiğinde gösterir.
group_by()
: Bu sihirli fiil, tek
başına bir şey yapmaz. Ancak kendisinden sonra gelen
summarise()
gibi fiillerin, tüm veri seti üzerinde değil
de, belirlediğimiz kategorik gruplar üzerinde ayrı ayrı çalışmasını
sağlar. Örneğin, her bir departmandaki çalışanların maaş ortalamasını
ayrı ayrı hesaplamak gibi.
%>%
)Bu fiilleri birer kelime olarak düşünürsek, bu kelimeleri anlamlı
cümlelere dönüştüren bağlaç ise pipe (boru) operatörüdür
(%>%
). Pipe operatörü, bir komutun çıktısını,
bir sonraki komutun ilk girdisi olarak “borular”. Bu sayede, iç içe
geçmiş karmaşık fonksiyonlar yerine, adım adım okunan, anlaşılır bir iş
akışı oluşturabiliriz.
Örneğin:
veriyi al %>% sonra satırları filtrele %>% sonra yeni bir sütun oluştur
Bu teorik temel, birazdan göreceğimiz kod örneklerini anlamamız için bize sağlam bir zemin hazırlayacak. Şimdi bu güçlü fiillerin pratikte nasıl çalıştığını keşfetmeye hazırız!
%>%
vs |>
)Serimiz boyunca, tidyverse
dünyasının vazgeçilmezi olan
%>%
(magrittr pipe) operatörünü kullanacağız. Ancak R’ın
4.1.0 sürümü ile birlikte, R’ın kendi içine yerleşik yeni bir “pipe”
operatörü daha geldi: |>
(base R
pipe).
Peki bu ikisi arasında ne fark var ve biz neden %>%
kullanmayı tercih ediyoruz?
Özellik / Fark | %>% (magrittr / Tidyverse Pipe) |
|> (Base R / Yerel Pipe) |
---|---|---|
Kaynak | magrittr paketinden gelir (ve
tidyverse ile yüklenir). |
R 4.1.0 ve üzeri sürümlerde R’ın kendi içinde yerleşiktir. Ek paket gerektirmez. |
Hız | Bir R fonksiyonu olduğu için çok küçük bir miktar ek yükü vardır. | R’ın çekirdeğinde (C dilinde) yazıldığı için genellikle daha hızlıdır. |
En Önemli Fark: Yer Tutucu
(. ) |
Sol taraftaki verinin, sağdaki fonksiyonda
nereye gideceğini belirtmek için . yer
tutucusunu kullanmamıza izin verir. Bu, inanılmaz esneklik sağlar. |
. yer tutucusunu
desteklemez. Sol taraftaki veri, sağdaki fonksiyonun
her zaman ilk argümanı olmak zorundadır. |
Neden .
Yer Tutucusu Bu Kadar
Önemli?
Bazı fonksiyonlar, veri setini ilk argüman olarak almaz. Örneğin, bir
lineer model kuran lm()
fonksiyonu, ilk argüman olarak
formula
’yı (formül) alır.
%>%
ile .
sayesinde bu sorunu kolayca
çözeriz:
# Beygir gücünü, diğer tüm değişkenlere göre modelle
# Nokta (.) "diğer tüm değişkenler" anlamına gelir.
cars_data %>%
lm(hp ~ ., data = .)
Burada .
yer tutucusu sayesinde,
cars_data
’yı lm()
fonksiyonunun
data
argümanına başarıyla “boruladık”.
Ancak |>
ile bu mümkün değildir:
# Bu kod HATA VERECEKTİR!
cars_data |>
lm(hp ~ ., data = .) # HATA: |> operatörü '.' yer tutucusunu anlamaz.
Serimiz İçin Kararımız
Her ne kadar |>
R’ın geleceği için heyecan verici bir
gelişme olsa da, bu seride aşağıdaki nedenlerden dolayı
tidyverse
’ün standartı olan
%>%
ile devam edeceğiz:
.
yer tutucusu,
dplyr
iş akışlarının ötesine geçen daha karmaşık
analizlerde vazgeçilmez bir esneklik sunar.%>%
kullanır. Bunu öğrenmek, R ekosistemini anlamanızı
kolaylaştırır.magrittr
paketi,
%>%
’in yanı sıra %T>%
(tee operatörü)
gibi başka kullanışlı borular da sunar.Bu nedenle, |>
’nin varlığından haberdar olmak harika
bir şey, ancak şimdilik R’da veri manipülasyonunun fiili standardı olan
%>%
ile ustalaşmak en doğru yaklaşımdır.
dplyr
Fiilleri İle Veri SanatıArtık dplyr
fiillerinin ne işe yaradığını teorik olarak
biliyoruz. Şimdi atölyemizin başına geçip bu fiilleri kullanarak
verilerimizle nasıl “konuşacağımızı” ve onları nasıl istediğimiz şekle
sokacağımızı görelim.
İlk olarak, dplyr
paketini yükleyelim (eğer daha önce
yapmadıysanız install.packages("dplyr")
komutunu konsola
yazarak bir kereliğine yüklemeniz gerekir) ve örnek bir veri seti
oluşturalım. Bu veri seti, küçük bir kütüphanenin kitap stok ve satış
bilgilerini temsil etsin.
# dplyr paketini aktif hale getirelim
library(dplyr)
##
## Attaching package: 'dplyr'
## The following objects are masked from 'package:stats':
##
## filter, lag
## The following objects are masked from 'package:base':
##
## intersect, setdiff, setequal, union
# Örnek veri setimizi oluşturalım: Kütüphane Kitap Bilgileri
kitaplar_df <- data.frame(
KitapID = 101:110,
KitapAdi = c("Evrenin Gizemi", "Kodlama Sanatı", "Veri Analizine Giriş",
"Tarihin Kırılma Noktaları", "Yapay Zeka Temelleri",
"Büyük Veri Mimarileri", "Roman Okuma Rehberi", "Uzay Keşfi",
"Matematiksel Düşünce", "Yeni Nesil Algoritmalar"),
Yazar = c("Yazar A", "Yazar B", "Yazar A", "Yazar C", "Yazar D",
"Yazar E", "Yazar F", "Yazar A", "Yazar G", "Yazar D"),
Kategori = c("Bilim", "Yazılım", "Veri Bilimi", "Tarih", "Yapay Zeka",
"Veri Bilimi", "Edebiyat", "Bilim", "Bilim", "Yapay Zeka"),
Fiyat = c(45.50, 60.00, 72.00, 35.00, 88.00,
95.00, 50.00, 55.00, 48.00, 110.00),
StokAdedi = c(10, 5, 12, 8, 3,
7, 15, 10, 6, 2),
OrtalamaPuan = c(4.2, 4.5, 4.1, 3.8, 4.7,
4.3, 4.0, 4.6, 3.9, 4.8)
)
# Veri setimize ilk göz atış
head(kitaplar_df)
select()
: İlgilendiğimiz Sütunları Seçmekselect()
fonksiyonu, bir veri çerçevesinden sadece
istediğimiz sütunları almamızı sağlar. Tıpkı büyük bir dosyada sadece ad
ve soyad kısmına bakmak gibi.
# --- Örnek 1: Sadece Kitap Adı ve Yazar sütunlarını seçelim ---
kitap_ve_yazar <- kitaplar_df %>% select(KitapAdi, Yazar)
kitap_ve_yazar
# --- Örnek 2: Kitap ID, Fiyat ve Stok Adedi dışındaki tüm sütunları seçelim ---
# "-" işareti ile hariç tutmak istediğimiz sütunları belirtebiliriz.
diger_bilgiler <- kitaplar_df %>% select(-KitapID, -Fiyat, -StokAdedi)
diger_bilgiler
# --- Örnek 3: Bir aralıktaki sütunları seçelim (sütun sırasına göre) ---
# KitapAdi'ndan Kategori'ye kadar olan tüm sütunları alalım.
belli_aralik_sutunlar <- kitaplar_df %>% select(KitapAdi:Kategori)
belli_aralik_sutunlar
filter()
: Verilerimizi Süzmekfilter()
fonksiyonu, belirli koşullara uyan satırları
seçmemizi sağlar. Bu, veri analizinde en sık kullandığımız işlemlerden
biridir.
# --- Örnek 1: Fiyatı 50 TL'den yüksek olan kitapları filtreleyelim ---
pahali_kitaplar <- kitaplar_df %>% filter(Fiyat > 50)
pahali_kitaplar
# --- Örnek 2: "Bilim" kategorisindeki ve Stok Adedi 10'dan fazla olan kitapları bulalım ---
# Birden fazla koşulu virgül (,) veya `&` (VE) operatörü ile birleştirebiliriz.
bilim_ve_stoklu <- kitaplar_df %>% filter(Kategori == "Bilim", StokAdedi > 10)
bilim_ve_stoklu
# --- Örnek 3: Yazar A tarafından yazılmış VEYA ortalama puanı 4.5'ten yüksek olan kitapları seçelim ---
# `|` (VEYA) operatörünü kullanarak farklı koşulları birleştirebiliriz.
yazar_a_veya_yuksek_puan <- kitaplar_df %>% filter(Yazar == "Yazar A" | OrtalamaPuan > 4.5)
yazar_a_veya_yuksek_puan
mutate()
: Yeni Sütunlar Oluşturmak veya Mevcutları
Değiştirmekmutate()
fonksiyonu, mevcut sütunları kullanarak yeni
sütunlar eklememizi veya var olanları değiştirmemizi sağlar. Bu,
verimizden yeni bilgiler türetmek için harikadır.
# --- Örnek 1: Toplam Gelir (Fiyat * StokAdedi) adında yeni bir sütun ekleyelim ---
gelir_eklenmis_df <- kitaplar_df %>% mutate(ToplamGelir = Fiyat * StokAdedi)
gelir_eklenmis_df
# --- Örnek 2: Puan Kategorisi (OrtalamaPuan'a göre "Yüksek", "Orta", "Düşük") ekleyelim ---
puan_kategorili_df <- kitaplar_df %>%
mutate(PuanKategorisi = case_when(
OrtalamaPuan >= 4.5 ~ "Yüksek",
OrtalamaPuan >= 4.0 ~ "Orta",
TRUE ~ "Düşük" # Diğer tüm durumlar
))
puan_kategorili_df
# --- Örnek 3: Fiyatları %10 artıralım ve KDV'li Fiyat adında yeni sütun ekleyelim ---
fiyat_guncel_df <- kitaplar_df %>%
mutate(Fiyat = Fiyat * 1.10, # Mevcut Fiyat sütununu güncelliyoruz
KDVFiyat = Fiyat * 1.18) # Yeni, güncel Fiyat üzerinden KDV'li Fiyat hesaplıyoruz
fiyat_guncel_df
arrange()
: Verilerimizi Sıralamakarrange()
fonksiyonu, veri çerçevemizdeki satırları bir
veya daha fazla sütuna göre sıralamamızı sağlar.
# --- Örnek 1: Kitapları Fiyata göre küçükten büyüğe sıralayalım ---
fiyata_gore_sirali <- kitaplar_df %>% arrange(Fiyat)
fiyata_gore_sirali
# --- Örnek 2: Kitapları Stok Adedine göre büyükten küçüğe sıralayalım ---
# `desc()` fonksiyonu, azalan (descending) sıralama yapar.
stok_azalan_sirali <- kitaplar_df %>% arrange(desc(StokAdedi))
stok_azalan_sirali
# --- Örnek 3: Önce Kategoriye göre (alfabetik), sonra Ortalama Puana göre (büyükten küçüğe) sıralayalım ---
cift_siralama <- kitaplar_df %>% arrange(Kategori, desc(OrtalamaPuan))
cift_siralama
summarise()
ve group_by()
: Gruplar Halinde
Özet ÇıkarmakBu ikili, veri analizinin en güçlü araçlarından biridir.
group_by()
ile veriyi gruplarız, summarise()
ile her grup için özet istatistikler hesaplarız.
# --- Örnek 1: Tüm kitapların ortalama fiyatını ve toplam stok adedini bulalım ---
genel_ozet <- kitaplar_df %>%
summarise(
OrtalamaFiyat = mean(Fiyat),
ToplamStok = sum(StokAdedi),
KitapSayisi = n() # n() fonksiyonu grup içindeki satır sayısını verir
)
genel_ozet
# --- Örnek 2: Her kategori için ortalama fiyatı ve ortalama puanı hesaplayalım ---
kategori_bazli_ozet <- kitaplar_df %>%
group_by(Kategori) %>%
summarise(
OrtalamaFiyat = mean(Fiyat),
OrtalamaPuan = mean(OrtalamaPuan),
KategoriKitapSayisi = n()
)
kategori_bazli_ozet
# --- Örnek 3: Her yazar için yazdığı kitap sayısını ve en düşük/yüksek fiyatını bulalım ---
yazar_bazli_fiyat_ozeti <- kitaplar_df %>%
group_by(Yazar) %>%
summarise(
YazilanKitapAdedi = n(),
EnDusukFiyat = min(Fiyat),
EnYuksekFiyat = max(Fiyat)
)
yazar_bazli_fiyat_ozeti
Tebrikler, dostlar! dplyr
’ın temel fiilleriyle
verilerimizi nasıl seçtiğimizi, süzdüğümüzü, dönüştürdüğümüzü,
sıraladığımızı ve özetlediğimizi gördük. Özellikle
group_by()
ve summarise()
ikilisinin gücü,
karmaşık veri setlerinden anlamlı içgörüler elde etmek için kilit rol
oynar.
Bu bilgiler, makine öğrenmesi modelleri kurmadan önce verilerimizi
hazırlamak ve keşfetmek için vazgeçilmez bir temel oluşturuyor.
tidyverse
felsefesiyle, veri manipülasyonu artık göz
korkutucu değil, aksine keyifli ve akıcı bir süreç haline geliyor.
Bir sonraki bölümde, verilerimizin bize anlattığı hikayeleri görselleştirmeye başlayacağız. Gelin, öğrendiğimiz bu yeni becerilerle verileri konuşturmaya devam edelim!
Bu bölümdeki konuların sırası, dplyr
fiillerinin
sınıflandırılması ve genel anlatım felsefesi oluşturulurken aşağıdaki
değerli eserden ilham alınmıştır. Örnekler ve metinler tamamen özgün
olsa da, bu kaynağın yol göstericiliği için atıfta bulunmak etik bir
gerekliliktir.
Lafaye de Micheaux, P., Drouilhet, R., & Liquet, B. (2013). The R Software: Fundamentals of Programming and Statistical Analysis. Springer. (Chapter 3: Data manipulation, functions)
The Tidyverse Team. (n.d.). Tidyverse. https://www.tidyverse.org/
Wickham, H., Averick, M., Bryan, J., Chang, W., McGowan, L., François, R., Grolemund, G., Hayes, A., Henry, L., Hester, J., Kuhn, M., Pedersen, T., Miller, E., Bache, S., Müller, K., Ooms, J., Robinson, D., Seidel, D., Spinu, V., … Yutani, H. (2023). Welcome to the tidyverse. Journal of Open Source Software, 4(43), 1686. https://joss.theoj.org/papers/10.21105/joss.01686
Wickham, H., & Grolemund, G. (2017). R for data science: Import, tidy, transform, visualize, and model data. O’Reilly Media. https://r4ds.had.co.nz/
Şimdi sıra sizde! Yukarıda öğrendiğimiz dplyr
fiillerini
ve pipe operatörünü (%>%
) kullanarak aşağıdaki görevleri
yerine getirin.
Veri Seti: Kitaplar_df veri setini kullanmaya devam edebilirsiniz.
1. Yeni Sütun Oluşturma ve Seçme: a. Kitapların
Fiyatına ve Stok Adedine göre TahminiCiro
(Fiyat *
StokAdedi) adında yeni bir sütun ekleyin. b. Sadece
KitapAdi
, Kategori
ve TahminiCiro
sütunlarını içeren yeni bir veri çerçevesi oluşturun.
2. Kitapları Filtreleme ve Sıralama: a.
Kategori
’si “Yapay Zeka” olan ve OrtalamaPuan
ı
4.5’ten yüksek olan kitapları listeleyin. b. Bu kitapları
OrtalamaPuan
a göre büyükten küçüğe doğru sıralayın.
3. Gruplama ve Özetleme: a. Her bir
Yazar
için yazdığı kitap sayısını, ortalama fiyatını ve
toplam stok adedini içeren bir özet tablo oluşturun. b. Sadece 2’den
fazla kitap yazmış yazarları ve onların özet bilgilerini gösterin.
4. Zincirleme İşlemler (Pipe Operatörü ile):
kitaplar_df
üzerinde tek bir zincirleme işlemle (tek bir
pipe serisi kullanarak): a. Fiyat
ı 50 TL’den düşük olan
kitapları seçin. b. Bu kitapların KitapAdi
ve
Fiyat
sütunlarını alın. c. Fiyat
ı artan sıraya
göre sıralayın.
# Çalışmaya başlamadan önce dplyr'ı yüklüyoruz ve örnek veri setimizi kullanıyoruz.
library(dplyr)
kitaplar_df <- data.frame(
KitapID = 101:110,
KitapAdi = c("Evrenin Gizemi", "Kodlama Sanatı", "Veri Analizine Giriş",
"Tarihin Kırılma Noktaları", "Yapay Zeka Temelleri",
"Büyük Veri Mimarileri", "Roman Okuma Rehberi",
"Uzay Keşfi", "Matematiksel Düşünce", "Yeni Nesil Algoritmalar"),
Yazar = c("Yazar A", "Yazar B", "Yazar A", "Yazar C", "Yazar D",
"Yazar E", "Yazar F", "Yazar A", "Yazar G", "Yazar D"),
Kategori = c("Bilim", "Yazılım", "Veri Bilimi", "Tarih", "Yapay Zeka",
"Veri Bilimi", "Edebiyat", "Bilim", "Bilim", "Yapay Zeka"),
Fiyat = c(45.50, 60.00, 72.00, 35.00, 88.00,
95.00, 50.00, 55.00, 48.00, 110.00),
StokAdedi = c(10, 5, 12, 8, 3,
7, 15, 10, 6, 2),
OrtalamaPuan = c(4.2, 4.5, 4.1, 3.8, 4.7,
4.3, 4.0, 4.6, 3.9, 4.8)
)
# --- Çözüm 1: Yeni Sütun Oluşturma ve Seçme ---
# a. Tahmini Ciro sütunu ekleme
kitaplar_ciro <- kitaplar_df %>%
mutate(TahminiCiro = Fiyat * StokAdedi)
# b. İstenen sütunları seçme
secilen_kitap_bilgileri <- kitaplar_ciro %>%
select(KitapAdi, Kategori, TahminiCiro)
secilen_kitap_bilgileri
# --- Çözüm 2: Kitapları Filtreleme ve Sıralama ---
# a. Kategori "Yapay Zeka" ve Ortalama Puan > 4.5 olan kitaplar
yapay_zeka_yuksek_puan <- kitaplar_df %>%
filter(Kategori == "Yapay Zeka" & OrtalamaPuan > 4.5)
yapay_zeka_yuksek_puan
# b. Bu kitapları Ortalama Puana göre büyükten küçüğe sıralama
sirali_yapay_zeka_kitaplar <- yapay_zeka_yuksek_puan %>%
arrange(desc(OrtalamaPuan))
sirali_yapay_zeka_kitaplar
# --- Çözüm 3: Gruplama ve Özetleme ---
# a. Her yazar için özet tablo
yazar_ozet <- kitaplar_df %>%
group_by(Yazar) %>%
summarise(
YazilanKitapAdedi = n(),
OrtalamaFiyat = mean(Fiyat),
ToplamStokAdedi = sum(StokAdedi)
)
yazar_ozet
# b. Sadece 2'den fazla kitap yazmış yazarları gösterme
cok_kitap_yazan_yazarlar <- yazar_ozet %>%
filter(YazilanKitapAdedi > 2)
cok_kitap_yazan_yazarlar
# --- Çözüm 4: Zincirleme İşlemler (Pipe Operatörü ile) ---
zincirleme_sonuc <- kitaplar_df %>%
filter(Fiyat < 50) %>% # a. Fiyatı 50 TL'den düşük olanları seç
select(KitapAdi, Fiyat) %>% # b. Kitap Adı ve Fiyat sütunlarını al
arrange(Fiyat) # c. Fiyatı artan sıraya göre sırala
zincirleme_sonuc
mtcars
Veri Setiyle
ÇalışmaŞimdiye kadar kütüphane verileriyle çalıştık. Şimdi ise bambaşka bir
alana geçerek, aynı dplyr
fiillerinin ne kadar evrensel
olduğunu görelim. Bu sefer, R ile birlikte gelen klasik
mtcars
(Motor Trend Araba Yol Testleri) veri setini
kullanarak bir otomobil mühendisi veya bir pazar araştırmacısı gibi
düşüneceğiz.
mtcars
veri setinin küçük bir sorunu var: araba
modelleri satır ismi olarak saklanıyor, bu da “tidy” (düzenli) veri
prensibine aykırı. İlk işimiz bu satır isimlerini “model” adında gerçek
bir sütuna dönüştürmek olacak. tidyverse
ekosisteminin bir
parçası olan tibble
paketi bunun için harika bir fonksiyona
sahip.
# dplyr'i içeren tidyverse paketini çağıralım
library(tidyverse)
# mtcars verisini yükleyip, satır isimlerini "model" adında bir sütuna dönüştürelim
# rownames_to_column() fonksiyonu bu işi yapar.
cars_data <- mtcars %>%
rownames_to_column(var = "model")
# Veri setimizin ilk 6 satırına ve sütunlarına hızlıca göz atalım
head(cars_data)
glimpse(cars_data) # glimpse(), str()'nin daha modern ve okunaklı bir alternatifidir.
## Rows: 32
## Columns: 12
## $ model <chr> "Mazda RX4", "Mazda RX4 Wag", "Datsun 710", "Hornet 4 Drive", "H…
## $ mpg <dbl> 21.0, 21.0, 22.8, 21.4, 18.7, 18.1, 14.3, 24.4, 22.8, 19.2, 17.8…
## $ cyl <dbl> 6, 6, 4, 6, 8, 6, 8, 4, 4, 6, 6, 8, 8, 8, 8, 8, 8, 4, 4, 4, 4, 8…
## $ disp <dbl> 160.0, 160.0, 108.0, 258.0, 360.0, 225.0, 360.0, 146.7, 140.8, 1…
## $ hp <dbl> 110, 110, 93, 110, 175, 105, 245, 62, 95, 123, 123, 180, 180, 18…
## $ drat <dbl> 3.90, 3.90, 3.85, 3.08, 3.15, 2.76, 3.21, 3.69, 3.92, 3.92, 3.92…
## $ wt <dbl> 2.620, 2.875, 2.320, 3.215, 3.440, 3.460, 3.570, 3.190, 3.150, 3…
## $ qsec <dbl> 16.46, 17.02, 18.61, 19.44, 17.02, 20.22, 15.84, 20.00, 22.90, 1…
## $ vs <dbl> 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0…
## $ am <dbl> 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0…
## $ gear <dbl> 4, 4, 4, 3, 3, 3, 3, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 4, 4, 4, 3, 3…
## $ carb <dbl> 4, 4, 1, 1, 2, 1, 4, 2, 2, 4, 4, 3, 3, 3, 4, 4, 4, 1, 2, 1, 1, 2…
Artık analiz için harika bir veri setimiz var. Haydi aynı fiilleri bu yeni atölyede kullanmaya başlayalım!
dplyr
Fiilleriyle Pratik Çalışma
(mtcars
)filter()
(Satırları Süzmek)Görevi: Belirlediğimiz koşul(lar)a uyan arabaları seçer.
# Örnek 1: Sadece 6 silindirli (cyl == 6) arabaları görelim.
filter(cars_data, cyl == 6)
# Örnek 2: 4 silindirli (cyl == 4) VE 100 beygir gücünden (hp > 100) yüksek arabalar.
filter(cars_data, cyl == 4, hp > 100)
arrange()
(Satırları Sıralamak)Görevi: Veri çerçevesini bir veya daha fazla özelliğe göre sıralar.
# Örnek 1: Arabaları en yüksek yakıt verimliliğinden (mpg) en düşüğe doğru sırala.
arrange(cars_data, desc(mpg))
# Örnek 2: Önce silindire (azdan çoğa), sonra beygir gücüne (çoktan aza) göre sırala.
arrange(cars_data, cyl, desc(hp))
select()
(Sütunları Seçmek)Görevi: Sadece ilgilendiğimiz özellikleri seçer.
# Örnek 1: Sadece model, silindir ve beygir gücü sütunlarını seç.
select(cars_data, model, cyl, hp)
# Örnek 2: 'gear' (vites) ve 'carb' (karbüratör) sütunları DIŞINDAKİ her şeyi seç.
select(cars_data, -gear, -carb)
mutate()
(Yeni Özellikler Türetmek)Görevi: Mevcut özelliklerden yeni özellikler hesaplamamızı sağlar.
# Örnek 1: 'wt' sütunu (1000 lbs cinsinden) kullanarak ağırlığı kilogram (kg) cinsinden hesaplayalım.
# 1 lbs = 0.453592 kg
cars_data_yeni <- mutate(cars_data, wt_kg = wt * 1000 * 0.453592)
head(select(cars_data_yeni, model, wt, wt_kg)) # Sadece ilgili sütunlara bakalım
# Örnek 2: Beygir gücünün ağırlığa oranını (kg başına düşen beygir gücü) hesaplayalım.
cars_data_yeni <- mutate(cars_data_yeni, hp_per_kg = hp / wt_kg)
head(select(cars_data_yeni, model, hp, wt_kg, hp_per_kg))
summarise()
ve group_by()
(Özetleme ve
Gruplama)Görevi: Farklı araba grupları için özet istatistikler hesaplar.
# Örnek 1: Her bir silindir (cyl) grubu için ayrı ayrı ortalama mpg hesapla.
cars_data %>%
group_by(cyl) %>%
summarise(ortalama_mpg = mean(mpg))
# Örnek 2: Her bir 'vites' (am: 0=Otomatik, 1=Manuel) tipi için;
# gruptaki araç sayısını (n()) ve ortalama beygir gücünü (mean(hp)) bulalım.
cars_data %>%
group_by(am) %>%
summarise(
arac_sayisi = n(),
ortalama_hp = mean(hp)
)
%>%
) ile UstalıkSoru: “Sadece 6 ve 8 silindirli arabaları seç,
bunları vites tipine (am
) göre grupla, her grup için
ortalama beygir gücünü (ortalama_hp
) ve ortalama yakıt
tüketimini (ortalama_mpg
) hesapla ve sonucu ortalama beygir
gücüne göre azalan şekilde sırala.”
# dplyr ile bu karmaşık soru, okunabilir bir iş akışına dönüşür:
cars_data %>%
filter(cyl %in% c(6, 8)) %>% # Silindiri 6 VEYA 8 olanları seç (%in% operatörü çok kullanışlıdır)
group_by(am) %>% # Vites tipine göre grupla
summarise( # Şimdi özetle:
ortalama_hp = mean(hp),
ortalama_mpg = mean(mpg)
) %>%
arrange(desc(ortalama_hp)) # Son olarak yüksek hp'ye göre sırala
Gördüğünüz gibi dostlar, problem ister kitap satışı olsun ister araba
performansı, dplyr
’ın temel fiilleri aynı mantık ve
sadelikle çalışıyor. Bu, tidyverse
felsefesinin en büyük
gücüdür: Veriyle “konuşmak” için evrensel bir dil sunması.
Bu iki farklı örnekle, veri manipülasyonunun temellerini sağlam bir şekilde atmış olduk.
Dostlar, şimdiye kadar R’ın kendi içinde hazır gelen
mtcars
gibi veri setleriyle çalıştık. R bu verilerin nerede
olduğunu zaten biliyordu. Ancak şimdi, tıpkı bir ustanın dışarıdan
getirdiği ham bir kütüğü atölyesine sokması gibi, biz de bilgisayarımıza
indirdiğimiz bir .csv
dosyasını R’a okutacağız.
Bunu yapabilmemiz için, R’a önce atölyemizin, yani proje klasörümüzün nerede olduğunu söylememiz gerekir. Bu adrese R dünyasında Çalışma Dizini (Working Directory) denir.
Çalışma Dizini, R’ın dosya okuma (read_csv()
) veya yazma
(write_csv()
) gibi komutları verdiğimizde ilk
bakacağı yerdir. Eğer bu adresi doğru ayarlamazsak, R aradığı
dosyayı bulamaz ve o meşhur “cannot open file … No such file or
directory” hatasını alırız. Bu adımı doğru yapmak, bizi birçok
potansiyel hatadan en baştan kurtarır.
getwd()
ile Mevcut Adresi
ÖğrenmeHerhangi bir değişiklik yapmadan önce, R’ın şu anda hangi klasörde
çalıştığını öğrenmek iyi bir alışkanlıktır. getwd()
(Get
Working Directory) fonksiyonu, bize tam olarak bu bilgiyi verir.
# R'a soralım: "Şu an hangi klasördesin?"
getwd()
Bu komutun çıktısı, R’ın o anki çalışma dizinini size bir metin olarak gösterecektir.
Eğer getwd()
komutunun çıktısı, proje dosyalarınızın
olduğu klasör değilse, adresimizi değiştirmemiz gerekir. Bunun iki temel
yolu vardır:
Bu yöntem, özellikle yeni başlayanlar için en hızlı ve en az hataya açık yoldur.
RStudio’nun sağ alt penceresindeki
Files
sekmesine gidin.
Proje Klasörünüze Gidin: Eğer proje klasörünüz
doğrudan görünmüyorsa, dosya yolunun gösterildiği çubuğun en sağındaki
...
(üç nokta) butonuna tıklayın. Bu,
bilgisayarınızın dosya gezginini açacaktır. Bu pencereden,
.Rmd
ve .csv
dosyalarınızın bulunduğu klasörü
bulun ve Open
’a tıklayın.
Çalışma Dizinini Ayarlayın: Artık
Files
paneli doğru klasörün içeriğini gösterdiğine göre,
More
yazan dişli ikonuna
tıklayın.
Seçimi Onaylayın: Açılan menüden
Set As Working Directory
seçeneğini
seçin.
RStudio’da Çalışma Dizinini Ayarlama
Bu işlemi yaptığınızda, Konsol penceresinde setwd("...")
şeklinde bir komutun belirdiğini göreceksiniz. Bu, RStudio’nun bizim
için bu komutu otomatik olarak çalıştırdığı anlamına gelir. Artık R,
doğru atölyede olduğumuzu biliyor!
Daha kalıcı ve projelerinizi başkalarıyla paylaşırken hayat kurtaran
yöntem ise, bu komutu script’imizin en başına kendimiz yazmaktır.
setwd()
(Set Working Directory) fonksiyonu, çalışma
dizinini ayarlar.
# setwd(".../proje/klasorunuzun/yolu")
# Örnek:
setwd("/Users/ismail/Documents/R_Serisi_Projesi")
Çok Önemli Not (Windows Kullanıcıları İçin):
Windows’ta dosya yolunu kopyaladığınızda, yollar \
ters
taksim işareti ile gelir (C:\Users\...
gibi). Ancak R, bu
işareti özel bir karakter olarak algılar. Bu nedenle,
setwd()
içinde dosya yolunu yazarken tüm
\
işaretlerini /
düz taksim ile
değiştirmelisiniz!
setwd("C:\\Users\\ismail\\Desktop")
-> HATA
VEREBİLİR! (Çift \\
de çalışır ama kafa
karıştırıcıdır.)setwd("C:/Users/ismail/Desktop")
-> HER ZAMAN
ÇALIŞIR!getwd()
ile Teyit Etmesetwd()
komutunu çalıştırdıktan veya menüden ayarınızı
yaptıktan sonra, getwd()
komutunu tekrar çalıştırarak
değişikliğin başarılı olup olmadığını kontrol etmek mükemmel bir
alışkanlıktır.
# Adresi değiştirdikten sonra tekrar soralım:
getwd()
Bu komutun çıktısı, artık sizin proje klasörünüzün adresini göstermelidir.
Artık R’a atölyemizin yerini gösterdiğimize ve doğru yerde olduğumuzu teyit ettiğimize göre, ilk gerçek dünya verimizi içeri almaya tamamen hazırız!
Dostlar, atölyemizde yeterince pratik yaptık. Artık R becerilerimizi
gerçek dünya verileriyle test etme zamanı. Bu bölümde, veri bilimcilerin
oyun alanı olan Kaggle’dan popüler bir veri seti alıp,
şimdiye kadar öğrendiğimiz tüm dplyr
fiillerini bu “ham”
veri üzerinde kullanacağız.
Bu adım, serimizin en heyecan verici kısmı olabilir, çünkü artık sadece R öğrenmiyor, aynı zamanda gerçek bir veri analizi projesinin ilk adımlarını atıyoruz!
Veri Seti: “Netflix Movies and TV Shows” Bu veri
seti, Netflix’te bulunan film ve diziler hakkında show_id
,
type
, title
, country
,
release_year
gibi bilgiler içerir.
Adım 1: Veriyi İndirme
netflix_titles.csv
dosyasını bilgisayarınıza indirin..csv
dosyasını, .Rmd
projenizin bulunduğu klasörün içine koyun. Bu, dosyayı R’a yüklememizi
çok kolaylaştıracaktır.Adım 2: Veriyi R’a Yükleme tidyverse
’ün
bir parçası olan readr
paketi, read_csv()
adında çok hızlı ve güçlü bir fonksiyon içerir. Bu fonksiyonu kullanarak
verimizi yükleyeceğiz.
library(tidyverse)
# Proje klasörümüzdeki CSV dosyasını okuyalım
netflix_df <- read_csv("netflix_titles.csv")
# Veri setine ilk bakışımızı atalım
glimpse(netflix_df)
## Rows: 8,807
## Columns: 12
## $ show_id <chr> "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s1…
## $ type <chr> "Movie", "TV Show", "TV Show", "TV Show", "TV Show", "TV …
## $ title <chr> "Dick Johnson Is Dead", "Blood & Water", "Ganglands", "Ja…
## $ director <chr> "Kirsten Johnson", NA, "Julien Leclercq", NA, NA, "Mike F…
## $ cast <chr> NA, "Ama Qamata, Khosi Ngema, Gail Mabalane, Thabang Mola…
## $ country <chr> "United States", "South Africa", NA, NA, "India", NA, NA,…
## $ date_added <chr> "September 25, 2021", "September 24, 2021", "September 24…
## $ release_year <dbl> 2020, 2021, 2021, 2021, 2021, 2021, 2021, 1993, 2021, 202…
## $ rating <chr> "PG-13", "TV-MA", "TV-MA", "TV-MA", "TV-MA", "TV-MA", "PG…
## $ duration <chr> "90 min", "2 Seasons", "1 Season", "1 Season", "2 Seasons…
## $ listed_in <chr> "Documentaries", "International TV Shows, TV Dramas, TV M…
## $ description <chr> "As her father nears the end of his life, filmmaker Kirst…
Gördüğünüz gibi, artık üzerinde çalışabileceğimiz 8000’den fazla satır içeren zengin bir veri setimiz var!
dplyr
ile Netflix Verilerini KeşfetmeSoru 1: Türkiye’de çekilmiş film ve diziler hangileri?
(filter
)
# 'country' sütununda "Turkey" içerenleri filtreleyelim.
# str_detect() fonksiyonu, bir metin içinde belirli bir kelime olup olmadığını kontrol eder.
netflix_df %>%
filter(str_detect(country, "Turkey")) %>%
select(title, type, release_year) # Sadece ilgili sütunları gösterelim
Soru 2: 2020’den sonra çıkan en uzun 5 film hangisi?
(filter
, arrange
,
select
)
Bu soruyu cevaplamak için duration
sütununu temizlememiz
gerekecek. Şu an “120 min” gibi metin formatında.
separate()
fonksiyonu ile sayıyı ve “min” kelimesini
ayıralım.
netflix_df %>%
filter(type == "Movie") %>% # Sadece filmleri seç
separate(duration, into = c("sure_dakika", "birim"), sep = " ", convert = TRUE) %>%
# "120 min" -> 120, "min"
filter(release_year >= 2020) %>% # 2020 ve sonrası
arrange(desc(sure_dakika)) %>% # Süreye göre büyükten küçüğe sırala
select(title, release_year, sure_dakika) %>% # İlgili sütunları seç
head(5) # İlk 5'i göster
Soru 3: Her bir “rating” (yaş sınırı) kategorisinde kaç adet
içerik var? (group_by
, summarise
)
netflix_df %>%
group_by(rating) %>% # Yaş sınırı kategorisine göre grupla
summarise(icerik_sayisi = n()) %>% # Her gruptaki eleman sayısını (n()) say
arrange(desc(icerik_sayisi)) # Çoktan aza doğru sırala
Soru 4 (Ustalık Sorusu): Her ülkenin en çok içerik ürettiği tür (listed_in) hangisidir?
Bu karmaşık soru, dplyr
’in gücünü tam anlamıyla
gösterir.
netflix_df %>%
# Bazı içeriklerin birden fazla ülkesi var, bunları ayıralım
separate_rows(country, sep = ", ") %>%
# Bazı içeriklerin birden fazla türü var, bunları da ayıralım
separate_rows(listed_in, sep = ", ") %>%
# Boş ülke isimlerini veri setinden çıkaralım
filter(!is.na(country) & country != "") %>%
# Ülke ve türe göre gruplayıp sayalım
count(country, listed_in, name = "sayi") %>%
# Her ülke içinde en yüksek sayıya sahip olanı bulalım
group_by(country) %>%
filter(sayi == max(sayi)) %>%
# Sadece 10'dan fazla içerik üretmiş ülkeleri görelim
filter(sum(sayi) > 10) %>%
arrange(desc(sayi))
Bu bölümle birlikte, artık sadece R komutlarını bilen değil, aynı zamanda bu komutları kullanarak gerçek dünya verilerinden anlamlı bilgiler çıkarabilen bir veri kaşifiyiz dostlar!
Dostlar, atölyemizde aletlerimizi kullandık, farklı malzemeler üzerinde çalıştık ve ustalık projemizi tamamladık. Şimdi sıra, bu aletleri tamamen kendi başınıza kullanarak ne kadar harika işler çıkarabileceğinizi görmekte!
Aşağıdaki görevleri, öğrendiğimiz dplyr
fiillerini ve
%>%
(pipe) operatörünü kullanarak çözmeye çalışın.
Unutmayın, önemli olan tek bir doğru cevap bulmak değil, çözüme giden
yolda bu fiillerle rahatça “düşünebilmektir”.
Kullanılacak Veri Setleri:
cars_data
(Hazırladığımız düzenli mtcars
veri seti)netflix_df
(Kaggle’dan indirdiğimiz Netflix veri
seti)cars_data
ile Otomobil AnaliziFiltreleme ve Sıralama Sanatı:
cars_data
veri setini kullanarak, 4’ten fazla silindire
sahip (cyl > 4
), 110’dan az beygir gücü
(hp < 110
) olan arabaları bulun ve bu arabaları yakıt
verimliliğine (mpg
) göre en iyiden en kötüye doğru
sıralayın.
Veriden Yeni Bilgi Türetme:
mutate()
kullanarak wt
(ağırlık) sütununu
kilograma çevirip (wt_kg
adıyla) ve qsec
(1/4
mil süresi) sütununu kullanarak arabaların 0’dan 100 km/s hıza yaklaşık
ne kadar sürede çıktığını hesaplayan hizlanma_100km
adında
yeni bir sütun oluşturun. (Not: Bu sadece bir yaklaşımdır,
qsec
doğrudan 0-100 hızlanması değildir ama pratik için
kullanalım). Son olarak sadece model
,
wt_kg
ve hizlanma_100km
sütunlarını
gösterin.
Grupların Sırrını Çözme: am
(0 =
Otomatik, 1 = Manuel) vites tipine ve vs
(0 = V motor, 1 =
Düz motor) motor tipine göre arabaları gruplayarak her bir kombinasyon
için (örneğin, Otomatik-V motor, Manuel-Düz motor) ortalama
beygir gücünü (hp
) ve maksimum yakıt
verimliliğini (mpg
) bulun.
netflix_df
ile İçerik KeşfiYönetmen Analizi: Netflix veri setinde
(netflix_df
), “Quentin Tarantino” tarafından yönetilmiş
olan içeriklerin title
, release_year
ve
rating
bilgilerini listeleyin. (İpucu:
director
sütununda NA
yani boş değerler
olabilir, bunları filtrelerken göz ardı etmeniz
gerekebilir.)
Türlere Göre Süre Analizi:
duration
sütunundaki ” min” ifadesini kaldırarak bu
sütunu sayısal hale getirin.listed_in
(tür) kategorisi için
ortalama film süresini (ortalama_sure
)
hesaplayın.Ustalık Zinciri (Pipe ile Tek Seferde): Tek bir
%>%
zinciri kullanarak aşağıdaki adımları sırayla
uygulayın:
country
bilgisi boş olmayanları
seçin.country
(ülke) için kaç adet TV şovu olduğunu
sayın.Aşağıda, alıştırmaların R kodlarını ve bu kodların çalıştırıldığında üreteceği çıktıları bulabilirsiniz. Kendi çözümlerinizle karşılaştırarak ne kadar yol katettiğinizi görebilirsiniz!
# Çalışmaya başlamadan önce gerekli paket ve verileri yüklüyoruz.
library(tidyverse)
# cars_data'yı oluşturalım
cars_data <- mtcars %>%
rownames_to_column(var = "model")
# --- Çözüm 1: Filtreleme ve Sıralama Sanatı ---
cars_data %>%
filter(cyl > 4, hp < 110) %>%
arrange(desc(mpg))
# --- Çözüm 2: Veriden Yeni Bilgi Türetme ---
cars_data %>%
mutate(
wt_kg = wt * 1000 * 0.453592,
hizlanma_100km = qsec * 1.5 # Çok kaba bir yaklaşım, sadece pratik için :)
) %>%
select(model, wt_kg, hizlanma_100km)
# --- Çözüm 3: Grupların Sırrını Çözme ---
cars_data %>%
group_by(am, vs) %>%
summarise(
ortalama_hp = mean(hp),
maksimum_mpg = max(mpg),
.groups = 'drop'
)
# --- ŞİMDİ NETFLIX BÖLÜMÜNE GEÇİYORUZ ---
# Önce dosyanın var olup olmadığını kontrol edelim. Bu, en sağlam yöntemdir.
if (file.exists("netflix_titles.csv")) {
# Dosya varsa, onu okuyalım
netflix_df <- read_csv("netflix_titles.csv")
# --- Çözüm 4: Yönetmen Analizi ---
# Not: Bu kod bloğu sadece dosya bulunduğunda çalışacak.
print("--- Çözüm 4: Yönetmen Analizi ---")
print(
netflix_df %>%
filter(director == "Quentin Tarantino") %>%
select(title, release_year, rating)
)
# --- Çözüm 5: Türlere Göre Süre Analizi ---
print("--- Çözüm 5: Türlere Göre Süre Analizi ---")
print(
netflix_df %>%
filter(type == "Movie") %>%
mutate(sure_dakika = as.integer(str_remove(duration, " min"))) %>%
group_by(listed_in) %>%
summarise(ortalama_sure = mean(sure_dakika, na.rm = TRUE), .groups = 'drop') %>%
arrange(desc(ortalama_sure))
)
# --- Çözüm 6: Ustalık Zinciri (Pipe ile Tek Seferde) ---
print("--- Çözüm 6: Ustalık Zinciri (Pipe ile Tek Seferde) ---")
print(
netflix_df %>%
filter(type == "TV Show") %>%
filter(!is.na(country)) %>%
count(country, name = "tv_show_sayisi") %>%
arrange(desc(tv_show_sayisi)) %>%
head(10)
)
} else {
# Eğer dosya yoksa, PDF'te bilgilendirici bir not bırakalım.
cat("Netflix Alıştırmaları Atlandı: 'netflix_titles.csv' dosyası proje klasöründe bulunamadı.")
}
## [1] "--- Çözüm 4: Yönetmen Analizi ---"
## # A tibble: 8 × 3
## title release_year rating
## <chr> <dbl> <chr>
## 1 Django Unchained 2012 R
## 2 The Hateful Eight: Extended Version 2015 R
## 3 The Hateful Eight 2015 R
## 4 Inglourious Basterds 2009 R
## 5 Jackie Brown 1997 R
## 6 Kill Bill: Vol. 1 2003 R
## 7 Kill Bill: Vol. 2 2004 R
## 8 Pulp Fiction 1994 R
## [1] "--- Çözüm 5: Türlere Göre Süre Analizi ---"
## # A tibble: 278 × 2
## listed_in ortalama_sure
## <chr> <dbl>
## 1 Classic Movies, Music & Musicals 173
## 2 Action & Adventure, Cult Movies, Dramas 172
## 3 Action & Adventure, Classic Movies, International Movies 166
## 4 Cult Movies, Dramas, Thrillers 158
## 5 Classic Movies, Dramas, Romantic Movies 154.
## 6 Action & Adventure, Sci-Fi & Fantasy, Thrillers 148
## 7 Classic Movies, Cult Movies, Dramas 146.
## 8 Classic Movies, Dramas, Music & Musicals 145
## 9 Action & Adventure, Classic Movies, Dramas 145.
## 10 Action & Adventure, International Movies, Music & Musicals 139.
## # ℹ 268 more rows
## [1] "--- Çözüm 6: Ustalık Zinciri (Pipe ile Tek Seferde) ---"
## # A tibble: 10 × 2
## country tv_show_sayisi
## <chr> <int>
## 1 United States 760
## 2 United Kingdom 213
## 3 Japan 169
## 4 South Korea 158
## 5 India 79
## 6 Taiwan 68
## 7 Canada 59
## 8 France 49
## 9 Australia 48
## 10 Spain 48
Dostlar, bu bölüm boyunca dplyr
’ın temel fiillerini
öğrendik ve farklı veri setleri üzerinde pratik yaptık. Şimdi, tüm bu
becerileri bir araya getirme ve bir veri analistinin gerçek hayatta
karşılaşabileceği türden bir projeyi baştan sona tamamlama zamanı.
Bu son meydan okumada, sadece komutları kullanmakla kalmayacak, aynı zamanda bir dizi soruyu cevaplamak için veriyi nasıl şekillendireceğinizi ve ondan nasıl yeni bilgiler türeteceğinizi de düşüneceksiniz.
Senaryo: Bir sınıfın vize ve final notları elimizde. Görevimiz, bu ham veriden yola çıkarak kapsamlı bir “başarı analizi tablosu” oluşturmak ve bir dizi kritik soruya yanıt vermek.
Hazırsanız, bu bölümün final projesine başlayalım!
Proje Adımları ve Analiz Soruları:
Temel Başarı Tablosunu Oluşturma Aşağıdaki
görevleri tek bir %>%
zinciri içinde tamamlayarak
basari_tablosu
adında yeni bir veri çerçevesi
oluşturun:
GecmeNotu
’nu
hesaplayın (VizeNotu
* 0.30 + FinalNotu
*
0.70).Sonuc
sütununu oluşturun
(40 ve üzeri “Geçti”, altı “Kaldı”).Sınıf Analizi ve İçgörü Çıkarma Oluşturduğunuz
basari_tablosu
’nu kullanarak aşağıdaki soruları
dplyr
ile cevaplayın:
Soru 2.1: Sınıfta “Geçti” ve “Kaldı” olarak kaçar öğrenci bulunmaktadır?
Soru 2.2: Sınıfın genel vize, final ve geçme notu ortalamaları nedir?
Soru 2.3 (Zorlayıcı Soru): “Geçen” ve “Kalan” öğrencilerin vize ve final notu ortalamaları arasında belirgin bir fark var mıdır? (Yani, geçenlerin ortalaması ve kalanların ortalaması nedir?)
Soru 2.4 (Ustalık Sorusu): Vize notu 50’nin altında olup da final notu sayesinde dersi geçen (“kurtaran”) kaç öğrenci vardır? Bu öğrencilerin listesini gösterin.
Aşağıda, alıştırmaların R kodlarını ve bu kodların çalıştırıldığında üreteceği çıktıları bulabilirsiniz.
# Çalışmaya başlamadan önce gerekli paket ve verileri yüklüyoruz.
library(tidyverse)
# --- Kapanış Meydan Okuması: Öğrenci Not Sistemi Çözümleri ---
# Önce üzerinde çalışacağımız 20 kişilik veri setini oluşturalım
set.seed(42) # Sonuçların tekrarlanabilir olması için
ogrenci_notlari_df <- data.frame(
OgrenciNo = 202501:(202501 + 19),
OgrenciAd = paste("Öğrenci", LETTERS[1:20]),
VizeNotu = sample(20:90, 20, replace = TRUE),
FinalNotu = sample(30:100, 20, replace = TRUE)
)
# --- Adım 1: Temel Başarı Tablosunu Oluşturma ---
basari_tablosu <- ogrenci_notlari_df %>%
mutate(
GecmeNotu = (VizeNotu * 0.30) + (FinalNotu * 0.70),
Sonuc = ifelse(GecmeNotu >= 40, "Geçti", "Kaldı")
) %>%
arrange(desc(GecmeNotu))
cat("--- Adım 1 Çıktısı: Başarı Tablosu ---\n")
## --- Adım 1 Çıktısı: Başarı Tablosu ---
print(basari_tablosu)
## OgrenciNo OgrenciAd VizeNotu FinalNotu GecmeNotu Sonuc
## 1 202509 Öğrenci I 56 97 84.7 Geçti
## 2 202511 Öğrenci K 45 98 82.1 Geçti
## 3 202506 Öğrenci F 66 87 80.7 Geçti
## 4 202513 Öğrenci M 60 79 73.3 Geçti
## 5 202508 Öğrenci H 90 65 72.5 Geçti
## 6 202514 Öğrenci N 46 78 68.4 Geçti
## 7 202502 Öğrenci B 84 59 66.5 Geçti
## 8 202503 Öğrenci C 44 72 63.6 Geçti
## 9 202501 Öğrenci A 68 53 57.5 Geçti
## 10 202505 Öğrenci E 68 51 56.1 Geçti
## 11 202515 Öğrenci O 55 55 55.0 Geçti
## 12 202520 Öğrenci T 61 50 53.3 Geçti
## 13 202519 Öğrenci S 77 32 45.5 Geçti
## 14 202510 Öğrenci J 39 47 44.6 Geçti
## 15 202504 Öğrenci D 37 44 41.9 Geçti
## 16 202517 Öğrenci Q 53 35 40.4 Geçti
## 17 202507 Öğrenci G 43 37 38.8 Kaldı
## 18 202516 Öğrenci P 24 35 31.7 Kaldı
## 19 202512 Öğrenci L 22 33 29.7 Kaldı
## 20 202518 Öğrenci R 22 31 28.3 Kaldı
cat("\n\n") # Çıktılar arasına boşluk bırakmak için
# --- Adım 2: Sınıf Analizi ve İçgörü Çıkarma ---
# --- Çözüm 2.1: Geçen ve Kalan Öğrenci Sayısı ---
cat("--- Soru 2.1 Çıktısı: Sınıftaki Geçen ve Kalan Öğrenci Sayısı ---\n")
## --- Soru 2.1 Çıktısı: Sınıftaki Geçen ve Kalan Öğrenci Sayısı ---
print(
basari_tablosu %>%
count(Sonuc)
)
## Sonuc n
## 1 Geçti 16
## 2 Kaldı 4
cat("\n\n")
# --- Çözüm 2.2: Sınıfın Genel Not Ortalamaları ---
cat("--- Soru 2.2 Çıktısı: Sınıfın Genel Not Ortalamaları ---\n")
## --- Soru 2.2 Çıktısı: Sınıfın Genel Not Ortalamaları ---
print(
basari_tablosu %>%
summarise(
OrtalamaVize = mean(VizeNotu),
OrtalamaFinal = mean(FinalNotu),
OrtalamaGecme = mean(GecmeNotu)
)
)
## OrtalamaVize OrtalamaFinal OrtalamaGecme
## 1 53 56.9 55.73
cat("\n\n")
# --- Çözüm 2.3: Geçen ve Kalanların Not Ortalamaları ---
cat("--- Soru 2.3 Çıktısı: Geçen ve Kalanların Not Ortalamaları ---\n")
## --- Soru 2.3 Çıktısı: Geçen ve Kalanların Not Ortalamaları ---
print(
basari_tablosu %>%
group_by(Sonuc) %>%
summarise(
OrtalamaVize = mean(VizeNotu),
OrtalamaFinal = mean(FinalNotu),
OgrenciSayisi = n(),
.groups = 'drop'
)
)
## # A tibble: 2 × 4
## Sonuc OrtalamaVize OrtalamaFinal OgrenciSayisi
## <chr> <dbl> <dbl> <int>
## 1 Geçti 59.3 62.6 16
## 2 Kaldı 27.8 34 4
cat("\n\n")
# --- Çözüm 2.4: Vizesi Düşük Olup Dersi Kurtaranlar ---
cat("--- Soru 2.4 Çıktısı: Vizesi 50 Altında Olup Dersi Kurtaranlar ---\n")
## --- Soru 2.4 Çıktısı: Vizesi 50 Altında Olup Dersi Kurtaranlar ---
print(
basari_tablosu %>%
filter(VizeNotu < 50, Sonuc == "Geçti")
)
## OgrenciNo OgrenciAd VizeNotu FinalNotu GecmeNotu Sonuc
## 1 202511 Öğrenci K 45 98 82.1 Geçti
## 2 202514 Öğrenci N 46 78 68.4 Geçti
## 3 202503 Öğrenci C 44 72 63.6 Geçti
## 4 202510 Öğrenci J 39 47 44.6 Geçti
## 5 202504 Öğrenci D 37 44 41.9 Geçti