Merhaba Dostlar,
Veri görselleştirme dünyasında bildiğimiz yolların sonuna geldik ve şimdi kendi patikalarımızı yaratma zamanı. ggplot2 ile attığımız sağlam temellerin üzerine, her biri farklı bir hikaye anlatma biçiminde uzmanlaşmış, niş ama bir o kadar da güçlü araçlarla dolu bir gökdelen inşa edeceğiz.
Bu atölyede, standart grafiklerin ötesine geçerek alet çantamıza çok daha özel ve etkileyici araçlar ekleyeceğiz. Amacımız, veriyi sadece göstermek değil, onunla bir sanat eseri yaratmak!
Atölye Menümüz: Sihirli Aletler
İşte atölye boyunca masamızın üzerinde olacak o sihirli aletler:
Akışları ve Bağlantıları Anlatmak: ggalluvial paketi ile Sankey grafikleri çizeceğiz. Bir sürecin adımları arasındaki geçişleri, müşteri segmentlerinin zaman içindeki değişimini veya herhangi bir sistemdeki akışları bir nehir gibi görselleştireceğiz.
Hiyerarşileri ve Oranları Resmetmek: treemapify paketi ile o karmaşık hiyerarşileri ve iç içe geçmiş oranları, anlaşılması kolay ve estetik Ağaç Haritaları’na (Treemaps) dönüştüreceğiz. Bütünü ve parçalarını tek bir bakışta görebilmek hiç bu kadar şık olmamıştı!
Coğrafi Hikayeleri Canlandırmak: leaflet paketi ile verilerimizi bir dünya haritası üzerine taşıyarak onlara coğrafi bir ruh katacağız. Kullanıcının keşfedebileceği, yakınlaşıp uzaklaşabileceği interaktif haritalar ile verinin nerede olduğunu anlatacağız.
Grafiklere Hayat Vermek: Ve son olarak, ggplot2 ile yarattığımız o güzel statik grafikleri alıp, plotly ile onlara interaktivite, gganimate ile de hareket kazandırarak onları yaşayan, nefes alan birer veri hikayesine dönüştüreceğiz!
Hazır mısın?
Bu bölümün sonunda, elindeki her bir veri setine baktığında “Bunu en etkileyici şekilde nasıl anlatabilirim?” sorusuna verecek birden çok yaratıcı cevabın olacak.
Şimdi kollarımızı sıvayalım ve ilk aletimiz olan ggalluvial ile veri nehirlerinde bir yolculuğa çıkalım!
ggalluvial ile Akışları
GörselleştirmeAtölyemizin ilk durağında, kategorik veriler arasındaki akışları ve
bağlantıları görselleştirmek için kullanılan güçlü bir aracı,
ggalluvial paketini öğreneceğiz.
Peki, Alluvial veya Sankey diyagramları nedir?
Bu grafikleri, verinin bir noktadan diğerine nasıl aktığını gösteren nehirler gibi düşünebilirsin. Örneğin:
göstermek için mükemmeldirler. Kısacası, “Nereden geldi, nereye gitti?” sorusunun en estetik cevabıdır bu grafikler.
Bu bölümü hazırlarken harika bir dersle karşılaştık:
ggalluvial paketinin yeni versiyonlarında, daha önce içinde
bulunan titanic_long veri seti kaldırılmış. Bu, veri bilimi
dünyasında çok normal bir durumdur. İyi bir analist, bu gibi durumlarda
pes etmez, çözüm üretir. Biz de şimdi tam olarak bunu yapıyoruz:
İhtiyacımız olan veriyi, R’ın temelindeki Titanic veri
setinden kendimiz üreteceğiz!
ggalluvial Neden Özel Bir Format İster?Grafiği çizmeden önce cevaplamamız gereken çok önemli bir soru var:
Neden R’daki standart Titanic veri setini doğrudan
kullanamadık da onu to_lodes() ile dönüştürmek zorunda
kaldık?
1. “Geniş” (Wide) Format - Standart Hali:
Önce R’daki orijinal Titanic verisinin dönüştürülmüş
haline bakalım:
library(tidyverse)
titanic_genis <- as.data.frame(Titanic)
head(titanic_genis)
Bu formata “geniş format” denir. Her bir satır, kategorilerin benzersiz bir kombinasyonunu (Sınıf, Cinsiyet, Yaş, Hayatta Kalma) ve bu kombinasyona kaç kişinin dahil olduğunu (Freq) gösterir. Bu format, özet tablolar ve bazı analizler için harikadır.
Ancak bir AKIŞI görselleştirmek için uygun değildir. ggplot’a bu tabloyla, “Önce Class’ı, sonra Sex’i eksen olarak koy ve aralarındaki bağlantıyı çiz” demenin doğrudan bir yolu yoktur. ggplot hangi frekansın nereden nereye aktığını bilemez.
2. “Uzun” (Lodes) Format - ggalluvial’ın Sevdiği Hali:
İşte to_lodes() fonksiyonunun yarattığı sihirli format:
library(ggalluvial)
# Bu kod bloğu sadece gösterim amaçlıdır, asıl işlem aşağıda yapılacak.
titanic_uzun_yeni_ornek <- to_lodes(titanic_genis, key = "x", value = "stratum",
id = "alluvium", axes = 1:4)
head(titanic_uzun_yeni_ornek)
Bu formata “uzun format” veya ggalluvial dilinde “lodes formatı” denir. Farkları görelim:
-alluvium: Bu, en kritik sütundur. Her bir orijinal akışa (örneğin ‘1. Sınıf, Erkek, Yetişkin, Hayatta Kalanlar’ grubu) verilen benzersiz bir kimlik kartı gibidir. ggalluvial bu kimlik kartını takip ederek nehrin bir eksenden diğerine nasıl akması gerektiğini anlar.
-x: Grafiğimizdeki dikey eksenleri temsil eder. Yani “1. durak (Class)”, “2. durak (Sex)” gibi…
-stratum: Bu duraklardaki kategorilerin kendisidir (‘1st’, ‘Male’, ‘Yes’ gibi).
-Freq: Bu kimlik kartına sahip akışın kalınlığını belirler.
Kısacası, to_lodes() fonksiyonu, özetlenmiş “geniş” veriyi alıp, her bir akışa bir kimlik kartı (alluvium) atayarak ve her adımı (x, stratum) tek tek satırlara yazarak, ggplot’un anlayabileceği bir “yol tarifine” dönüştürür. İşte bu yüzden bu dönüşüm, Alluvial diyagramları çizebilmemiz için zorunludur!
Artık neden yaptığımızı bildiğimize göre, nasıl yapıldığını gösteren nihai kodumuza geçebiliriz.
# --- ADIM 1: Kütüphaneleri Yükle ---
library(tidyverse)
library(ggalluvial)
# --- ADIM 2: Veriyi Hazırla ---
# R'da yerleşik olan `Titanic` veri setini bir veri çerçevesine dönüştürelim.
titanic_genis <- as.data.frame(Titanic)
# Şimdi bu "geniş" formatı, `ggalluvial`'ın sevdiği "uzun" formata çevirelim.
titanic_uzun_yeni <- to_lodes(titanic_genis,
key = "x", # Eksenler sütununun adı 'x' olsun
value = "stratum", # Kategori sütununun adı 'stratum' olsun
id = "alluvium", # Akış ID'si sütununun adı 'alluvium' olsun
axes = 1:4) # İlk 4 sütunu eksen olarak kullan
# --- ADIM 3: Grafiği Çiz ---
# Artık kendi ürettiğimiz "uzun" veri ile grafiğimizi çizebiliriz.
ggplot(data = titanic_uzun_yeni,
aes(x = x,
stratum = stratum,
alluvium = alluvium,
y = Freq, # Akışın kalınlığını 'Freq' sütunu belirleyecek
fill = stratum,
label = stratum)) +
geom_flow(stat = "alluvium", lode.guidance = "forward", color = "darkgray") +
geom_stratum() +
geom_text(stat = "stratum", size = 3, color = "black") +
labs(
title = "Titanic Yolcularinin Hayatta Kalma Akisi",
subtitle = "Sinif, Cinsiyet, Yas ve Hayatta Kalma Durumu Arasindaki Iliski",
x = "Degisken",
y = "Yolcu Sayisi"
) +
theme_minimal() +
theme(legend.position = "none")
Ustalık Dokunuşu: Rengi Hikayenin Odağına Göre Değiştirmek
Oluşturduğumuz ilk grafik genel akış yapısını göstermekte başarılıydı. Ancak, belirli bir başlangıç grubunun (örneğin 1. Sınıf yolcularının) akıbetini takip etmek imkansızdı.
Çözüm, ggplot’un en güçlü özelliklerinden birinde yatar: estetikleri (aes) verideki farklı sütunlara atayabilmek. Şimdi çizeceğimiz grafiğin bir “hafızası” olmasını ve bir akışın başlangıç noktasını unutmamasını sağlayacağız.
Akışları Başlangıç Noktasına Göre Renklendirme (Mevkilerin Kaderi)
Bu grafikte soracağımız soru şudur: “Her bir mevkiden yola çıkan yolcuların akıbeti ne oldu?”
# Kütüphaneleri ve veriyi bir önceki adımdan zaten hazırlamıştık,
# ama bu bloğun tek başına çalışabilmesi için tekrar ekleyelim.
library(tidyverse)
library(ggalluvial)
titanic_genis <- as.data.frame(Titanic)
titanic_uzun_yeni <- to_lodes(titanic_genis, key = "x", value = "stratum", id = "alluvium", axes = 1:4)
# Her bir akış grubuna ('alluvium'), o grubun başlangıç sınıfını içeren yeni bir sütun ekleyelim.
titanic_renk_sinif <- titanic_uzun_yeni %>%
group_by(alluvium) %>%
mutate(BaslangicSinifi = first(stratum)) %>%
ungroup()
# Şimdi grafiği 'fill' estetiğini bu yeni sütuna bağlayarak çizelim!
ggplot(data = titanic_renk_sinif,
aes(x = x,
stratum = stratum,
alluvium = alluvium,
y = Freq,
fill = BaslangicSinifi, # Rengi artık başlangıç sınıfı belirliyor!
label = stratum)) +
geom_flow(stat = "alluvium", lode.guidance = "forward") +
geom_stratum(color = "black") + # Katmanların kenarlıklarını belirginleştirelim
geom_text(stat = "stratum", size = 3.5, color = "black") +
labs(
title = "Titanic'teki Mevkilerin Kaderi",
subtitle = "Akislar, yolcularin baslangictaki sinifina gore renklendirilmistir",
x = "Degisken",
y = "Yolcu Sayisi",
fill = "Baslangic Sinifi"
) +
theme_minimal(base_size = 14) # Genel yazı boyutunu biraz büyütelim
İşte bu! Şimdi grafiği tekrar dikkatle okuyalım:
Bu grafiği yorumlarken, lejanttaki (Başlangıç Sınıfı) kategori isimleri ile akışların renklerini eşleştirmelisiniz.
Mürettebatı (Crew) temsil eden akışın (lejantta mor renkli) neredeyse tamamının nasıl ‘No’ (Hayatta Kalamadı) havuzuna aktığını net bir şekilde görebilirsiniz.
Birinci Sınıfı (1st) temsil eden akışın (lejantta kırmızı/pembe renkli) ne kadar büyük bir kısmının ‘Yes’ (Hayatta Kaldı) havuzuna ulaştığını, özellikle de kadınlar (Female) üzerinden geçtiğinde, rahatlıkla takip edebilirsiniz.
Üçüncü Sınıfı (3rd) temsil eden akışın (lejantta turkuaz renkli) ise ne kadar ezici bir çoğunlukla ‘No’ havuzuna döküldüğünü görmek artık çok kolay.
Bu grafik, artık sadece bir akış şeması değil, güçlü bir hikaye anlatıcısıdır.
ggalluvial Neden Özel Bir Format İster?
İkinci ÖrnekElimizde standart, “geniş” (wide) formatta bir veri varsa ne yapacağız sorusuna ikinci örnek ile cevap verip bu çözüm yolunu pekiştirelim.
to_lodes() fonksiyonu standart veri çerçevelerini ggalluvial’ın sevdiği uzun formata çevirdiğini tekrar hatırlayalım.
Atölyemizde şimdiye kadar veriyi dönüştürmeyi ve akışları çizmeyi öğrendik. Şimdi ise bu iki yeteneği birleştirerek, veri biliminin en ünlü paradokslarından birini, Simpson Paradoksu’nu, R’da yerleşik olarak bulunan UCBAdmissions veri seti üzerinden görsel bir kanıta dönüştüreceğiz.
Bu veri setindeki yüzeysel bir analiz, Berkeley’in cinsiyet ayrımcılığı yaptığı gibi yanıltıcı bir sonuca götürebilir. Ancak standart bir akış grafiği, bu veri setindeki gizli katmanı göstermekte yetersiz kalacaktır.
Bu yüzden bir veri kaşifi olarak biz, işe doğrudan bir “ustalık dokunuşu” ile başlayacağız. Grafiğimizi, hikayenin en kilit noktası olan “Kabul Durumu”nu (Admitted/Rejected) takip edecek şekilde, en başından doğru kurgulayacağız. Amacımız, kabul edilen ve edilmeyen grupların izlediği yolu renklerin hafızasını kullanarak takip etmektir.
# Veri setine bakalım. Bu bir "table" formatında.
UCBAdmissions
Bu veriyi önce bir veri çerçevesine (data.frame), sonra da to_lodes() ile akış formatına çevirelim.
# --- ADIM 1: Gerekli Kütüphaneler ---
library(tidyverse)
library(ggalluvial)
# --- ADIM 2: Veriyi Hazırlama ---
# R'da yerleşik veriyi modern bir data.frame'e çevirelim.
ucb_df <- as.data.frame(UCBAdmissions)
# Veriyi ggalluvial'ın anlayacağı 'uzun' formata dönüştürelim.
ucb_lodes <- to_lodes(ucb_df, key = "variable", value = "stratum", id = "cohort", axes = c("Admit", "Gender", "Dept"))
# --- ADIM 3: Ustalık Dokunuşu! ---
# Her akış grubuna ('cohort'), o grubun başlangıçtaki kabul durumunu ('stratum') içeren
# yeni bir 'KabulDurumu' sütunu ekleyelim. Bu, grafiğimizin "hafızası" olacak.
ucb_renkli <- ucb_lodes %>%
group_by(cohort) %>%
mutate(KabulDurumu = first(stratum)) %>%
ungroup()
# --- ADIM 4: Nihai Grafiği Çizme ---
# Şimdi grafiği 'fill' estetiğini bu yeni 'KabulDurumu' sütununa bağlayarak çizelim.
ggplot(data = ucb_renkli,
aes(x = variable,
stratum = stratum,
alluvium = cohort,
y = Freq,
fill = KabulDurumu, # Rengi, akışın en başındaki Kabul Durumu belirliyor!
label = stratum)) +
geom_flow(stat = "alluvium", lode.guidance = "forward", alpha = 0.8) +
geom_stratum(color = "black", alpha = 1) +
geom_text(stat = "stratum", size = 3.5, color = "black") +
labs(
title = "UC Berkeley Basvurularinda Kabul Durumuna Gore Akis",
subtitle = "Kabul edilen ve reddedilen gruplarin izledigi yollar",
y = "Basvuru Sayisi",
fill = "Basvuru Sonucu"
) +
theme_minimal(base_size = 14) +
theme(axis.title.x = element_blank())
Grafiğin Yorumu ve Ustalık İpucu: Lejanttaki O Gizemli ‘NA’ Nedir?
Grafiğimiz tam istediğimiz hikayeyi anlatıyor, ancak lejantta bir de NA kategorisi belirdi. Bu bir hata değil, aksine ggplot’un bize verdiği mantıklı bir bilgidir ve hikayemizi güçlendirir.
Peki, bu NA neden ortaya çıktı?
Bunun nedeni, aes(fill = KabulDurumu) komutunu ana ggplot() fonksiyonuna yazmamızdır. Bu, ggplot’a şu genel emri verir: “Bu grafiğe ekleyeceğim BÜTÜN katmanları, KabulDurumu sütununa göre renklendir.”
geom_flow (Akışlar): Bu katman emre uyar. Her akışın bir “Admitted” veya “Rejected” geçmişi olduğu için kendini bu renklere boyar.
geom_stratum (Kutular): Bu katman emri uygulamaya çalıştığında bir sorunla karşılaşır: Admit eksenindeki “Admitted” ve “Rejected” kutuları için bir renk karşılığı vardır. Ancak Gender eksenindeki “Male”, “Female” veya Dept eksenindeki “A”, “B”, “C” kutularının KabulDurumu diye bir karşılığı yoktur. Onlar kendi başlarına birer kategoridir.
İşte bu noktada ggplot bize dürüstçe cevap verir: “Akışları istediğiniz gibi renklendirdim. Ama Gender ve Dept eksenlerindeki kutuların renk karşılığını bulamadım, bu yüzden onları ‘NA’ (Eşleşme Yok) olarak etiketliyor ve varsayılan gri renge boyuyorum.”
Bu gri kutular, görsel olarak hikayemizin ana odağı olan renkli akışlardan ayrışarak grafiğin okunabilirliğini artırır. Dolayısıyla bu NA’den kurtulmaya çalışmak yerine, onun ggplot’un bize sunduğu akıllıca bir varsayılan ayar olduğunu bilmek gerçek bir ustalık göstergesidir.
Grafiğin Ardındaki Hikaye: Simpson Paradoksu’nu Deşifre Etmek
Elinizdeki bu grafik, sadece bir veri görselleştirmesi değil, aynı zamanda bir dedektiflik hikayesidir. Bize, veriye yüzeysel bakmanın ne kadar tehlikeli olabileceğini ve asıl gerçeğin genellikle bir katman derinde nasıl saklandığını gösterir. Bu meşhur olayın adı Simpson Paradoksu’dur.
Haydi, bir veri kaşifi gibi bu grafikteki ipuçlarını adım adım takip edelim.
1. İpucu: Yüzeydeki Aldatıcı Görüntü
Eğer dikkatinizi sadece ilk iki eksene (Admit ve Gender) verirseniz, yanıltıcı bir sonuca kolayca varabilirsiniz:
Admit eksenindeki “Admitted” (Kabul Edilenler) kutusundan çıkan pembe nehre bakın. Bu nehrin “Male” (Erkek) kutusuna akan kolu, “Female” (Kadın) kutusuna akan koldan gözle görülür şekilde daha kalındır.
Tersine, “Rejected” (Reddedilenler) kutusundan çıkan turkuaz nehrin “Female” kutusuna akan kolu oldukça kalındır.
Bu ilk bakış, bize “Berkeley Üniversitesi’ne yapılan başvurularda erkek adaylar, kadın adaylara göre daha avantajlı bir konumda” gibi bir ön yargı sunar. Eğer analizimizi burada bitirseydik, tamamen yanlış bir sonuca varmış olurduk.
2. İpucu: Renkleri Takip Ederek Gerçeğe Ulaşmak (Ustalık Dokunuşu)
İşte grafiğimize eklediğimiz “hafıza”nın, yani renklerin gücünün ortaya çıktığı an burasıdır. Şimdi, akışları başlangıç noktalarından son duraklarına kadar takip edelim:
Pembe Nehri Takip Edin (Admitted): “Kabul Edilenler” grubunu temsil eden pembe akışların izlediği yola odaklanın. Bu akışların ezici bir çoğunlukla A ve B departmanlarında son bulduğunu net bir şekilde görebilirsiniz. C, D, E ve F departmanlarına ulaşan pembe akışlar ise oldukça cılızdır. Anlamı: Kabul edilen öğrencilerin büyük bir kısmı, aslında sadece iki departmandan (A ve B) gelmektedir.
Turkuaz Nehri Takip Edin (Rejected): “Reddedilenler” grubunu temsil eden turkuaz akışların yolculuğuna bakın. Bu akışların en güçlü ve en yoğun olduğu yerlerin C, D, E ve F departmanları olduğunu görebilirsiniz. Anlamı: Reddedilen öğrencilerin büyük bir kısmı ise diğer dört departmanda yoğunlaşmıştır.
Sonuç: Paradoksun Çözülmesi
Bu iki ipucunu birleştirdiğimizde, gerçek hikaye ortaya çıkar:
Sorun, üniversitenin cinsiyete dayalı bir ayrımcılık yapması değildir. Sorun, farklı cinsiyetlerdeki başvuru sahiplerinin, farklı zorluk seviyelerindeki departmanlara başvurma eğiliminde olmalarıdır.
-Departman A ve B: Veriler bize bu departmanların kabul oranlarının genel olarak daha yüksek olduğunu gösteriyor. Ve tesadüfen (veya değil), erkek adaylar toplamda bu “kolay” departmanlara daha fazla başvurmuşlardır.
-Departman C, D, E ve F: Veriler bize bu departmanların kabul oranlarının genel olarak çok daha düşük ve rekabetin çetin olduğunu gösteriyor. Ve kadın adaylar toplamda bu “zor” departmanlara daha fazla başvurmuşlardır.
Özetle, genel ortalamaya bakıldığında kadınların kabul oranı daha düşük görünür, çünkü kadınlar kendilerini daha zorlu bir rekabetin içine atmışlardır. Eğer her departmanı kendi içinde inceleseydik, bazı zorlu departmanlarda kadınların kabul oranının erkeklerden daha bile yüksek olduğunu görebilirdik.
Bu grafik, bir veri kaşifinin en önemli dersini özetler: Korelasyon, nedensellik değildir. Veride görülen bir eğilimin ardında, onu açıklayan “gizli” bir değişken (lurking variable) olabilir. Bizim hikayemizde bu gizli değişken, “Başvuru Yapılan Departmanın Zorluğu” idi ve bu ustalıkla hazırlanmış Alluvial diyagramı, o gizli değişkeni aydınlatan bir fener görevi gördü.
Harika bir başlangıç yaptık! Veri nehirlerimizi başarıyla oluşturduk. Şimdi atölyemizin bir sonraki tezgâhına geçip hiyerarşileri ve oranları treemapify ile nasıl görselleştireceğimize bakalım.