Merhaba Dostlar,
Projemize dalmadan önce, bir an durup yapacağımız işin felsefesini anlamamız gerekiyor: Keşifsel Veri Analizi, ya da veri kaşiflerinin dilindeki adıyla EDA.
Kendinizi okyanusta yeni bir adaya ayak basan bir kaşif olarak hayal edin. Elinizde kazma kürek, hemen rastgele bir yeri kazmaya başlamazsınız, değil mi? Önce adanın genel bir haritasını çizer, en yüksek tepeye tırmanıp araziye bir göz atar, nehirlerin nereye aktığını, hangi bölgelerin ormanlık, hangilerinin kayalık olduğunu anlarsınız. Kısacası, neyle karşı karşıya olduğunuzu anlamak için bir keşif yaparsınız.
İstatistik dünyasında bu keşif yaklaşımını ilk kez sistematik hale getiren ve popülerleştiren kişi, efsanevi istatistikçi John W. Tukey’dir. Tukey (1977), EDA’yı “verinin bize söylemek zorunda olmadığı şeyleri bize nasıl söyleyebileceğini araştırma” sanatı olarak tanımlamıştır. Bu, veri setini daha derinlemesine analiz etmeden veya üzerine karmaşık makine öğrenmesi modelleri kurmadan önce, onun temel özelliklerini anlamak, özetlemek ve görselleştirmek için kullandığımız bir ilk temas sanatı ve bilimidir. Amacı, verinin bize anlattığı hikayeyi, henüz biz sormadan fısıldadığı sırları ortaya çıkarmaktır.
İyi bir veri analizi süreci, her zaman EDA ile başlar. Çünkü EDA bize şunları sağlar:
Verinin Sırlarını Açığa Çıkarmak: Veri setindeki gizli kalmış desenleri, beklenmedik ilişkileri ve aykırı değerleri ilk bu aşamada fark ederiz. Belki de masrafları en çok etkileyen faktör, ilk bakışta hiç aklımıza gelmeyecek bir değişkendir. EDA, bu “vay canına!” anlarını yaşadığımız yerdir (Han, J., Kamber, M., & Pei, J., 2006) .
Hataları ve Anormallikleri Yakalamak: Veri her zaman temiz gelmez. EDA sırasında, imkansız değerleri veya veri giriş hatalarını tespit ederiz. Eksik verilerin yapısını anlamak, projenin ilerleyen adımlarında uygulanacak stratejiler için hayati önem taşır (Little, R. J. A., & Rubin, D. B., 2002) .
Değişkenleri Tanımak: Her bir değişkenin dağılımı nasıldır? Sağa mı çarpık, normale mi yakın? Bu temel soruların cevapları, sonraki adımlarda hangi istatistiksel teknikleri kullanabileceğimizi belirler (Field, A., 2013) .
İlişkilerin Haritasını Çıkarmak: Hangi değişkenler birbiriyle güçlü bir ilişkiye sahip? Bu ilişkileri anlamak, modelleme aşaması için hipotezler kurmamızı sağlar ve model seçimi konusunda bize rehberlik eder (James, G., Witten, D., Hastie, T., & Tibshirani, R., 2023) .
Bu keşif sürecinde en sık kullanacağımız teknikler şunlardır:
Tek Değişkenli (Univariate) Analiz: Her bir değişkeni tek başına incelemek.
summary()
), sayısal verilerin dağılımı için histogramlar
(geom_histogram()
), kategorik verilerin frekansı için çubuk
grafikler (geom_bar()
) (Tukey, J. W., 1977; Field, A.,
2013) .İki Değişkenli (Bivariate) Analiz: Değişkenleri ikili çiftler halinde inceleyerek aralarındaki ilişkiye bakmak.
geom_point()
), bir sayısal ve bir kategorik
değişken için kutu grafikleri (geom_boxplot()
) (Tukey,
J. W., 1977; James, G., Witten, D., Hastie, T., & Tibshirani, R.,
2023) .Aykırı Değer Tespiti: Kutu grafikleri veya IQR (Interquartile Range) yöntemi ile modelin performansını olumsuz etkileyebilecek uç değerleri belirlemek (Barnett, V., & Lewis, T., 1984) .
EDA’nın ruhu, sürekli soru sormaktır: “Neden bu böyle?”, “Şu iki değişken arasında bir ilişki olabilir mi?”, “Bu aykırı değer bir hata mı, yoksa hikayenin en önemli parçası mı?”. Bu süreçte en büyük yardımcımız ise veri görselleştirme olacaktır. Hadley Wickham’ın da belirttiği gibi, “görselleştirmenin amacı hipotezleri doğrulamak değil, onları keşfetmektir.” (Wickham, H., 2016) .
Bu bölüm hazırlanırken Keşifsel Veri Analizi alanındaki aşağıdaki temel eserlerden yararlanılmıştır:
Teorik altyapımızı sağlamlaştırdığımıza ve bu sürecin öncülerine saygımızı sunduğumuza göre, artık bu felsefeyi eyleme dökme zamanı. Haydi, kaşif şapkamızı takıp Sigorta Masrafları veri setimizle ilk adımı atalım!
Her büyük keşif, iyi bir hazırlıkla başlar. Bu adımda, tıpkı bir kaşifin haritasını masaya yayması, pusulasını kontrol etmesi ve kampını kurması gibi, biz de çalışma ortamımızı hazırlayacak ve veri setimizle ilk teması kuracağız.
İhtiyacımız olan tüm araçları çalışma alanımıza getirmemiz gerekiyor.
Serimizin İsviçre çakısı olan tidyverse
paketini çağırarak
başlıyoruz. Bu paketi, Bölüm 3’de görmüş, felsefesini
ve gücünü anlamaya başlamıştık.
# Gerekli kütüphanelerimizi çağıralım
library(tidyverse) # ggplot2, dplyr, readr gibi temel araçlarımızı içerir
Şimdi, projemizin kalbi olan insurance.csv
dosyasını R
ortamına yükleyelim. Bunun için readr
paketinin
(tidyverse
içinde gelir) güçlü fonksiyonu
read_csv()
’yi kullanacağız.
#insurance.csv dosyasını okuyup 'insurance_df' adında bir data frame'e atayalım
insurance_df <- read_csv("insurance.csv")
Ustalık Notu:
Değişken ismini insurance_df
olarak belirledik. Sonuna
_df
eklemek, bu nesnenin bir “Data Frame” olduğunu
kendimize ve kodumuzu okuyan başkalarına hatırlatmak için R topluluğunda
sıkça kullanılan iyi bir pratiktir.
Veri setimiz artık R’da. Peki içinde ne var? Bu sorunun cevabını almak için birkaç temel komutla hızlı bir keşif turuna çıkacağız.
head()
ile İlk Merhabahead()
fonksiyonu, veri setimizin ilk 6 satırını bize
gösterir. Bu, bir kitabın ilk sayfasını okumak gibidir; bize sütun
isimleri ve verinin genel formatı hakkında anında bir fikir verir.
# Veri setimizin ilk 6 satırına bakalım
head(insurance_df)
Gördüklerimiz:
age
, sex
, bmi
gibi sütun
isimlerini ve içlerindeki “female”, “yes”, 19, 27.9 gibi gerçek verileri
görüyoruz. Her şey yolunda görünüyor.
glimpse()
ile X-Ray Görüşüglimpse()
fonksiyonu, dplyr
’in bize sunduğu
harika bir araçtır ve veri çerçevemizin adeta röntgenini çeker. Bize
veri setinin boyutlarını, her bir sütunun adını, veri tipini
(<chr>
, <dbl>
) ve ilk birkaç
değerini tek bir temiz çıktıda sunar.
# Veri setimizin yapısına içeriden bir bakış atalım
glimpse(insurance_df)
## Rows: 1,338
## Columns: 7
## $ age <dbl> 19, 18, 28, 33, 32, 31, 46, 37, 37, 60, 25, 62, 23, 56, 27, 1…
## $ sex <chr> "female", "male", "male", "male", "male", "female", "female",…
## $ bmi <dbl> 27.900, 33.770, 33.000, 22.705, 28.880, 25.740, 33.440, 27.74…
## $ children <dbl> 0, 1, 3, 0, 0, 0, 1, 3, 2, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0…
## $ smoker <chr> "yes", "no", "no", "no", "no", "no", "no", "no", "no", "no", …
## $ region <chr> "southwest", "southeast", "southeast", "northwest", "northwes…
## $ charges <dbl> 16884.924, 1725.552, 4449.462, 21984.471, 3866.855, 3756.622,…
Gördüklerimiz ve Yorumumuz:
age
ve children
<dbl>
(double), yani ondalıklı
olabilecek sayılar olarak okunmuş.sex
, smoker
, region
<chr>
(character), yani metin olarak
okunmuş. Bu doğru, çünkü bunlar kategorik değişkenler.charges
(hedef değişkenimiz) de
<dbl>
, yani sayısal. Bu da
beklediğimiz bir durum.summary()
ile Hızlı İstatistiksel Kontrolsummary()
fonksiyonu, her bir sütun için temel
istatistiksel bir özet sunar. Sayısal değişkenler için bize minimum,
maksimum, ortalama, medyan gibi değerleri verirken; kategorik
değişkenler için uzunluk ve sınıf bilgisini verir.
# Her sütunun istatistiksel özetini görelim
summary(insurance_df)
## age sex bmi children
## Min. :18.00 Length:1338 Min. :15.96 Min. :0.000
## 1st Qu.:27.00 Class :character 1st Qu.:26.30 1st Qu.:0.000
## Median :39.00 Mode :character Median :30.40 Median :1.000
## Mean :39.21 Mean :30.66 Mean :1.095
## 3rd Qu.:51.00 3rd Qu.:34.69 3rd Qu.:2.000
## Max. :64.00 Max. :53.13 Max. :5.000
## smoker region charges
## Length:1338 Length:1338 Min. : 1122
## Class :character Class :character 1st Qu.: 4740
## Mode :character Mode :character Median : 9382
## Mean :13270
## 3rd Qu.:16640
## Max. :63770
Gördüklerimiz ve İlk Çıkarımlarımız:
charges
dağılımının sağa çarpık
olabileceğinin (yani, çok yüksek masraflara sahip küçük bir grup insanın
ortalamayı yukarı çektiğinin) ilk sinyalini veriyor! Bu, Adım
2’de histogram çizdiğimizde doğrulayacağımız önemli bir
ipucu.colSums(is.na())
ile Gönül RahatlığıBir kaşifin en büyük kabusu, yola çıktıktan sonra ekipmanının eksik olduğunu fark etmesidir. Bizim için bu, eksik veridir. Analize başlamadan önce veri setimizde eksik değer olup olmadığını kontrol edelim.
# Her sütundaki eksik değer (NA) sayısını toplayarak gösterelim
colSums(is.na(insurance_df))
## age sex bmi children smoker region charges
## 0 0 0 0 0 0 0
Gördüklerimiz ve Yorumumuz:
Mükemmel! Her sütun için sonuç 0
. Bu, veri setimizin
tertemiz olduğu ve eksik verilerle başa çıkmak için ekstra adımlar
atmamıza gerek olmadığı anlamına geliyor. Keşif gezimize gönül
rahatlığıyla devam edebiliriz.
1. Adım Özeti ve Sonraki Adım
Harika! Keşif gezimizin ilk adımını başarıyla tamamladık. Kampımızı kurduk, haritamızı inceledik ve genel durumu anladık:
charges
’ın dağılımı hakkında
ilk önemli ipucumuzu yakaladık.Artık genel manzarayı gördüğümüze göre, dürbünümüzü alıp her bir tepeyi (değişkeni) tek tek daha yakından inceleme zamanı. Bir sonraki adımımız, Tek Değişkenli Analiz olacak!
İlk adımda veri setimizin genel bir panoramasını çektik. Artık haritanın üzerindeki her bir tepeyi, ovayı ve nehri (yani her bir değişkeni) daha yakından inceleme zamanı. Bu adımda, her bir değişkeni tek başına ele alarak dağılımlarını, merkezlerini ve yayılımlarını anlamaya çalışacağız. Bu, hikayemizin karakterlerini tek tek tanımak gibidir.
Öncelikle sayısal (numeric) değişkenlerimiz olan age
,
bmi
, children
ve hedef değişkenimiz
charges
’ın dağılımlarını görselleştirelim.
Bunun için Bölüm 4.6’da öğrendiğimiz
geom_histogram()
ve Bölüm 4.3’da
tanıştığımız geom_boxplot()
fonksiyonlarını
kullanacağız.
Bir değişkenin nasıl bir dağılıma sahip olduğunu anlamanın en iyi yollarından biri histogram çizmektir.
# Yaş Dağılımı
p_age_hist <- ggplot(insurance_df, aes(x = age)) +
geom_histogram(binwidth = 5, fill = "#1f77b4", color = "white", alpha = 0.8) +
labs(title = "Yas Dagilimi", x = "Yas", y = "Kisi Sayisi") +
theme_light()
# BMI Dağılımı
p_bmi_hist <- ggplot(insurance_df, aes(x = bmi)) +
geom_histogram(binwidth = 2, fill = "#ff7f0e", color = "white", alpha = 0.8) +
labs(title = "Vucut Kitle Indeksi (BMI) Dagilimi", x = "BMI", y = "Kisi Sayisi") +
theme_light()
# Çocuk Sayısı Dağılımı
p_children_hist <- ggplot(insurance_df, aes(x = children)) +
geom_histogram(binwidth = 1, fill = "#2ca02c", color = "white", alpha = 0.8) +
labs(title = "Cocuk Sayisi Dagilimi", x = "Cocuk Sayisi", y = "Kisi Sayisi") +
theme_light()
# Sigorta Masrafları Dağılımı
p_charges_hist <- ggplot(insurance_df, aes(x = charges)) +
geom_histogram(binwidth = 5000, fill = "#d62728", color = "white", alpha = 0.8) +
labs(title = "Sigorta Masraflari Dagilimi", x = "Masraflar ($)", y = "Kisi Sayisi") +
theme_light()
Şimdi, Bölüm 4.8’de öğrendiğimiz
patchwork
paketinin gücünü kullanarak bu dört grafiği tek
bir tuvalde sergileyelim.
# Patchwork kütüphanesini çağıralım
library(patchwork)
# Grafikleri birleştirelim
(p_age_hist + p_bmi_hist) / (p_children_hist + p_charges_hist)
Gördüklerimiz ve Yorumumuz:
summary()
fonksiyonunda şüphelendiğimiz gibi, masrafların
dağılımı ciddi şekilde sağa çarpık (right-skewed). Bu,
insanların büyük çoğunluğunun düşük masraflara sahip olduğunu, ancak çok
yüksek masraflara sahip küçük bir grubun olduğunu gösterir. Bu
çarpıklık, ileride modelleme yapacak olursak dikkate almamız gereken en
önemli özelliklerden biridir.Şimdi de kategorik (character) değişkenlerimize (sex
,
smoker
, region
) bakalım. Bu değişkenlerin
frekanslarını, yani her bir kategoride kaç kişi olduğunu anlamak için
Bölüm 3’nden dplyr::count()
ve
Bölüm 4.3’ten geom_bar()
fonksiyonlarını
kullanacağız.
# Cinsiyet Dağılımı
p_sex_bar <- ggplot(insurance_df, aes(x = sex, fill = sex)) +
geom_bar() +
labs(title = "Cinsiyet Dagilimi", x = "Cinsiyet", y = "Kisi Sayisi") +
theme_light() +
theme(legend.position = "none") # Lejant gereksiz, kaldıralım
# Sigara İçme Durumu Dağılımı
p_smoker_bar <- ggplot(insurance_df, aes(x = smoker, fill = smoker)) +
geom_bar() +
# YENİ KATMAN: Renkleri manuel olarak belirliyoruz
scale_fill_manual(values = c("no" = "#2ca02c", "yes" = "#d62728")) +
labs(title = "Sigara Icme Durumu", x = "Sigara Iciyor mu?", y = "Kisi Sayisi") +
theme_light() +
theme(legend.position = "none")
# Bölge Dağılımı
p_region_bar <- ggplot(insurance_df, aes(x = region, fill = region)) +
geom_bar() +
# YENİ KATMAN: Her bir bölge için özel bir renk atıyoruz
scale_fill_manual(values = c(
"southwest" = "#1f77b4", # Mavi
"southeast" = "#ff7f0e", # Turuncu
"northwest" = "#2ca02c", # Yeşil
"northeast" = "#9467bd" # Mor
)) +
labs(title = "Bolge Dagilimi", x = "Bolge", y = "Kisi Sayisi") +
theme_light() +
theme(legend.position = "none")
# Bu üç grafiği yan yana sergileyelim
p_sex_bar + p_smoker_bar + p_region_bar
Gördüklerimiz ve Yorumumuz:
2. Adım Özeti ve Sonraki Adım:
Bu adımda, her bir değişkenin profilini çıkardık ve karakterlerini anladık.
charges
değişkenindeki sağa çarpıklık,
hikayemizin en önemli ipuçlarından biri olacak.Karakterlerimizi tek tek tanıdığımıza göre, artık onların birbirleriyle olan ilişkilerini, yani hikayenin olay örgüsünü incelemeye başlayabiliriz. Bir sonraki adımımız, İkili İlişki Analizi!
Önceki adımda hikayemizin karakterlerini (değişkenleri) tek tek
tanıdık. Şimdi ise bu karakterlerin birbirleriyle olan ilişkilerini,
diyaloglarını ve etkileşimlerini inceleyeceğiz. Özellikle de herkesin
etrafında döndüğü ana karakter olan charges
(masraflar) ile
diğer değişkenlerin ilişkisi, bu keşif gezimizin en önemli etabını
oluşturuyor. Artık “Ne?” sorusundan “Neden?” sorusuna geçiş
yapıyoruz.
Bir kategorik değişkenin (örneğin “sigara içiyor” / “içmiyor”) sayısal bir değişken (masraflar) üzerindeki etkisini anlamak için en güçlü araçlarımızdan biri kutu grafikleridir. Bu tekniği Bölüm 4.3’de detaylıca öğrenmiştik.
Acaba sigara içme durumu, sigorta masrafları üzerinde ne kadar
etkili? geom_boxplot
ile bu sorunun cevabını görsel olarak
arayalım.
ggplot(insurance_df, aes(x = smoker, y = charges, fill = smoker)) +
geom_boxplot(alpha = 0.8) +
labs(
title = "Sigara Icme Durumuna Gore Sigorta Masraflari",
x = "Sigara Iciyor mu?",
y = "Masraflar ($)"
) +
theme_light() +
theme(legend.position = "none") +
# Ortalama değerleri de noktalarla göstererek daha fazla bilgi ekleyelim
stat_summary(fun = mean, geom = "point", shape = 23, size = 4, fill = "white")
Gördüklerimiz ve Yorumumuz:
Bu, projemizdeki belki de en net ve en sarsıcı grafik!
Aynı analizi cinsiyet ve bölge için de yapalım. Bu sefer,
Bölüm 4.8’de öğrendiğimiz patchwork
ile
iki grafiği yan yana koyarak alanımızı daha verimli kullanalım.
# Cinsiyete Göre Masraflar
p_sex_charges <- ggplot(insurance_df, aes(x = sex, y = charges, fill = sex)) +
geom_boxplot(alpha = 0.8) +
labs(title = "Cinsiyete Gore Masraflar", x = "Cinsiyet", y = "Masraflar ($)") +
theme_light() +
theme(legend.position = "none")
# Bölgeye Göre Masraflar
p_region_charges <- ggplot(insurance_df, aes(x = region, y = charges, fill = region)) +
geom_boxplot(alpha = 0.8) +
labs(title = "Bolgelere Gore Masraflar", x = "Bolge", y = "Masraflar ($)") +
theme_light() +
theme(legend.position = "none")
# İki grafiği birleştirelim
p_sex_charges + p_region_charges
Gördüklerimiz ve Yorumumuz:
southeast
(güneydoğu) bölgesinin
kutusu bir tık daha yukarıda olsa da, aradaki farklar dramatik
değil.Şimdi de iki sayısal değişken arasındaki ilişkiyi anlamak için en iyi
aracımız olan saçılım grafiklerine (geom_point
) bakalım. Bu
tekniğin temellerini Bölüm 4.2’de görmüştük. “Yaş
arttıkça masraflar artar mı?” veya “Kilo aldıkça masraflar artar mı?”
gibi sorulara cevap arayacağız.
Yaş Faktörü
ggplot(insurance_df, aes(x = age, y = charges)) +
geom_point(color = "#1f77b4", alpha = 0.5) +
labs(
title = "Yas ve Sigorta Masraflari Arasindaki Iliski",
x = "Yas",
y = "Masraflar ($)"
) +
theme_light()
Gördüklerimiz ve Yorumumuz:
Vücut Kitle İndeksi (BMI) Faktörü
ggplot(insurance_df, aes(x = bmi, y = charges)) +
geom_point(color = "#ff7f0e", alpha = 0.5) +
labs(
title = "BMI ve Sigorta Masraflari Arasindaki Iliski",
x = "Vucut Kitle Indeksi (BMI)",
y = "Masraflar ($)"
) +
theme_light()
Gördüklerimiz ve Yorumumuz:
3. Adım Özeti ve Sonraki Adım:
Bu adımda çok önemli ipuçları yakaladık:
Bu gizemli kümelerin sırrını çözmek ve değişkenlerin birbirleriyle olan “etkileşimini” anlamak için, artık birden fazla değişkeni aynı anda analiz etme zamanı. Bir sonraki adımımız, Çok Değişkenli Analiz!
Önceki adımlarda hikayemizin karakterlerini tanıdık ve ikili ilişkilerini gözlemledik. Ancak gerçek hayatta olduğu gibi, verideki ilişkiler de nadiren bu kadar basittir. Genellikle birden fazla faktör bir araya gelerek bir sonucu etkiler. Bu adımda, bir dedektif gibi çalışarak ikiden fazla değişkeni aynı anda analiz edecek ve hikayenin daha derin katmanlarını ortaya çıkaracağız.
Adım 3’te, yaş ve masraflar arasındaki ilişkiyi incelediğimiz saçılım
grafiğinde üç gizemli “küme” fark etmiştik. Acaba bu kümeleri oluşturan
ortak özellik ne olabilir? Aklımıza gelen en güçlü şüpheli, Adım 3.1’de
masrafları dramatik şekilde etkilediğini gördüğümüz smoker
(sigara içme durumu) değişkeni.
Bu hipotezi test etmek için, Bölüm 4.2’de
öğrendiğimiz en güçlü tekniklerden birini kullanacağız:
color
estetiğini kullanarak noktaları üçüncü bir değişkene
göre renklendirmek.
ggplot(insurance_df, aes(x = age, y = charges, color = smoker)) +
geom_point(alpha = 0.7) +
labs(
title = "Yas ve Masraflar Iliskisi (Sigara Durumuna Gore)",
subtitle = "Gizemli kumelerin sirri sigara icme durumunda yatıyor!",
x = "Yas",
y = "Masraflar ($)",
color = "Sigara Icme Durumu" # Lejant başlığını Türkçeleştirelim
) +
theme_light()
Gördüklerimiz ve Yorumumuz:
Aha! İşte o an!
geom_smooth
ile NetleştirmekBu “etkileşim etkisini” daha da net göstermek için, Bölüm
4.4’de öğrendiğimiz geom_smooth()
fonksiyonunu
kullanarak her grup için ayrı bir trend çizgisi ekleyebiliriz.
ggplot(insurance_df, aes(x = age, y = charges, color = smoker)) +
geom_point(alpha = 0.5) +
# Her renk grubu için ayrı bir lineer model (lm) trend çizgisi ekle
geom_smooth(method = "lm", se = FALSE, size = 1.2) +
labs(
title = "Yas ve Masraflar Arasindaki Trendler",
subtitle = "Sigara icenler ve icmeyenler icin trendler birbirinden çok farkli",
x = "Yas",
y = "Masraflar ($)",
color = "Sigara Icme Durumu"
) +
theme_light()
Gördüklerimiz ve Yorumumuz:
Gördüklerimiz ve Yorumumuz: Trend çizgileri, hikayeyi çok daha net bir şekilde anlatıyor. Bu grafikte iki önemli bulgu var:
Farklı Başlangıç Seviyeleri (Intercept): Sigara içenlerin (turkuaz çizgi) masrafları, daha en genç yaşlarda bile sigara içmeyenlere (kırmızı çizgi) göre çok daha yüksek bir seviyeden başlıyor. Aradaki bu devasa başlangıç farkı, sigara içmenin maliyetler üzerindeki en baskın etkisidir.
Farklı Eğimler (Slope): Dikkatli bakıldığında, sigara içenlerin trend çizgisinin eğiminin, içmeyenlerinkinden bir miktar daha dik olduğu seziliyor. Bu, her geçen yılın, sigara içen bir kişinin sigorta maliyetini, içmeyen birine göre daha fazla artırdığı anlamına gelir. Peki bu görsel sezgiyi matematiksel olarak kanıtlayabilir miyiz? Elbette!
Ustalık Notu: İşte İspatı!
Bir trend çizgisinin eğimi (slope), basit bir lineer
regresyon modelindeki (y ~ x
) x
değişkeninin
katsayısıdır. Bu katsayı, x’teki bir birimlik artışın y’de
ortalama olarak ne kadarlık bir değişikliğe yol
açtığını gösterir. Şimdi her iki grup için bu eğim katsayılarını
hesaplayarak görsel sezgimizi matematiksel olarak kanıtlayalım.
# Sadece sigara içmeyenler için lineer model
model_icmeyenler <- lm(charges ~ age, data = filter(insurance_df, smoker == "no"))
egim_icmeyenler <- coef(model_icmeyenler)["age"]
# Sadece sigara içenler için lineer model
model_icenler <- lm(charges ~ age, data = filter(insurance_df, smoker == "yes"))
egim_icenler <- coef(model_icenler)["age"]
# Sonuçları yazdıralım
cat("Sigara İçmeyenlerin Eğim Katsayısı (Yıllık Ortalama Artış):", round(egim_icmeyenler, 2), "$\n")
## Sigara İçmeyenlerin Eğim Katsayısı (Yıllık Ortalama Artış): 267.25 $
cat("Sigara İçenlerin Eğim Katsayısı (Yıllık Ortalama Artış): ", round(egim_icenler, 2), "$")
## Sigara İçenlerin Eğim Katsayısı (Yıllık Ortalama Artış): 305.24 $
Gördüğümüz gibi, R’a sorduğumuzda bize net bir cevap veriyor. Bu iki modelin eğim katsayıları, yani “yıllık ortalama masraf artışı” miktarları şunlardır: Sigara içmeyenler için her yıl ortalama 267 USD, sigara içenler için ise her yıl ortalama 305 USD. Bu matematiksel kanıt, iki grubun maliyet trendlerinin farklı eğimlere sahip olduğunu ve aradaki makasın yaş ilerledikçe daha da açıldığını kesin olarak doğrulamaktadır.
facet_wrap
ile Sahneyi BölmekBazen grafikleri renklerle ayırmak yerine, tamamen ayrı panellere
bölmek hikayeyi daha net anlatabilir. Bölüm 4.7’de
değindiğimiz facet_wrap()
fonksiyonu tam da bu işe
yarar.
Şimdi de BMI ve masraflar arasındaki ilişkiyi, sigara içenler ve içmeyenler için ayrı ayrı panellerde inceleyelim.
# `facet_wrap` başlıklarını daha anlamlı hale getirmek için bir çeviri fonksiyonu oluşturalım.
# Bu, Bölüm 4.8'de öğrendiğimiz "sözlük" mantığının bir başka versiyonudur.
smoker_labeller <- as_labeller(c(`no` = "Sigara Icmeyenler", `yes` = "Sigara Icenler"))
ggplot(insurance_df, aes(x = bmi, y = charges, color = smoker)) + # Renk artık 'smoker'a göre
geom_point(alpha = 0.7) +
# Trend çizgisi artık her grubun kendi renginde olacak
geom_smooth(method = "lm", se = FALSE, size = 1.2) +
#`labeller` argümanını ekleyerek başlıkları anlamlı hale getiriyoruz.
facet_wrap(~ smoker, labeller = smoker_labeller) +
labs(
title = "BMI ve Masraflar Iliskisi: Iki Farkli Dunya",
x = "Vucut Kitle Indeksi (BMI)",
y = "Masraflar ($)"
) +
theme_light() +
# Lejant artık bir anlam ifade ediyor (renklerin kime ait olduğunu gösteriyor),
scale_color_manual(values = c("no" = "#1f77b4", "yes" = "#d62728"))
Gördüklerimiz ve Yorumumuz:
Sigara İçmeyenler
Paneli: Bu grupta
(mavi noktalar), BMI ile masraflar arasında çok zayıf bir pozitif ilişki
var. Trend çizgisi neredeyse yatay. Bu, sigara içmeyen bir kişi için
kilonun, masraflar üzerinde tek başına büyük bir belirleyici olmadığını
gösteriyor.Sigara İçenler
Paneli: Bu grupta ise
(kırmızı noktalar) dünya tamamen farklı! BMI arttıkça masraflar da
belirgin ve güçlü bir şekilde artıyor. Trend çizgisinin
dik eğimi, sigara içen ve aynı zamanda yüksek BMI’a sahip kişilerin en
yüksek risk grubunu oluşturduğunu net bir şekilde kanıtlıyor.4. Adım Özeti ve Sonraki Adım:
Bu adımda, hikayenin en derin sırlarını çözdük:
color
ve facet_wrap
gibi
ggplot2
yeteneklerinin, bu tür karmaşık ilişkileri ortaya
çıkarmada ne kadar güçlü olduğunu canlı olarak gördük.Artık veri setimizin ana dinamiklerini anladığımıza göre, bir kaşifin yeni yollar ve kısayollar keşfetmesi gibi, biz de elimizdeki veriden yeni bilgiler türetebilir miyiz diye bakacağız. Bir sonraki adımımız, Özellik Mühendisliği!
Şu ana kadar veri setimizdeki değişkenleri olduğu gibi kullandık.
Ancak bazen, mevcut değişkenlerden yeni bilgiler türetmek, hikayeyi çok
daha net bir şekilde anlatmamızı sağlar. Bu sürece Özellik
Mühendisliği (Feature Engineering) diyoruz. Bu adımda, sürekli
sayılar olan age
ve bmi
değişkenlerinden, daha
kolay yorumlayabileceğimiz kategorik gruplar oluşturacağız.
Bu işlemi yapmak için Bölüm 3’nda öğrendiğimiz ve
dplyr
paketinin en güçlü fonksiyonlarından olan
mutate()
ve case_when()
ikilisini
kullanacağız.
Vücut Kitle İndeksi (BMI), tek başına bir sayı olarak anlamlı olsa da, genellikle sağlık kategorileriyle birlikte yorumlanır (“Normal Kilo”, “Fazla Kilolu”, “Obez”). Biz de şimdi bu kategorileri kendimiz oluşturalım. Dünya Sağlık Örgütü’nün genel sınıflandırmasını referans alacağız.
# `mutate()` ile `insurance_df` veri setimize yeni bir sütun ekliyoruz.
insurance_df <- insurance_df %>%
mutate(bmi_category = case_when(
bmi < 18.5 ~ "Zayif",
bmi >= 18.5 & bmi < 25 ~ "Normal Kilo",
bmi >= 25 & bmi < 30 ~ "Fazla Kilolu",
bmi >= 30 ~ "Obez"
))
# --- Ustalık Dokunuşu: Kategorileri Mantıksal Sıraya Koyma ---
# `bmi_category` sütununu, seviyelerini (levels) belirttiğimiz bir faktöre dönüştürüyoruz.
# ggplot2, grafiği çizerken bu sıralamaya sadık kalacaktır.
insurance_df$bmi_category <- factor(insurance_df$bmi_category,
levels = c("Zayif", "Normal Kilo", "Fazla Kilolu", "Obez"))
Yeni bmi_category
sütunumuz hazır! Peki bu yeni değişken
bize ne anlatıyor? Bu kategorilerin masraflar üzerindeki etkisini, yine
en sevdiğimiz araçlardan biri olan geom_boxplot
ile
görselleştirelim.
ggplot(insurance_df, aes(x = bmi_category, y = charges, fill = bmi_category)) +
geom_boxplot(alpha = 0.8) +
labs(
title = "BMI Kategorilerine Gore Sigorta Masraflari",
subtitle = "Kilo kategorisi arttikca masraflarin medyani da artma egilimindedir",
x = "Vucut Kitle Indeksi Kategorisi",
y = "Masraflar ($)"
) +
theme_light() +
theme(legend.position = "none")
Gördüklerimiz ve Yorumumuz:
Grafik “Zayıf” kategorisinden “Obez” kategorisine doğru mantıksal bir akış sergiliyor. Bu sıralama sayesinde, BMI arttıkça medyan masrafların da (kutu içindeki çizgiler) basamak basamak nasıl yükseldiğini çok daha net bir şekilde görebiliyoruz.
Özellikle “Obez” kategorisindeki masraf dağılımının diğerlerine göre çok daha geniş ve yukarı yönlü olduğu, şimdi bu mantıksal sırada daha da çarpıcı bir şekilde ortaya çıkıyor. Bu, obezitenin masraflar üzerinde önemli bir risk faktörü olduğunu güçlü bir şekilde doğruluyor.
age
değişkeni de sürekli bir sayı. Bazen, belirli yaş
aralıklarının davranışlarını karşılaştırmak, tek tek yaşları
incelemekten daha anlamlı olabilir. Örneğin, “genç yetişkinler” ile
“emekliliğe yakın olanlar” arasında masraf farkı var mı?
Yine mutate()
ve case_when()
kullanarak yaş
grupları oluşturalım.
insurance_df <- insurance_df %>%
mutate(age_group = case_when(
age < 30 ~ "18-29 (Genc Yetiskin)",
age >= 30 & age < 45 ~ "30-44 (Orta Yas)",
age >= 45 & age < 60 ~ "45-59 (Deneyimli Yetiskin)",
TRUE ~ "60+ (Kidemli)" # Geriye kalan tüm durumlar için (60 ve üstü)
))
Oluşturduğumuz bu yeni yaş gruplarının masraflar üzerindeki etkisini görselleştirelim.
ggplot(insurance_df, aes(x = age_group, y = charges, fill = age_group)) +
geom_violin(alpha = 0.8, trim = FALSE) + # Dağılımları daha iyi görmek için violin plot kullanalım!
geom_boxplot(width = 0.1, fill = "white") +
labs(
title = "Yas Gruplarina Gore Sigorta Masraflari",
x = "Yas Grubu",
y = "Masraflar ($)"
) +
theme_light() +
theme(legend.position = "none", axis.text.x = element_text(angle = 15, hjust = 1))
Ustalık Notu:
Bu grafikte, Bölüm 4.3’te gördüğümüz
geom_boxplot
ile Bölüm 4.6’te gördüğümüz
yoğunluk grafiğinin bir birleşimi olan geom_violin()
kullandık. Keman grafikleri, bize sadece kutu grafiğindeki özet
istatistikleri değil, aynı zamanda o aralıktaki veri yoğunluğunu da
gösterir. İçine eklediğimiz ince geom_boxplot
ile de her
iki dünyanın en iyi yönlerini birleştirmiş olduk!
Gördüklerimiz ve Yorumumuz:
5. Adım Özeti ve Sonraki Adım:
Bu adımda, ham veriden yeni ve anlamlı bilgiler türetme gücümüzü gördük:
mutate()
ve case_when()
’in ne kadar esnek
ve güçlü olduğunu canlı olarak uyguladık.Artık kaşifimiz adanın neredeyse her köşesini gezdi, haritasını çizdi, gizli patikaları keşfetti ve önemli ipuçlarını topladı. Geriye tek bir şey kalıyor: Tüm bu bulguları bir araya getirip, keşif günlüğüne son notları düşmek. Bir sonraki ve son adımımız, Bulguların Raporlanması!
Keşifsel Veri Analizi yolculuğumuzun sonuna geldik. Şimdiye kadar veriyi temizledik, değişkenleri tek tek tanıdık, aralarındaki gizli ve açık ilişkileri keşfettik ve hatta yeni bilgiler türettik. Artık tüm bu bulguları bir araya getirme ve ana sorumuz olan “Bir kişinin sağlık sigortası maliyetini hangi faktörler en çok etkiler?” sorusuna net cevaplar verme zamanı.
Bu adımda, teknik olmayan, herkesin anlayabileceği bir dille
sonuçlarımızı özetleyeceğiz. Ancak bu özetleri desteklemek için,
Bölüm 3’de öğrendiğimiz group_by()
ve
summarise()
fonksiyonlarını kullanarak kesin ve sayısal
kanıtlar sunacağız.
Görselleştirmelerimiz bize harika ipuçları verdi. Şimdi o ipuçlarını somut rakamlara dökelim.
Grafiklerde sigara içenlerin masraflarının çok daha yüksek olduğunu görmüştük. Peki, ne kadar daha yüksek?
# `smoker` değişkenine göre gruplayıp her grubun ortalama masrafını hesaplayalım
smoker_summary <- insurance_df %>%
group_by(smoker) %>%
summarise(
ortalama_masraf = mean(charges),
medyan_masraf = median(charges),
kisi_sayisi = n() # Her gruptaki kişi sayısını görmek için
)
# Sonuçları güzel bir formatta yazdıralım
knitr::kable(smoker_summary, caption = "Sigara Icme Durumuna Gore Ortalama ve Medyan Masraflar")
smoker | ortalama_masraf | medyan_masraf | kisi_sayisi |
---|---|---|---|
no | 8434.268 | 7345.405 | 1064 |
yes | 32050.232 | 34456.348 | 274 |
Bu tablo bize şunu söylüyor: Sigara içen bir kişinin ortalama sigorta
masrafı (32,050 USD
), içmeyen birininkinden
(8,434 USD
) yaklaşık 4 kat daha fazladır!
Bu, analizimizdeki en baskın ve en net bulgudur.
Yeni oluşturduğumuz bmi_category
özelliğinin de etkili
olduğunu görmüştük. Özellikle “Obez” kategorisinin masrafları
artırdığını fark etmiştik. Şimdi bunu sayılarla görelim.
# `bmi_category`'e göre gruplayıp ortalama masrafı hesaplayalım
bmi_summary <- insurance_df %>%
group_by(bmi_category) %>%
summarise(
ortalama_masraf = mean(charges)
) %>%
arrange(ortalama_masraf) # Sonuçları ortalama masrafa göre sıralayalım
knitr::kable(bmi_summary, caption = "BMI Kategorisine Gore Ortalama Masraflar")
bmi_category | ortalama_masraf |
---|---|
Zayif | 8852.201 |
Normal Kilo | 10409.338 |
Fazla Kilolu | 10987.510 |
Obez | 15552.335 |
Tablo, “Zayıf” kategorisinden “Obez” kategorisine doğru gidildikçe ortalama masrafların istikrarlı bir şekilde arttığını doğruluyor.
En ilginç bulgularımızdan biri, yaş ve sigaranın “etkileşim” halinde olmasıydı. Yani, sigara içen yaşlı bir kişinin masrafı, bu iki faktörün tekil etkilerinin toplamından daha fazlaydı. Bunu da sayılarla gösterelim.
# Hem `age_group` hem de `smoker`'a göre gruplayalım
interaction_summary <- insurance_df %>%
group_by(age_group, smoker) %>%
summarise(ortalama_masraf = mean(charges))
knitr::kable(interaction_summary, caption = "Yas Grubu ve Sigara Durumuna Gore Ortalama Masraflar")
age_group | smoker | ortalama_masraf |
---|---|---|
18-29 (Genc Yetiskin) | no | 4418.568 |
18-29 (Genc Yetiskin) | yes | 27518.035 |
30-44 (Orta Yas) | no | 6945.332 |
30-44 (Orta Yas) | yes | 30833.988 |
45-59 (Deneyimli Yetiskin) | no | 11871.666 |
45-59 (Deneyimli Yetiskin) | yes | 35889.869 |
60+ (Kidemli) | no | 15232.709 |
60+ (Kidemli) | yes | 40630.695 |
Bu tablo, hikayenin en can alıcı noktasını ortaya koyuyor. Örneğin, “18-29” yaş grubundaki sigara içen birinin masrafı, içmeyen yaşıtından çok daha fazladır. Ve bu fark, yaş grubu ilerledikçe daha da açılmaktadır. “60+” yaş grubundaki sigara içen bir kişinin ortalama masrafı (yaklaşık 40,631 USD), aynı yaş grubundaki sigara içmeyen bir kişiden (yaklaşık 15,233 USD) yaklaşık 2.7 kat daha fazladır.
Bu detaylı Keşifsel Veri Analizi yolculuğunun sonunda, ana sorumuza şu net cevapları verebiliriz:
En Güçlü Faktör: Sigara Kullanımı
İkinci Dereceden Önemli Faktörler: Yaş ve Vücut Kitle İndeksi (BMI)
“Tetikleyici Etki”: Etkileşimler Her Şeydir
Daha Az Etkili Faktörler: Cinsiyet ve Bölge
Bu proje, bize EDA’nın gücünü bir kez daha gösterdi. Basit özet istatistiklerden ve güçlü görselleştirmelerden yola çıkarak, bir veri setinin içinde yatan karmaşık ve çok katmanlı hikayeyi nasıl ortaya çıkarabileceğimizi canlı olarak deneyimledik. Artık bu veri setini çok daha derin bir seviyede anlıyoruz ve gelecekteki herhangi bir modelleme çalışması için kaya gibi sağlam bir temele sahibiz.
Bravo dostlar! Bu keşif gezisini başarıyla tamamladık ve serimizin
başından beri öğrendiğimiz araçlarla (dplyr
,
ggplot2
, patchwork
) ne kadar derin analizler
yapabileceğimizi kanıtladık.
Ancak unutmayalım ki, bir veri kaşifinin alet çantası her zaman daha da zenginleşebilir. Bu Keşifsel Veri Analizi (EDA) çalışmasını, şu ana kadar Bölüm 4.8’e kadar öğrendiğimiz bilgi ve yetenekler çerçevesinde gerçekleştirdik.
Peki ya daha fazlası?
log
gibi
dönüşümlerle normale yaklaştırarak modellemeye
hazırlama sanatı,Tüm bu ileri seviye konular ve çok daha fazlası, serimizin gelecek bölümlerinde alet çantamıza ekleyeceğimiz yeni ve güçlü araçlar olacak. Bu proje, yolculuğumuzun sonu değil, daha derin sulara yelken açmadan önce ulaştığımız sağlam bir limandı.
Şimdi alet çantamızı daha da doldurmaya ve yeni keşiflere hazırlanmaya devam edelim!
Peki, bu kazandığımız yeni süper güçleri nerede kullanacağız? Veri Görselleştirme Sanatı’nın temellerini ve ustalık dokunuşlarını öğrendiğimize göre, artık vites yükseltme zamanı geldi!
Mini-Bölüm 5.1 ile, bir projeyi “elle” yapmanın, her grafiği özenle çizmenin ve her bulguyu adım adım keşfetmenin ne kadar öğretici ve önemli olduğunu gördük. Verinin ruhunu anlamak için bu “zanaatkar” yaklaşımı paha biçilmezdir.
Ama ya zamana karşı yarışıyorsak? Ya önümüzde keşfedilecek onlarca yeni veri seti varsa? İşte o zaman bir veri kaşifinin en iyi dostu, verimli araçlarıdır.
Mini-Bölüm 5.2: Veri Kaşifinin Pusulası - Otomatik EDA
Paketleri bölümünde işleri bir üst vitese takacağız. Projeyi
“elle” yapmanın ardındaki mantığı anladıktan sonra,
DataExplorer
, summarytools
ve
SmartEDA
gibi güçlü paketler sayesinde tüm bu keşif
sürecini tek bir komutla nasıl otomatize edebileceğimizi ve
projelerimize başlarken nasıl inanılmaz bir hız kazanabileceğimizi
göreceğiz.
Hazır olun, çünkü alet çantamızı doldurduk ve şimdi gerçek keşiflere başlıyoruz!
Veriyle kalın. Lütfen takipte kalın dostlar….