1. Kütüphanelerin Yüklenmesi

Analiz için gerekli olan kütüphaneler yükleniyor.

library(tidyverse)
# tidyverse paketi veri manipülasyonu ve okuma işlemleri için yükleniyor. 

library(ggplot2)
# ggplot2 paketi görselleştirme işlemleri için yükleniyor. 

library(corrplot)
# corrplot paketi korelasyon matrislerini görselleştirmek için kullanılır.

library(caTools)
# caTools paketi veri setini train ve test olarak bölmek için kullanılır.

library(car)
# car paketi VIF (Variance Inflation Factor) testini hesaplamak için gereklidir. Çoklu bağıntı problemini tespit etmeye yarar.

library(lmtest)
# lmtest paketi Breusch-Pagan ve Durbin-Watson gibi istatistiksel testleri yapmak için kullanılır.

library(fastDummies)
# fastDummies paketi one-hot encoding işlemi için aktif hale getiriliyor.

2. Veri Yükleme ve Genel Bakış

data <- read.csv("/Users/fatihakcay/Desktop/rrrr/insurance.csv")
df <- data
# Kullanıcıdan bir CSV dosyası seçmesi isteniyor ve bu dosya df isimli bir veri çerçevesine yükleniyor.

cat("Veri Seti Boyutu:", dim(df), "\n")
## Veri Seti Boyutu: 1338 7
# Veri setinin boyutu yani satır ve sütun sayısı ekrana yazdırılıyor.
# Çıktıya göre veri seti toplamda (satır sayısı) gözlem ve (sütun sayısı)değişkenden oluşmaktadır.
# Bu büyüklük, çoklu doğrusal regresyon analizi için yeterli gözlem sayısına sahip olunduğunu göstermektedir.

print(head(df))
##   age    sex    bmi children smoker    region   charges
## 1  19 female 27.900        0    yes southwest 16884.924
## 2  18   male 33.770        1     no southeast  1725.552
## 3  28   male 33.000        3     no southeast  4449.462
## 4  33   male 22.705        0     no northwest 21984.471
## 5  32   male 28.880        0     no northwest  3866.855
## 6  31 female 25.740        0     no southeast  3756.622
# Veri setinin ilk 6 satırı ekrana yazdırılarak veriye genel bir bakış sağlanıyor.
# İlk 6 gözlem incelendiğinde değişkenlerin veri tipleri ve genel dağılımları hakkında ön bilgi edinilmektedir.
# charges değişkeninin sayısal ve geniş aralıklı olduğu, diğer değişkenlerin ise beklenen formatta olduğu görülmektedir.

3. Eksik Veri ve Aykırı Değer Analizi

cat("\n--- Eksik Veri Sayıları ---\n")
## 
## --- Eksik Veri Sayıları ---
print(colSums(is.na(df)))
##      age      sex      bmi children   smoker   region  charges 
##        0        0        0        0        0        0        0
# Her sütundaki eksik veri sayısı hesaplanıp ekrana yazdırılıyor.
# Çıktıya göre veri setinde eksik gözlem bulunmamaktadır (tüm değişkenler için NA sayısı 0'dır).
# Bu durum, modelleme öncesinde eksik veri temizleme veya imputasyon işlemine gerek olmadığını göstermektedir.

numeric_cols <- c("age", "bmi", "children", "charges")
# Sayısal değişkenlerin isimleri bir vektörde toplanıyor. Bu değişkenler üzerinde aykırı değer analizi yapılacak.

cat("\n--- Aykırı Değer Analizi (IQR) ---\n")
## 
## --- Aykırı Değer Analizi (IQR) ---
for(col in numeric_cols) {
  # Sayısal her sütun için döngü başlatılıyor.
  
  Q1 <- quantile(df[[col]], 0.25)
  # Birinci çeyrek değeri yani %25'lik dilim hesaplanıyor.
  
  Q3 <- quantile(df[[col]], 0.75)
  # Üçüncü çeyrek değeri yani %75'lik dilim hesaplanıyor.
  
  IQR <- Q3 - Q1
  # Çeyrekler arası açıklık IQR hesaplanıyor. Bu değer aykırı değer tespitinde kullanılır.
  
  lower <- Q1 - 1.5 * IQR
  # Alt sınır hesaplanıyor. Bu sınırın altındaki değerler aykırı kabul edilir.
  
  upper <- Q3 + 1.5 * IQR
  # Üst sınır hesaplanıyor. Bu sınırın üstündeki değerler aykırı kabul edilir.
  
  outliers <- df[[col]][df[[col]] < lower | df[[col]] > upper]
  # Alt veya üst sınırın dışında kalan değerler outliers vektörüne atanıyor.
  
  cat(col, ":", length(outliers), "adet aykırı değer bulundu.\n")
  # Her değişken için bulunan aykırı değer sayısı ekrana yazdırılıyor.
  # IQR yöntemine göre her bir sayısal değişkende aykırı değer sayısı ayrı ayrı raporlanmıştır.
  # Özellikle charges değişkeninde bulunan aykırı değer sayısının diğer değişkenlere kıyasla daha fazla olması beklenen bir durumdur.
  # Bunun nedeni sigorta maliyetlerinin bazı bireylerde çok yüksek değerlere ulaşabilmesidir.
  # Bu aykırı değerler model sonuçlarını etkileyebileceği için, sonraki aşamalarda tanı testleri ve grafikler ile birlikte değerlendirilecektir.
}
## age : 0 adet aykırı değer bulundu.
## bmi : 9 adet aykırı değer bulundu.
## children : 0 adet aykırı değer bulundu.
## charges : 139 adet aykırı değer bulundu.

4. Veri Ön İşleme (Encoding)

df <- df %>%
  mutate(
    sex_encoded = ifelse(sex == "male", 1, 0),
    smoker_encoded = ifelse(smoker == "yes", 1, 0)
  )
# sex değişkeni için male ise 1, female ise 0 değeri atanıyor. smoker değişkeni için yes ise 1, no ise 0 değeri atanıyor. Bu işlem binary encoding olarak bilinir.

df <- dummy_cols(df, select_columns = "region", remove_first_dummy = TRUE)
# region değişkeni için one-hot encoding yapılıyor. remove_first_dummy parametresi ile ilk dummy değişken çıkarılarak çoklu bağıntı probleminden kaçınılıyor.

names(df) <- make.names(names(df))
# Sütun isimlerindeki boşluk, tire gibi karakterler R'ın kurallarına uygun hale getiriliyor.

5. Görselleştirme ve Korelasyon

selected_cols <- c("age", "bmi", "children", "charges", "sex_encoded", "smoker_encoded")
# Korelasyon analizi için kullanılacak sayısal sütunlar seçiliyor.

cor_matrix <- cor(df[, selected_cols])
# Seçilen sütunlar arasındaki korelasyon matrisi hesaplanıyor.

corrplot(cor_matrix, method = "color", type = "upper", 
         addCoef.col = "black", tl.col = "black", title = "Korelasyon Matrisi")

# Korelasyon matrisi renkli bir ısı haritası şeklinde görselleştiriliyor. Sadece üst üçgen gösteriliyor ve korelasyon katsayıları siyah yazı ile ekleniyor.
# Korelasyon matrisi incelendiğinde charges değişkeni ile smoker_encoded arasında güçlü ve pozitif yönlü bir ilişki olduğu görülmektedir.
# Bu sonuç, sigara içen bireylerin sigorta maliyetlerinin belirgin biçimde daha yüksek olduğunu göstermektedir.
# charges ile age ve bmi değişkenleri arasında pozitif yönlü ancak smoker değişkenine kıyasla daha zayıf ilişkiler gözlemlenmektedir.
# sex_encoded ve children değişkenlerinin charges ile olan korelasyonlarının ise oldukça düşük olduğu görülmektedir.
# Bu durum, bu değişkenlerin tek başına maliyetleri açıklama gücünün sınırlı olabileceğini düşündürmektedir.
ggplot(df, aes(x = smoker, y = charges, fill = smoker)) +
  geom_boxplot() +
  theme_minimal() +
  labs(title = "Sigara Kullanımına Göre Maliyet Dağılımı")

# Sigara kullanan ve kullanmayan kişilerin sigorta maliyetlerinin dağılımı kutu grafiği ile görselleştiriliyor.
# Kutu grafiği incelendiğinde sigara içen bireylerin medyan sigorta maliyetinin,
# sigara içmeyen bireylere kıyasla oldukça yüksek olduğu açıkça görülmektedir.
# Ayrıca sigara içen grupta maliyet dağılımının daha geniş olduğu ve üst uçta çok sayıda yüksek maliyetli gözlem bulunduğu dikkat çekmektedir.
# Bu bulgu, sigara kullanımının maliyet seviyesini belirgin biçimde artırdığını ve maliyetlerdeki değişkenliği de yükselttiğini göstermektedir.

df$sex    <- as.factor(df$sex)
# sex değişkeni faktör tipine dönüştürülüyor. Bu kategorik değişkenlerin modelde doğru işlenmesini sağlar.
# Bu dönüşüm sonrasında model çıktısında sex ile ilgili katsayı, referans cinsiyete göre maliyet farkı şeklinde yorumlanacaktır.

df$smoker <- as.factor(df$smoker)
# smoker değişkeni faktör tipine dönüştürülüyor.
# Bu dönüşüm sonrasında model çıktısında smoker ile ilgili katsayı, referans gruba göre (genellikle "no") maliyet farkı şeklinde yorumlanacaktır.

df$region <- as.factor(df$region)
# region değişkeni faktör tipine dönüştürülüyor.
# Bu dönüşüm sonrasında model çıktısında region katsayıları, referans bölgeye göre maliyet farkları şeklinde yorumlanacaktır.

6. Veri Setini Bölme (Train/Test Split)

set.seed(145)
#Kodumuzu her çalıştırdığımızda aynı değerlerle çalışmak adına belli bir veri alanı sabitlemek için set.seed kullandık.

sampleindx <- sample(1:nrow(df), size = 0.80 * nrow(df))

trainset <- df[sampleindx, ]
testset  <- df[-sampleindx, ]

#Modeli değerlendirmek adına ikiye böldük.
#Verinin %80'ini modelin ilişkileri öğrenmesi için trainset olarak aldık.
#Verinin geri kalanını yani %20'sini ise testset olarak modelden çıkardık,bu verileri modeli test etmek için kullandık.
#Bu bölmedeki amacımız overfitting engellemek ve modelin performansını görmektir

cat("Train Set Boyutu:", nrow(trainset), "\n")
## Train Set Boyutu: 1070
cat("Test Set Boyutu :", nrow(testset), "\n")
## Test Set Boyutu : 268
# Ayrıştırmanın matematiksel olarak doğru olduğundan ve verilerin eksilmediğinden emin olmak için boyut kontrolleri yaptık.
# Çıktıda da görüldüğü üzere, veri setimiz beklenen oranlarda ayrıştırıldı.

7. Modelleme

model3 <- lm(charges ~ age + bmi + children + sex + smoker + region, data = trainset)

# Lineer regresyon modeli oluşturduk.Charges bağımlı değişken, diğerleri bağımsız değişkenler olarak kullanılıyor.
# Bu modelde yaş,cinsiyet,sigara içilmesi,çocuk sahibi olunması,vücut kütle indeksi 
# ve bölgeye göre sigorta fiyatlandırmasının nasıl değiştiğini modelliyoruz

summary(model3)
## 
## Call:
## lm(formula = charges ~ age + bmi + children + sex + smoker + 
##     region, data = trainset)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -11042.9  -2762.4   -847.2   1332.2  25944.7 
## 
## Coefficients:
##                   Estimate Std. Error t value Pr(>|t|)    
## (Intercept)     -12392.959   1057.582 -11.718  < 2e-16 ***
## age                263.996     12.802  20.622  < 2e-16 ***
## bmi                331.190     30.483  10.865  < 2e-16 ***
## children           469.982    149.108   3.152  0.00167 ** 
## sexmale            -75.009    357.784  -0.210  0.83398    
## smokeryes        23748.810    448.020  53.008  < 2e-16 ***
## regionnorthwest      9.984    507.536   0.020  0.98431    
## regionsoutheast   -645.795    510.743  -1.264  0.20636    
## regionsouthwest   -551.467    513.830  -1.073  0.28340    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 5832 on 1061 degrees of freedom
## Multiple R-squared:  0.7642, Adjusted R-squared:  0.7624 
## F-statistic: 429.9 on 8 and 1061 DF,  p-value: < 2.2e-16
#Modelin özetini bize gösterir.Bu özetteki değerlendirmeler ile hangi değişkenimizin kalacağını hangisinin çıkacağını kontrol ederiz.

#  ESTIMATE
# Estimate sütununda değişkenlerin harcamalar üzerindeki net etkisini gösterir.
# (Intercept):Tüm değişkenler 0 olduğunda beklenen baz maliyettir.
#  age: Kişinin yaşı 1 arttığında, sigorta maliyetinin ortalama ne kadar artacağını gösterir.(pozitif etki ,çok yüksek değildir ama vardır)
#  bmi:Vücut kitle indeksindeki 1 birimlik artışın maliyete yansımasıdır.(pozitif etki ,çok yüksek değildir ama vardır)
#  children:Çocuk sahibi olup olmamanın ortalama ne kadar artış sağladığını gösterir.(pozitif etkisi bulunmaktadır)
#  sex:Cinsiyetin sigorta maliyetine olan etkisini gösterir(negatif etki vardır ama çok düşüktür.)
#  smokeryes:Sigara içen birinin, içmeyene göre ortalama ne kadar maliyetinin fazla olduğunu gösterir.(pozitif etki vardır.en yüksek etki buradadır.)
#  region:Genel olarak bakıldığında regionın etkisi northwestte çok düşük pozitifken diğerlerinde negatif etki vardır.
#  Pozitif değerler harcamayı artırır, negatif değerler azaltır.

# Std.Error:
# Bu katsayının ne kadar güvenilir olduğunu test etme ölçüsüdür.
# Bu değer ne kadar küçükse, hesapladığımız 'Estimate' değeri o kadar kesindir.
# Regiondaki değerlerin yüksek olması estimate değerinin güvenilir olmadığını gösterir.

# t-value ve Pr(>|t|):
# Bir değişkenin modelde kalıp kalmadığına karar verdiğimiz değerler bu ikisidir.
# P-değeri (Pr) 0.05'ten küçük olan değişkenler istatistiksel olarak anlamlıdır.Yani sigorta maliyeti üzerinde gerçek bir etkisi vardır.
# Yüksek olan değerler ise modelden çıkarılıp model yeniden test edilecektir. 

#Residual standart error:
#Modelin yaptığı hataların standart sapmasıdır. 
#Tahminlerin gerçek değerlerden ortalama ne kadar saptığını gösterir.
#Düşük olması iyidir.Şuanki modelde çok yüksektir.

# Multiple R-squared ve Adjusted R-squared:
# Bağımsız değişkenin bağımlı değişkendeki değişimin yüzde kaçını açıkladığını gösterir.Bu değer 0 ile 1 arasındadır.
# Şuandaki değerimize göre model verinin %76'sını açıklar.%24 ise başka sebeplerden kaynaklanır.

# E) F-statistic:
# Modelin bir bütün olarak anlamlı olup olmadığını test eder
# Buradaki p-value < 0.05 ise, model anlamlıdır.

#Bazı değişkenleri çıkarıp daha iyi bir model elde etmeye çalışacağız.

model2 <- lm(charges ~ age + bmi + children + smoker + region, data = trainset)
summary(model2)
## 
## Call:
## lm(formula = charges ~ age + bmi + children + smoker + region, 
##     data = trainset)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -11077.9  -2768.1   -850.5   1310.9  25988.3 
## 
## Coefficients:
##                   Estimate Std. Error t value Pr(>|t|)    
## (Intercept)     -12420.604   1048.857 -11.842  < 2e-16 ***
## age                264.017     12.796  20.633  < 2e-16 ***
## bmi                330.899     30.438  10.871  < 2e-16 ***
## children           469.453    149.020   3.150  0.00168 ** 
## smokeryes        23743.745    447.166  53.098  < 2e-16 ***
## regionnorthwest      9.341    507.298   0.018  0.98531    
## regionsoutheast   -647.611    510.439  -1.269  0.20481    
## regionsouthwest   -552.465    513.577  -1.076  0.28230    
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 5829 on 1062 degrees of freedom
## Multiple R-squared:  0.7642, Adjusted R-squared:  0.7627 
## F-statistic: 491.7 on 7 and 1062 DF,  p-value: < 2.2e-16
#Cinsiyet değişkenini p değeri 0.05den yüksek olduğu için çıkardık.
#Residual standart error,f-statistic değerleri az miktarda düşüş gerçekleştirdi.
#Residual standart errorun düşmesi pozitif ,f-statistic değerinin düşmesi ise negatif bir etkidir.
#Adjusted error ise biraz yükseldi.
#Büyük bir değişim olmasa da model iyileşti.

model1 <- lm(charges ~ age + bmi + children + smoker, data = trainset)
summary(model1)
## 
## Call:
## lm(formula = charges ~ age + bmi + children + smoker, data = trainset)
## 
## Residuals:
##      Min       1Q   Median       3Q      Max 
## -11532.3  -2805.3   -866.8   1346.4  26414.1 
## 
## Coefficients:
##              Estimate Std. Error t value Pr(>|t|)    
## (Intercept) -12352.35    1008.81 -12.244  < 2e-16 ***
## age            264.41      12.77  20.708  < 2e-16 ***
## bmi            318.38      29.26  10.883  < 2e-16 ***
## children       472.45     148.90   3.173  0.00155 ** 
## smokeryes    23711.41     445.92  53.174  < 2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
## 
## Residual standard error: 5829 on 1065 degrees of freedom
## Multiple R-squared:  0.7636, Adjusted R-squared:  0.7627 
## F-statistic:   860 on 4 and 1065 DF,  p-value: < 2.2e-16
#Region değişkenini de modelden çıkardık.
#Geri kalan değerler genellikle sabit kalırken F istatistiği büyük bir yükselme gösterdi.
#Model anlamlılığı iyileşti.

#Modelden children çıkarıldığında F istatistiği artsa da adjusted 
#R squared azaldığından modelde değişim yapmadık.

8. Varsayım Kontrolleri

cat("\n--- VIF Değerleri ---\n")
## 
## --- VIF Değerleri ---
vif_values <- vif(model1)
print(vif_values)
##      age      bmi children   smoker 
## 1.012931 1.012092 1.002850 1.002084
if(any(vif_values > 5)) cat("UYARI: 5'ten büyük VIF değeri var!\n") else cat("Multicollinearity sorunu görünmüyor.\n")
## Multicollinearity sorunu görünmüyor.
# İlk olarak Multicollinearity sorununu kontrol ediyoruz. 
# Değişkenlerin birbirini tekrar edip etmediğine bakıyoruz. 
# Eğer bir değişkenin VIF değeri 5'in üzerindeyse, bu değişken modelde sorun yaratıyor demektir. 
# Bizim çıktımızda tüm değerler 5'in altında olduğu için, değişkenlerimiz birbirinden bağımsız ve temizdir.

residuals <- residuals(model1)
cat("\n--- Shapiro-Wilk Normallik Testi ---\n")
## 
## --- Shapiro-Wilk Normallik Testi ---
shapiro_res <- shapiro.test(residuals[1:5000]) # Büyük veride örneklem alarak test ettik
print(shapiro_res)
## 
##  Shapiro-Wilk normality test
## 
## data:  residuals[1:5000]
## W = 0.90431, p-value < 2.2e-16
# Modelin yaptığı hataların (kalıntıların) rastgele ve normal dağılıp dağılmadığını 'Shapiro-Wilk' ile test ediyoruz.
# H0 : Hatalar normal dağılır.
# H1 : Hatalar normal dağılmaz.
# Eğer p-değeri < 0.05 ise hatalar normal dağılmıyor demektir. 
# Büyük verisetlerinde p-değeri genelde küçük çıkar, bu yüzden Q-Q grafiği ile görsel teyit daha önemlidir.

cat("\n--- Breusch-Pagan Testi ---\n")
## 
## --- Breusch-Pagan Testi ---
print(bptest(model1))
## 
##  studentized Breusch-Pagan test
## 
## data:  model1
## BP = 111.57, df = 4, p-value < 2.2e-16
# Burada hataların varyansının sabit olup olmadığını ölçüyoruz.
# Eğer p-değeri < 0.05 ise 'Heteroscedasticity' (değişen varyans) sorunu vardır. 
# Yani modelimiz verinin bazı bölgelerinde tutarsız davranıyor olabilir.

cat("\n--- Durbin-Watson Testi ---\n")
## 
## --- Durbin-Watson Testi ---
print(dwtest(model1))
## 
##  Durbin-Watson test
## 
## data:  model1
## DW = 1.9525, p-value = 0.219
## alternative hypothesis: true autocorrelation is greater than 0
# Hataların birbiriyle ilişkili olup olmadığını yani Otokorelasyon test ediyoruz.
# Çıkan 'DW' değeri 0 ile 4 arasındadır. 
# Bizim hedefimiz bu değerin 2'ye yakın olmasıdır.
# 0-1.5 negatif otokorelasyon
# 1.5-2.5 otokorelasyon yok
# 2.5-4 pozitif otokorelasyon
# 2 civarı bir değer, hataların birbirinden bağımsız olduğunu, yani modelin bir önceki hatasının bir sonraki hatayı etkilemediğini gösterir.

par(mfrow = c(2, 2)) # Ekranı 4'e böl
plot(model1)         # 4 temel grafiği çiz

par(mfrow = c(1, 1)) # Ekranı normale döndür


# Bu kod çalıştığında ekrana 4 grafik gelir.
# 1. Residuals vs Fitted : Kırmızı çizginin dümdüz yatay olması gerekir. Eğrilik varsa, model verideki lineer olmayan yapıyı kaçırıyor demektir.
# 2. Normal Q-Q : Noktaların kesikli çizgi üzerinde ip gibi dizilmesi gerekir. Eğer uçlarda sapmalar varsa, hatalar normal dağılmıyordur.
# 3. Scale-Location: Varyansın sabitliğini gösterir. Noktaların rastgele dağılmasını bekleriz.
# 4. Residuals vs Leverage: Veri setinde modeli tek başına bozan 'baskın' (outlier) gözlemler olup olmadığını gösterir. Cook's distance çizgisi dışına taşan nokta varsa o veriyi incelemeliyiz.

9. Test Seti Performans Değerlendirmesi

predictions <- predict(model1, newdata = testset)

# Modelimizin eğitimini tamamladıktan sonra, kenara ayırdığımız ve 
# modelin daha önce hiç görmediği %20'lik 'Test Seti'ni devreye sokuyoruz.

rmse_val <- sqrt(mean((testset$charges - predictions)^2)) # Hataların karesinin ortalamasının karekökü
mae_val <- mean(abs(testset$charges - predictions))       # Mutlak hataların ortalaması

# 1. MAE (Ortalama Mutlak Hata): tahminimizin ne kadar saptığını gösterir.
#    Daha yorumlanabilir bir değerdir.
# 2. RMSE (Kök Ortalama Kare Hata): RMSE ile MAE arasındaki farka bakarak model değerlendirilir.

r2_val <- summary(lm(predictions ~ testset$charges))$r.squared

# Modelin eğitim setindeki başarısının, test setinde de devam edip etmediğini kontrol ediyoruz.
# Eğer Train R² yüksek, ama buradaki Test R² çok düşükse overfitting var demektir.
# Birbirine yakın olması, modelin sağlıklı olduğunu gösterir.

cat("\n--- Test Seti Performansı ---\n")
## 
## --- Test Seti Performansı ---
cat("RMSE (Risk Odaklı Hata):", round(rmse_val, 2), "\n")
## RMSE (Risk Odaklı Hata): 6946.34
cat("MAE  (Ortalama Sapma) :", round(mae_val, 2), "\n")
## MAE  (Ortalama Sapma) : 4723.49
cat("R²   (Açıklama Gücü)  :", round(r2_val, 4), "\n")
## R²   (Açıklama Gücü)  : 0.701
# Gördüğünüz gibi, modelimizin hiç görmediği verilerdeki R-Kare değeri (0.7) 
# eğitim setiyle tutarlı.
# MAE değerimize baktığımızda ise modelimiz, bir kişinin sağlık harcamasını tahmin ederken 
# ortalama 4723.49 birimlik bir yanılma payı ile çalışıyor. 
# Sigorta sektörü için bu sapma kabul edilebilir sınırlar içindedir.