1 Giriş

Bu çalışma, OLC733 kodlu dersin ilk iki haftasında ele alınan veri hazırlığı ve kayıp veri analizi konularını uygulamalı olarak pekiştirmek amacıyla hazırlanmıştır. Çalışmada kullanılan veri seti yapay zeka aracılığıyla üretilmiş olup bir lisenin farklı şubelerinde öğrenim gören 300 öğrenciye ait bilgileri içermektedir. Veri setinde öğrencilerin cinsiyeti, şubesi (A/B/C/D) ve sosyoekonomik düzeyi (düşük/orta/yüksek) kategorik değişkenler olarak yer almaktadır. Sürekli değişkenler olarak dikkat testi puanı (5-25), günlük ders çalışma süresi (dakika) ve dönem içi devamsızlık gün sayısı bulunmaktadır. Bağımlı değişken ise 0-100 arasında puanlanan dönem sonu başarı puanıdır.

2 Verinin Okunması ve Kontrol Edilmesi

# Paketlerin yüklenmesi
library(tidyverse)    # veri manipülasyonu ve görselleştirme
library(readxl)       # Excel dosyası okuma
library(psych)        # betimsel istatistikler
library(naniar)       # kayıp veri analizi
library(mice)         # çok atama (multiple imputation)
library(VIM)          # kayıp veri görselleştirme
library(car)          # regresyon varsayım testleri
library(nortest)      # normallik testleri
library(knitr)        # tablo formatlama
library(kableExtra)   # gelişmiş tablo formatlama

3 Verinin Okunması

df <- read_excel("kayip_veri_dataset.xlsx", sheet = "Veri") %>%
  rename(
    ogrenci_id        = `Öğrenci ID`,
    cinsiyet          = Cinsiyet,
    sube              = `Şube`,
    ses_duzeyi        = `SES Düzeyi`,
    dikkat_puani      = `Dikkat Puanı\n(5-25)`,
    calisma_suresi_dk = `Çalışma Süresi\n(dakika)`,
    devamsizlik_gun   = `Devamsızlık\n(gün)`,
    basari_puani      = `Başarı Puanı\n(0-100)`
  )

# Kategorik değişkenleri faktöre çevir
df <- df %>%
  mutate(
    cinsiyet   = factor(cinsiyet, levels = c("Kız", "Erkek")),
    sube       = factor(sube, levels = c("A", "B", "C", "D")),
    ses_duzeyi = factor(ses_duzeyi, levels = c("Düşük", "Orta", "Yüksek"),
                        ordered = TRUE)
  )
tibble(
  `Değişken`             = c("ogrenci_id", "cinsiyet", "sube", "ses_duzeyi",
                              "dikkat_puani", "calisma_suresi_dk", 
                              "devamsizlik_gun", "basari_puani"),
  `Tür`                  = c("Nominal", "Kategorik", "Kategorik", "Sıralı Kategorik",
                              "Sürekli", "Sürekli", "Sürekli", "Sürekli (BĞ)"),
  `Kategoriler / Aralık` = c("S001–S300", "Kız, Erkek", "A, B, C, D",
                              "Düşük, Orta, Yüksek",
                              "5 – 25", "15 – 240", "0 – 40", "0 – 100"),
  `Min`                  = c("—", "—", "—", "—", "5",  "15", "0",  "0"),
  `Max`                  = c("—", "—", "—", "—", "25", "240", "40", "100"),
  `Açıklama`             = c("Kimlik kodu", "Öğrenci cinsiyeti", "Sınıf şubesi",
                              "Sosyoekonomik düzey", "Dikkat testi puanı",
                              "Günlük çalışma süresi (dk)",
                              "Devamsızlık (gün)", "Dönem sonu başarı puanı")
) %>%
  kable(caption = "Tablo 1. Veri Setindeki Değişkenlere İlişkin Bilgiler",
        align = c("l","l","c","c","c","l")) %>%
  kable_styling(
    bootstrap_options = c("hover", "condensed", "bordered"),
    full_width = TRUE,
    font_size  = 13
  ) %>%
  row_spec(0, bold = TRUE, color = "white", background = "#2E4057") %>%
  row_spec(1:8, color = "#1a1e2e", background = "#d6e4f0") %>%
  row_spec(c(2,4,6,8), background = "#eaf4fb") %>%
  row_spec(5:8, bold = TRUE) %>%
  column_spec(1, bold = TRUE) %>%
 footnote(general = "BĞ: Bağımlı Değişken. — : Kategorik değişkenler için geçerli değil.",
         general_title = "Not:")
Tablo 1. Veri Setindeki Değişkenlere İlişkin Bilgiler
Değişken Tür Kategoriler / Aralık Min Max Açıklama
ogrenci_id Nominal S001–S300 Kimlik kodu
cinsiyet Kategorik Kız, Erkek Öğrenci cinsiyeti
sube Kategorik A, B, C, D Sınıf şubesi
ses_duzeyi Sıralı Kategorik Düşük, Orta, Yüksek Sosyoekonomik düzey
dikkat_puani Sürekli 5 – 25 5 25 Dikkat testi puanı
calisma_suresi_dk Sürekli 15 – 240 15 240 Günlük çalışma süresi (dk)
devamsizlik_gun Sürekli 0 – 40 0 40 Devamsızlık (gün)
basari_puani Sürekli (BĞ) 0 – 100 0 100 Dönem sonu başarı puanı
Not:
BĞ: Bağımlı Değişken. — : Kategorik değişkenler için geçerli değil.

4 Uç Değerlerin Kontrolü

4.1 Z Puanları İle Kontrol

surekli <- c("dikkat_puani", "calisma_suresi_dk", "devamsizlik_gun", "basari_puani")

z_df <- df %>%
  mutate(across(all_of(surekli), ~round((. - mean(.)) / sd(.), 2),
                .names = "z_{.col}"))

uc_deger_z <- z_df %>%
  filter(if_any(starts_with("z_"), ~ abs(.) > 3.29)) %>%
  select(ogrenci_id,
         z_dikkat      = z_dikkat_puani,
         z_calisma     = z_calisma_suresi_dk,
         z_devamsizlik = z_devamsizlik_gun,
         z_basari      = z_basari_puani) %>%
  mutate(across(starts_with("z_"), ~ ifelse(abs(.) > 3.29, ., NA))) %>%
  mutate(across(starts_with("z_"), ~ ifelse(is.na(.), "", as.character(.))))

uc_deger_z %>%
  kable(caption   = "Tablo 2. z Puanı ±3.29 Eşiğini Aşan Gözlemler",
        col.names = c("Öğrenci ID", "z Dikkat", "z Çalışma", "z Devamsızlık", "z Başarı")) %>%
  kable_styling(bootstrap_options = c("hover", "condensed", "bordered"),
                full_width = FALSE, font_size = 13) %>%
  row_spec(0, bold = TRUE, color = "white", background = "#2E4057") %>%
  row_spec(1:nrow(uc_deger_z), color = "#1a1e2e", background = "#fde8e8") %>%
  column_spec(1, bold = TRUE)
Tablo 2. z Puanı ±3.29 Eşiğini Aşan Gözlemler
Öğrenci ID z Dikkat z Çalışma z Devamsızlık z Başarı
S150 -3.45
S180 -3.34
S193 -3.48
S211 -3.41
S227 6.17
S243 -3.41

Tablo incelendiğinde 6 öğrenci için puanların uç değer olduğu görülmektedir. Bunlardan birisi dikkat, birisi devamsızlık ve diğerleri başarı puanlarında yer almaklatadır. Söz konusu uç değerler silinerek bir sonraki adımda BOXPLOT aracılığıyla uç değer konrolü yapılacaktır. Uç değerler silinirken z puanı olarak 3.29 değeri esas alınmıştır.

# z puani ±3.29 esigini asan gozlemler cikariliyor
silinecek_id <- z_df %>%
  filter(if_any(starts_with("z_"), ~ abs(.) > 3.29)) %>%
  pull(ogrenci_id)

cat("Cikarilan gozlem sayisi:", length(silinecek_id), "\n")
## Cikarilan gozlem sayisi: 6
cat("Cikarilan ogrenciler:", paste(silinecek_id, collapse = ", "), "\n")
## Cikarilan ogrenciler: S150, S180, S193, S211, S227, S243
veri_uc_degersiz1 <- df %>%
  filter(!ogrenci_id %in% silinecek_id)

cat("Temiz veri seti boyutu:", nrow(veri_uc_degersiz1), "gozlem\n")
## Temiz veri seti boyutu: 294 gozlem

4.2 Boxplot İle Kontrol

veri_uc_degersiz1 %>%
  select(all_of(surekli)) %>%
  pivot_longer(everything(), names_to = "degisken", values_to = "deger") %>%
  mutate(degisken = case_when(
    degisken == "dikkat_puani"      ~ "Dikkat Puanı",
    degisken == "calisma_suresi_dk" ~ "Çalışma Süresi (dk)",
    degisken == "devamsizlik_gun"   ~ "Devamsızlık (gün)",
    degisken == "basari_puani"      ~ "Başarı Puanı"
  )) %>%
  ggplot(aes(x = degisken, y = deger, fill = degisken)) +
  geom_boxplot(
    outlier.shape  = 21,
    outlier.fill   = "#e63946",
    outlier.color  = "white",
    outlier.size   = 3,
    outlier.stroke = 0.5,
    alpha          = 0.85,
    width          = 0.5,
    linewidth      = 0.6
  ) +
  geom_jitter(width = 0.12, alpha = 0.08, color = "white", size = 0.8) +
  facet_wrap(~ degisken, scales = "free", ncol = 4) +
  scale_fill_manual(values = c("#2E4057", "#048A81", "#5e81ac", "#7eb8d4")) +
  theme_minimal(base_size = 12) +
  theme(
    legend.position   = "none",
    strip.text        = element_text(face = "bold", size = 11, color = "#e8e8e8"),
    strip.background  = element_rect(fill = "#2E4057", color = NA),
    axis.text         = element_text(color = "#cccccc"),
    axis.title        = element_blank(),
    panel.grid.major  = element_line(color = "#333a50", linewidth = 0.4),
    panel.grid.minor  = element_blank(),
    panel.background  = element_rect(fill = "#1a1e2e", color = NA),
    plot.background   = element_rect(fill = "#1a1e2e", color = NA),
    plot.title        = element_text(color = "#7eb8d4", face = "bold",
                                     size = 13, hjust = 0.5, margin = margin(b = 15)),
    plot.margin       = margin(15, 15, 15, 15)
  ) +
  labs(title = "Şekil 1. Sürekli Değişkenlere Ait Boxplot Grafikleri")

Grafik incelendiğinde 4 başarı puanında, 1 devamsızlıkta ve 1 dikkat pauanında uç değer olduğu görülmektedir. Ancak başarı pauanındaki ve devamsızlıkla ilgili değerler araştırmacının veri topladığı örneklem açısından normal değerler olarak kabul edilmektedir. Dikkat puanındaki en düşük değer ise gerçek bir uç değerdir. Çünkü dikkat puanının alabileceği en düşük değerin 5 olduğu daha önce ifade edilmiştir. Öğrenci sayısı yapılacak analizler için yeterli olduğundan dikkat puanı 5’ten küçük olan öğrenci de veri setinden çıkarılarak analizlere devam edilecektir.

veri_uc_degersiz2 <- veri_uc_degersiz1 %>%
  filter(dikkat_puani >= 5)

cat("Cikarilan gozlem sayisi:", nrow(veri_uc_degersiz1) - nrow(veri_uc_degersiz2), "\n")
## Cikarilan gozlem sayisi: 1
cat("Temiz veri seti boyutu:", nrow(veri_uc_degersiz2), "gozlem\n")
## Temiz veri seti boyutu: 293 gozlem

4.3 Çok Değişkenli Uç Değer Analizi

surekli <- c("dikkat_puani", "calisma_suresi_dk", "devamsizlik_gun", "basari_puani")

df_s <- veri_uc_degersiz2 %>% select(all_of(surekli))

mah_dist <- mahalanobis(df_s,
                        center = colMeans(df_s),
                        cov    = cov(df_s))

mah_p <- pchisq(mah_dist, df = ncol(df_s), lower.tail = FALSE)

mah_sonuc <- veri_uc_degersiz2 %>%
  mutate(Mahalanobis = round(mah_dist, 3),
         p_degeri    = round(mah_p, 4)) %>%
  filter(p_degeri < 0.001) %>%
  select(ogrenci_id, all_of(surekli), Mahalanobis, p_degeri) %>%
  arrange(p_degeri) %>% 
  mutate(p_degeri = ifelse(p_degeri < 0.001, "< .001", as.character(p_degeri))) 

cat("Potansiyel Çok Değişkenli Uç Değer Sayısı:", nrow(mah_sonuc), "\n")
## Potansiyel Çok Değişkenli Uç Değer Sayısı: 3
mah_sonuc %>%
  kable(caption   = "Tablo 3. Mahalanobis Uzaklığı p < .001 Olan Gozlemler",
        col.names = c("Öğrenci ID", "Dikkat", "Calışma (dk)",
                      "Devamsızlık", "Başarı", "Mahalanobis", "p")) %>%
  kable_styling(bootstrap_options = c("hover", "condensed", "bordered"),
                full_width = FALSE, font_size = 13) %>%
  row_spec(0, bold = TRUE, color = "white", background = "#2E4057") %>%
  row_spec(1:nrow(mah_sonuc), color = "#1a1e2e", background = "#fde8e8") %>%
  column_spec(1, bold = TRUE)
Tablo 3. Mahalanobis Uzaklığı p < .001 Olan Gozlemler
Öğrenci ID Dikkat Calışma (dk) Devamsızlık Başarı Mahalanobis p
S007 12 92 7 98 33.674 < .001
S253 15 98 12 98 27.645 < .001
S259 16 141 6 100 18.685 < .001

Tablo incelendiğinde 3 öğrenciye ait paunlarda çok değişkenli uç değer olma olasılığı tespit edilmiştir. Bu öğrenciler veri setinden çıkarılarak araştırmaya devam edilmiştir. Çıkarılan 3 öğrenciden sonra 290 gözlem kalmıştır.

silinecek_mah <- mah_sonuc %>% pull(ogrenci_id)

veri_uc_degersiz3 <- veri_uc_degersiz2 %>%
  filter(!ogrenci_id %in% silinecek_mah)

cat("Cikarilan gozlem sayisi:", length(silinecek_mah), "\n")
## Cikarilan gozlem sayisi: 3
cat("Temiz veri seti boyutu:", nrow(veri_uc_degersiz3), "gozlem\n")
## Temiz veri seti boyutu: 290 gozlem

4.4 Kategorik Değişkenlerde Beklenmeyen Değer Varlığının Kontrolü

kategorik <- c("cinsiyet", "sube", "ses_duzeyi")
basliklar  <- c("Cinsiyet", "Şube", "SES Düzeyi")

tablo_listesi <- lapply(seq_along(kategorik), function(i) {
  x <- kategorik[i]
  df_tablo <- as.data.frame(table(veri_uc_degersiz3[[x]], useNA = "always"))
  colnames(df_tablo) <- c("Kategori", "Frekans")
  df_tablo$Kategori  <- as.character(df_tablo$Kategori)
  df_tablo$Kategori[is.na(df_tablo$Kategori)] <- "Kayıp (NA)"
  df_tablo$Yüzde     <- paste0(round(df_tablo$Frekans / 
                                sum(df_tablo$Frekans[df_tablo$Kategori != "Kayıp (NA)"]) * 100, 1), "%")
  df_tablo$Değişken  <- basliklar[i]
  df_tablo
})

tablo_birlesik <- do.call(rbind, tablo_listesi)

tablo_birlesik %>%
  select(Değişken, Kategori, Frekans, Yüzde) %>%
  kable(caption = "Tablo 4. Kategorik Değişkenlerin Dağılımı",
        align   = c("l", "l", "c", "c")) %>%
  kable_styling(bootstrap_options = c("hover", "condensed", "bordered"),
                full_width = FALSE, font_size = 13) %>%
  row_spec(0, bold = TRUE, color = "white", background = "#2E4057") %>%
  row_spec(1:nrow(tablo_birlesik), color = "#1a1e2e", background = "#d6e4f0") %>%
  row_spec(which(tablo_birlesik$Kategori == "Kayıp (NA)"),
           color = "red", background = "#fde8e8") %>%
  collapse_rows(columns = 1, valign = "middle") %>%
  column_spec(1, bold = TRUE)
Tablo 4. Kategorik Değişkenlerin Dağılımı
Değişken Kategori Frekans Yüzde
Cinsiyet Kız 150 51.7%
Erkek 140 48.3%
Kayıp (NA) 0 0%
Şube A 73 25.2%
B 67 23.1%
C 66 22.8%
D 84 29%
Kayıp (NA) 0 0%
SES Düzeyi Düşük 99 34.1%
Orta 130 44.8%
Yüksek 61 21%
Kayıp (NA) 0 0%

Tablo incelendiğinde kategorik değişkenler için herhangi bir kayıp veri veya uç değer olmadığı görülmüştür.

5 Veri Setinin Fotoğrafı

5.1 Öğrencilerin Alt Gruplardaki Dağılımı

library(plotly)

df_cinsiyet <- veri_uc_degersiz3 %>%
  count(cinsiyet) %>%
  mutate(oran = round(n / sum(n) * 100, 1))

df_sube <- veri_uc_degersiz3 %>%
  count(sube) %>%
  mutate(oran = round(n / sum(n) * 100, 1))

df_ses <- veri_uc_degersiz3 %>%
  count(ses_duzeyi) %>%
  mutate(oran = round(n / sum(n) * 100, 1))

plot_ly() %>%
  add_pie(data = df_cinsiyet,
          labels = ~cinsiyet, values = ~n,
          hole = 0.5, domain = list(x = c(0, 0.3), y = c(0, 1)),
          marker = list(colors = c("#048A81", "#5e81ac"),
                        line = list(color = "#1a1e2e", width = 2)),
          textinfo = "label+percent",
          textposition = "inside",
          hovertemplate = "<b>%{label}</b><br>Frekans: %{value}<br>Oran: %{percent}<extra></extra>",
          showlegend = FALSE,
          name = "Cinsiyet") %>%
  add_pie(data = df_sube,
          labels = ~sube, values = ~n,
          hole = 0.5, domain = list(x = c(0.35, 0.65), y = c(0, 1)),
          marker = list(colors = c("#2E4057", "#048A81", "#5e81ac", "#7eb8d4"),
                        line = list(color = "#1a1e2e", width = 2)),
          textinfo = "label+percent",
          textposition = "inside",
          hovertemplate = "<b>%{label}</b><br>Frekans: %{value}<br>Oran: %{percent}<extra></extra>",
          showlegend = FALSE,
          name = "Şube") %>%
  add_pie(data = df_ses,
          labels = ~ses_duzeyi, values = ~n,
          hole = 0.5, domain = list(x = c(0.7, 1), y = c(0, 1)),
          marker = list(colors = c("#e63946", "#f4a261", "#2a9d8f"),
                        line = list(color = "#1a1e2e", width = 2)),
          textinfo = "label+percent",
          textposition = "inside",
          hovertemplate = "<b>%{label}</b><br>Frekans: %{value}<br>Oran: %{percent}<extra></extra>",
          showlegend = FALSE,
          name = "SES Düzeyi") %>%
  layout(
    title         = list(text = "Şekil 2. Kategorik Değişkenlerin Dağılımı",
                         font = list(color = "#7eb8d4", size = 15)),
    paper_bgcolor = "#1a1e2e",
    plot_bgcolor  = "#1a1e2e",
    font          = list(color = "#e8e8e8", size = 12),
    showlegend    = FALSE
  )

Şekil 2 incelendiğinde veri setinin cinsiyet açısından dengeli bir dağılım sergilediği görülmektedir; öğrencilerin %51,7’si kız, %48,3’ü erkektir. Şube dağılımı da birbirine oldukça yakın olmakla birlikte D şubesinin (%29) diğerlerine kıyasla hafif daha kalabalık olduğu dikkat çekmektedir. Sosyoekonomik düzey açısından ise orta SES grubunun büyük çoğunluğu (%44,8) oluşturduğu, bunu düşük (%34,1) ve yüksek (%21,0) SES gruplarının izlediği görülmektedir.

5.2 Sürekli Değişkenlerin İncelenmesi

library(plotly)

surekli_etiket <- c("Dikkat Puanı", "Çalışma Süresi (dk)", "Devamsızlık (gün)", "Başarı Puanı")
renkler        <- c("#f4a261", "#e76f51", "#e9c46a", "#e63946")

x_pos <- c(0.040, 0.375, 0.750, 0.950)

grafik_listesi <- lapply(seq_along(surekli), function(i) {
  d <- veri_uc_degersiz3[[surekli[i]]]
  plot_ly() %>%
    add_trace(
      type      = "violin",
      y         = round(d, 2),
      name      = surekli_etiket[i],
      box       = list(visible = TRUE),
      meanline  = list(visible = TRUE, color = "white", width = 2),
      points    = "all",
      jitter    = 0.35,
      pointpos  = 0,
      marker    = list(size = 3, opacity = 0.35, color = renkler[i]),
      line      = list(color = renkler[i]),
      fillcolor = renkler[i],
      opacity   = 0.75,
      hovertemplate = paste0(
        "<b>", surekli_etiket[i], "</b><br>",
        "Değer: %{y:.2f}<br>",
        "Ort: ", round(mean(d, na.rm=TRUE), 2), "<br>",
        "SS: ",  round(sd(d,   na.rm=TRUE), 2), "<br>",
        "Min: ", round(min(d,  na.rm=TRUE), 2), "<br>",
        "Maks: ",round(max(d,  na.rm=TRUE), 2),
        "<extra></extra>"
      ),
      showlegend = FALSE
    ) %>%
    layout(
      yaxis         = list(gridcolor = "#333a50", tickfont = list(color = "#e8e8e8"), tickformat = ".2f"),
      xaxis         = list(showticklabels = FALSE),
      paper_bgcolor = "#1a1e2e",
      plot_bgcolor  = "#1a1e2e"
    )
})

annotations <- lapply(seq_along(surekli), function(i) {
  list(
    x = x_pos[i], y = -0.08,
    xref = "paper", yref = "paper",
    text = paste0("<b>", surekli_etiket[i], "</b>"),
    showarrow = FALSE,
    font = list(color = "#e8e8e8", size = 11)
  )
})

subplot(grafik_listesi[[1]], grafik_listesi[[2]],
        grafik_listesi[[3]], grafik_listesi[[4]],
        nrows = 1, shareY = FALSE, margin = 0.06) %>%
  layout(
    title         = list(text = "Şekil 3. Sürekli Değişkenlerin Dağılımı",
                         font = list(color = "#7eb8d4", size = 15)),
    paper_bgcolor = "#1a1e2e",
    plot_bgcolor  = "#1a1e2e",
    font          = list(color = "#e8e8e8"),
    showlegend    = FALSE,
    margin        = list(b = 80),
    annotations   = annotations
  )

Şekil 3 incelendiğinde sürekli değişkenlerin birbirinden oldukça farklı dağılım örüntüleri sergilediği görülmektedir. Dikkat puanı 5-25 aralığında görece simetrik ve dar bir dağılım gösterirken çalışma süresi daha geniş bir yayılım sergilemekte ve hafif sağa çarpık bir yapıya işaret etmektedir. Devamsızlık değişkeni belirgin biçimde sağa çarpık görünmekte; düşük devamsızlık değerlerinde yoğunlaşma olduğu, buna karşın yüksek devamsızlık gösteren az sayıda öğrencinin dağılımı uzattığı anlaşılmaktadır. Başarı puanı ise diğerlerine kıyasla daha geniş bir aralıkta ve yaklaşık simetrik bir dağılım sergilemektedir. Tüm değişkenlerde violin genişliğinin orta değerlerde belirgin biçimde arttığı, uç noktalarda ise daraldığı gözlemlenmektedir.

6 Normal Dağılım Testleri

6.1 Çarpıklık ve Basıklık Değerleri ile Kontrol

library(psych)

normallik_tablo <- describe(veri_uc_degersiz3[, surekli]) %>%
  as.data.frame() %>%
  select(n, mean, sd, min, max, skew, kurtosis) %>%
  round(3) %>%
  mutate(
    carpiklik_yorum = ifelse(abs(skew) <= 1.0, "Normal", "Anormal"),
    basiklik_yorum  = ifelse(abs(kurtosis) <= 1.0, "Normal", "Anormal")
  )

rownames(normallik_tablo) <- c("Dikkat Puanı", "Çalışma Süresi (dk)", "Devamsızlık (gün)", "Başarı Puanı")

normallik_tablo %>%
  kable(
    caption   = "Tablo 5. Normallik Kontrolü: Çarpıklık ve Basıklık Değerleri",
    col.names = c("n", "Ortalama", "SS", "Min", "Maks", "Çarpıklık", "Basıklık",
                  "Çarpıklık Yorum", "Basıklık Yorum")
  ) %>%
  kable_styling(bootstrap_options = c("hover", "condensed", "bordered"),
                full_width = TRUE, font_size = 13) %>%
  row_spec(0, bold = TRUE, color = "white", background = "#2E4057") %>%
  row_spec(1:4, color = "#1a1e2e", background = "#d6e4f0") %>%
  column_spec(8, color = ifelse(normallik_tablo$carpiklik_yorum == "Anormal", "red", "darkgreen"),
              bold = TRUE) %>%
  column_spec(9, color = ifelse(normallik_tablo$basiklik_yorum == "Anormal", "red", "darkgreen"),
              bold = TRUE) %>%
  footnote(general = "Çarpıklık ve basıklık değerlerinin -1.0 ile +1.0 arasında olması normal dağılıma yakınlığın göstergesidir.",
           general_title = "Not:")
Tablo 5. Normallik Kontrolü: Çarpıklık ve Basıklık Değerleri
n Ortalama SS Min Maks Çarpıklık Basıklık Çarpıklık Yorum Basıklık Yorum
Dikkat Puanı 290 16.310 3.991 7.0 25.0 0.032 -0.365 Normal Normal
Çalışma Süresi (dk) 290 99.966 37.156 5.0 191.0 0.014 -0.304 Normal Normal
Devamsızlık (gün) 290 7.376 4.650 0.0 20.0 0.242 -0.626 Normal Normal
Başarı Puanı 290 55.131 13.221 17.8 94.7 0.098 0.017 Normal Normal
Not:
Çarpıklık ve basıklık değerlerinin -1.0 ile +1.0 arasında olması normal dağılıma yakınlığın göstergesidir.

Tablo 5 incelendiğinde dört sürekli değişkenin tamamında çarpıklık ve basıklık değerlerinin -1.0 ile +1.0 arasında kaldığı görülmektedir. Bu bulgu, tüm değişkenlerin normal dağılıma yakın bir yapı sergilediğine işaret etmektedir. Çarpıklık değerleri sıfıra oldukça yakın olmakla birlikte devamsızlık değişkeni (0.242) hafif sağa çarpık bir eğilim sergilemektedir; bu durum daha önce violin grafiğinde de gözlemlenmiş ve uç değer temizliği sonrasında büyük ölçüde düzelmiştir. Basıklık değerleri ise tüm değişkenlerde negatif yönde seyretmekte olup dağılımların normal eğriye kıyasla biraz daha yassı olduğunu göstermektedir.

6.2 Görsel Kontrol

library(ggpubr)
library(patchwork)

renkler <- c("#f4a261", "#e76f51", "#e9c46a", "#e63946")

qq_listesi <- lapply(seq_along(surekli), function(i) {
  ggqqplot(veri_uc_degersiz3, x = surekli[i],
           color = renkler[i],
           ggtheme = theme_minimal()) +
    labs(title = surekli_etiket[i]) +
    theme(
      plot.title       = element_text(color = "#7eb8d4", face = "bold",
                                      size = 11, hjust = 0.5),
      panel.background = element_rect(fill = "#1a1e2e", color = NA),
      plot.background  = element_rect(fill = "#1a1e2e", color = NA),
      panel.grid.major = element_line(color = "#333a50", linewidth = 0.4),
      panel.grid.minor = element_blank(),
      axis.text        = element_text(color = "#e8e8e8"),
      axis.title       = element_text(color = "#e8e8e8")
    )
})

(qq_listesi[[1]] | qq_listesi[[2]]) / (qq_listesi[[3]] | qq_listesi[[4]]) +
  plot_annotation(
    title   = "Şekil 4. Q-Q Grafikleri",
    theme   = theme(
      plot.title      = element_text(color = "#7eb8d4", face = "bold",
                                     size = 14, hjust = 0.5),
      plot.background = element_rect(fill = "#1a1e2e", color = NA)
    )
  )

Şekil 4’te yer alan Q-Q grafikleri incelendiğinde tablo bulgularını büyük ölçüde desteklediği görülmektedir. Dikkat puanı ve başarı puanına ait noktaların referans doğrusuna oldukça yakın seyrettiği ve güven bandı içinde kaldığı dikkat çekmektedir; bu değişkenler için normallik varsayımının karşılandığı söylenebilir. Çalışma süresi değişkeninde noktalar orta değerlerde referans çizgisini takip ederken uç noktalarda hafif sapmalar gözlemlenmektedir. Devamsızlık değişkeninde ise sol uçta daha belirgin bir sapma söz konusudur; bu durum dağılımın sağa çarpık yapısıyla örtüşmekte ve çarpıklık katsayısıyla tutarlılık göstermektedir.

7 Doğrusallık Kontrolü

library(GGally)

veri_uc_degersiz3 %>%
  select(all_of(surekli)) %>%
  ggpairs(
    columnLabels = surekli_etiket,
    upper = list(continuous = wrap("cor", size = 4, color = "#7eb8d4")),
    lower = list(continuous = wrap("smooth", alpha = 0.3,
                                   color = "#f4a261", se = TRUE)),
    diag  = list(continuous = wrap("densityDiag",
                                   fill = "#048A81", alpha = 0.6))
  ) +
  theme_minimal() +
  theme(
    strip.text       = element_text(color = "#7eb8d4", face = "bold", size = 10),
    panel.background = element_rect(fill = "#1a1e2e", color = NA),
    plot.background  = element_rect(fill = "#1a1e2e", color = NA),
    panel.grid.major = element_blank(),
    panel.grid.minor = element_blank(),
    axis.text        = element_text(color = "#e8e8e8", size = 7),
    strip.background = element_rect(fill = "#2E4057", color = NA)
  ) +
  labs(title = "Şekil 5. Sürekli Değişkenler Arası Saçılım Matrisi")

Şekil 5’te yer alan saçılım matrisi incelendiğinde sürekli değişkenlerin doğrusallık varsayımını büyük ölçüde karşıladığı görülmektedir. Köşegen üzerindeki yoğunluk grafikleri normallik bulgularıyla tutarlı bir dağılım sergilemektedir. Alt üçgendeki saçılım grafikleri ve regresyon çizgileri incelendiğinde değişkenler arasındaki ilişkilerin doğrusal bir örüntü izlediği dikkat çekmektedir. Üst üçgendeki korelasyon katsayıları bu ilişkilerin yönü ve büyüklüğü hakkında önemli bilgiler sunmaktadır. Dikkat puanı ile başarı puanı arasında güçlü pozitif bir ilişki (r = .678, p < .001) gözlemlenirken çalışma süresi ile başarı puanı arasında orta düzeyde pozitif bir ilişki (r = .327, p < .001) bulunmaktadır. Devamsızlık ile başarı puanı arasında ise beklenen yönde zayıf negatif bir ilişki (r = -.153, p < .01) tespit edilmiştir.

8 Çoklu Bağlantı

library(car)

model_vif <- lm(basari_puani ~ dikkat_puani + calisma_suresi_dk + devamsizlik_gun +
                  cinsiyet + sube + ses_duzeyi,
                data = veri_uc_degersiz3)

vif_tablo <- vif(model_vif) %>%
  as.data.frame() %>%
  rownames_to_column("Değişken") %>%
  mutate(
    Tolerans = round(1 / GVIF, 3),
    VIF      = round(GVIF, 3),
    Yorum    = ifelse(GVIF >= 10, "Sorunlu", ifelse(GVIF >= 5, "Dikkat", "Kabul Edilebilir"))
  ) %>%
  select(Değişken, Tolerans, VIF, Yorum)

vif_tablo$Değişken <- c("Dikkat Puanı", "Çalışma Süresi (dk)",
                         "Devamsızlık (gün)", "Cinsiyet", "Şube", "SES Düzeyi")

vif_tablo %>%
  kable(caption = "Tablo 6. Çoklu Bağlantı: Tolerans ve VIF Değerleri",
        align   = c("l", "c", "c", "c")) %>%
  kable_styling(bootstrap_options = c("hover", "condensed", "bordered"),
                full_width = FALSE, font_size = 13) %>%
  row_spec(0, bold = TRUE, color = "white", background = "#2E4057") %>%
  row_spec(1:nrow(vif_tablo), color = "#1a1e2e", background = "#d6e4f0") %>%
  column_spec(4, bold = TRUE,
              color = ifelse(vif_tablo$Yorum == "Sorunlu", "red",
                      ifelse(vif_tablo$Yorum == "Dikkat", "orange", "darkgreen"))) %>%
  footnote(general = "VIF > 10 çoklu bağlantı sorunu, VIF > 5 dikkat gerektirir, VIF < 10 kabul edilebilir.",
           general_title = "Not:")
Tablo 6. Çoklu Bağlantı: Tolerans ve VIF Değerleri
Değişken Tolerans VIF Yorum
Dikkat Puanı 0.897 1.115 Kabul Edilebilir
Çalışma Süresi (dk) 0.952 1.051 Kabul Edilebilir
Devamsızlık (gün) 0.988 1.012 Kabul Edilebilir
Cinsiyet 0.985 1.016 Kabul Edilebilir
Şube 0.972 1.029 Kabul Edilebilir
SES Düzeyi 0.866 1.155 Kabul Edilebilir
Not:
VIF > 10 çoklu bağlantı sorunu, VIF > 5 dikkat gerektirir, VIF < 10 kabul edilebilir.

Tablo 6 incelendiğinde tüm değişkenler için VIF değerlerinin 1.0 ile 1.2 arasında olduğu ve tolerans değerlerinin 0.85’in üzerinde kaldığı görülmektedir. Bu bulgular modelde çoklu bağlantı sorununun bulunmadığına işaret etmektedir.

library(corrplot)

cor_matrix <- veri_uc_degersiz3 %>%
  select(all_of(surekli)) %>%
  cor(use = "complete.obs")

rownames(cor_matrix) <- surekli_etiket
colnames(cor_matrix) <- surekli_etiket

corrplot(cor_matrix,
         method   = "color",
         type     = "upper",
         order    = "hclust",
         addCoef.col = "#e8e8e8",
         number.cex  = 0.9,
         tl.col   = "black",
         tl.srt   = 45,
         tl.cex   = 0.9,
         col      = colorRampPalette(c("#e63946", "#1a1e2e", "#048A81"))(200),
         bg       = "#1a1e2e",
         mar      = c(0, 0, 1, 0),
         title    = "Şekil 6. Korelasyon Matrisi")

Şekil 6 incelendiğinde değişkenler arasındaki korelasyon örüntüsünün analiz bulgularıyla tutarlı olduğu görülmektedir. Dikkat puanı ile başarı puanı arasındaki güçlü pozitif ilişki (r = .68) en belirgin bulgu olarak öne çıkmaktadır. Çalışma süresi ile başarı puanı arasında orta düzeyde pozitif (r = .33), devamsızlık ile başarı puanı arasında ise beklenen yönde negatif bir ilişki (r = -.15) gözlemlenmektedir. Bağımsız değişkenler arasındaki korelasyon değerlerinin düşük olması çoklu bağlantı bulgularıyla örtüşmekte ve regresyon modelinin güvenilirliğini desteklemektedir.

9 Regresyon Analizi (Tam Veri)

library(broom)

model <- lm(basari_puani ~ dikkat_puani + calisma_suresi_dk + 
              devamsizlik_gun + cinsiyet + sube + ses_duzeyi,
            data = veri_uc_degersiz3)
library(broom)

model_tidy <- tidy(model) %>%
  filter(term != "ses_duzeyi.Q") %>%
  mutate(
    term = case_when(
      term == "(Intercept)"       ~ "Sabit",
      term == "dikkat_puani"      ~ "Dikkat Puanı",
      term == "calisma_suresi_dk" ~ "Çalışma Süresi (dk)",
      term == "devamsizlik_gun"   ~ "Devamsızlık (gün)",
      term == "cinsiyetErkek"     ~ "Erkek (ref: Kız)",
      term == "subeB"             ~ "Şube B (ref: A)",
      term == "subeC"             ~ "Şube C (ref: A)",
      term == "subeD"             ~ "Şube D (ref: A)",
      term == "ses_duzeyi.L"      ~ "SES Düzeyi",
      TRUE ~ term
    ),
    estimate  = round(estimate, 3),
    std.error = round(std.error, 3),
    statistic = round(statistic, 3),
    p.value   = ifelse(p.value < .001, "< .001", as.character(round(p.value, 3))),
    anlamli   = p.value == "< .001" | (!is.na(suppressWarnings(as.numeric(p.value))) &
                                        as.numeric(p.value) < .05)
  )

model_fit <- glance(model) %>%
  mutate(across(where(is.numeric), ~round(., 3)))

model_tidy %>%
  select(term, estimate, std.error, statistic, p.value) %>%
  kable(
    caption   = "Tablo 7. Çoklu Regresyon Analizi Sonuçları",
    col.names = c("Değişken", "B", "Std. Hata", "t", "p"),
    align     = c("l", "c", "c", "c", "c")
  ) %>%
  kable_styling(bootstrap_options = c("hover", "condensed", "bordered"),
                full_width = TRUE, font_size = 13) %>%
  row_spec(0, bold = TRUE, color = "white", background = "#2E4057") %>%
  row_spec(1:nrow(model_tidy), color = "#1a1e2e", background = "#d6e4f0") %>%
  row_spec(which(model_tidy$anlamli), background = "#c8e6c9", bold = TRUE) %>%
  row_spec(1, background = "#e8e8e8") %>%
  pack_rows("Sürekli Değişkenler", 2, 4, 
            label_row_css = "background-color: #2E4057; color: white;") %>%
  pack_rows("Cinsiyet", 5, 5,
            label_row_css = "background-color: #3a4f6b; color: white;") %>%
  pack_rows("Şube", 6, 8,
            label_row_css = "background-color: #3a4f6b; color: white;") %>%
  pack_rows("SES Düzeyi", 9, 9,
            label_row_css = "background-color: #3a4f6b; color: white;") %>%
  footnote(
    general = paste0("R² = ", model_fit$r.squared,
                     ", Düzeltilmiş R² = ", model_fit$adj.r.squared,
                     ", F(", model_fit$df, ", ", model_fit$df.residual,
                     ") = ", model_fit$statistic,
                     ", p < .001. Yeşil satırlar p < .05 düzeyinde anlamlıdır."),
    general_title = "Not:"
  )
Tablo 7. Çoklu Regresyon Analizi Sonuçları
Değişken B Std. Hata t p
Sabit 13.676 2.747 4.979 < .001
Sürekli Değişkenler
Dikkat Puanı 2.186 0.121 18.125 < .001
Çalışma Süresi (dk) 0.123 0.013 9.774 < .001
Devamsızlık (gün) -0.506 0.099 -5.133 < .001
Cinsiyet
Erkek (ref: Kız) -1.020 0.918 -1.111 0.267
Şube
Şube B (ref: A) -3.335 1.315 -2.537 0.012
Şube C (ref: A) -2.761 1.323 -2.086 0.038
Şube D (ref: A) -1.757 1.251 -1.404 0.161
SES Düzeyi
SES Düzeyi 4.316 0.956 4.517 < .001
Not:
R² = 0.667, Düzeltilmiş R² = 0.656, F(9, 280) = 62.368, p < .001. Yeşil satırlar p < .05 düzeyinde anlamlıdır.

Tablo 7 incelendiğinde kurulan çoklu regresyon modelinin istatistiksel olarak anlamlı olduğu görülmektedir, F(9, 280) = 62.37, p < .001. Model, başarı puanındaki toplam varyansın %66.7’sini (düzeltilmiş R² = .656) açıklamaktadır; bu değer güçlü bir model uyumuna işaret etmektedir.

Sürekli değişkenler incelendiğinde dikkat puanının başarıyı en güçlü biçimde yordayan değişken olduğu görülmektedir (B = 2.186, p < .001). Dikkat puanındaki her bir birimlik artış başarı puanında ortalama 2.19 puanlık artışa karşılık gelmektedir. Çalışma süresi de başarıyı anlamlı biçimde yordamaktadır (B = 0.123, p < .001); günlük çalışma süresindeki her bir dakikalık artış başarı puanını yaklaşık 0.12 puan artırmaktadır. Devamsızlık değişkeni beklenen yönde negatif bir etki sergilemekte olup her bir gün devamsızlık başarı puanını ortalama 0.51 puan düşürmektedir (B = −0.506, p < .001).

Kategorik değişkenler açısından SES düzeyi başarıyı anlamlı biçimde yordamaktadır (B = 4.316, p < .001); sosyoekonomik düzeydeki artış başarı puanını olumlu etkilemektedir. Şube karşılaştırmalarında A şubesi referans alındığında B şubesi (B = −3.335, p = .012) ve C şubesi (B = −2.761, p = .038) anlamlı biçimde daha düşük başarı puanı sergilemektedir. D şubesi (B = −1.757, p = .161) ve cinsiyet değişkeni (B = −1.020, p = .267) ise başarıyı anlamlı düzeyde yordamamaktadır.

Bu bulgular doğrultusunda regresyon denklemi aşağıdaki şekilde ifade edilebilir:

\[\hat{Y} = 13.68 + 2.19 \times \text{Dikkat} + 0.12 \times \text{Çalışma} - 0.51 \times \text{Devamsızlık} + 4.32 \times \text{SES} - 3.34 \times \text{ŞubeB} - 2.76 \times \text{ŞubeC} + \varepsilon\]

9.1 Artıkların Analizi

library(ggpubr)
library(patchwork)

artik_df <- data.frame(
  fitted   = fitted(model),
  residual = residuals(model),
  std_res  = rstandard(model)
)

# 1. Artıkların normalliği - Q-Q plot
p1 <- ggqqplot(artik_df, x = "residual",
               color = "#048A81",
               ggtheme = theme_minimal()) +
  labs(title = "Artıkların Normalliği (Q-Q)") +
  theme(
    plot.title       = element_text(color = "#7eb8d4", face = "bold", size = 11, hjust = 0.5),
    panel.background = element_rect(fill = "#1a1e2e", color = NA),
    plot.background  = element_rect(fill = "#1a1e2e", color = NA),
    panel.grid.major = element_blank(),
    panel.grid.minor = element_blank(),
    axis.text        = element_text(color = "#e8e8e8"),
    axis.title       = element_text(color = "#e8e8e8")
  )

# 2. Eşvaryanslılık - Fitted vs Residuals
p2 <- ggplot(artik_df, aes(x = fitted, y = std_res)) +
  geom_point(alpha = 0.5, color = "#f4a261", size = 1.5) +
  geom_hline(yintercept = 0,  color = "white",   linewidth = 0.8) +
  geom_hline(yintercept =  2, color = "#e63946", linewidth = 0.5, linetype = "dashed") +
  geom_hline(yintercept = -2, color = "#e63946", linewidth = 0.5, linetype = "dashed") +
  geom_smooth(se = FALSE, color = "#7eb8d4", linewidth = 0.8, method = "loess") +
  labs(title    = "Eşvaryanslılık (Fitted vs Residuals)",
       x = "Tahmin Edilen Değerler",
       y = "Standartlaştırılmış Artıklar") +
  theme_minimal() +
  theme(
    plot.title       = element_text(color = "#7eb8d4", face = "bold", size = 11, hjust = 0.5),
    panel.background = element_rect(fill = "#1a1e2e", color = NA),
    plot.background  = element_rect(fill = "#1a1e2e", color = NA),
    panel.grid.major = element_line(color = "#333a50", linewidth = 0.3),
    panel.grid.minor = element_blank(),
    axis.text        = element_text(color = "#e8e8e8"),
    axis.title       = element_text(color = "#e8e8e8")
  )

p1 + p2 +
  plot_annotation(
    title = "Şekil 7. Regresyon Artık Grafikleri",
    theme = theme(
      plot.title      = element_text(color = "#7eb8d4", face = "bold", size = 14, hjust = 0.5),
      plot.background = element_rect(fill = "#1a1e2e", color = NA)
    )
  )

Şekil 7 incelendiğinde regresyon modelinin artık varsayımlarını büyük ölçüde karşıladığı görülmektedir. Sol paneldeki Q-Q grafiğinde artıkların orta değerlerde referans doğrusunu yakından takip ettiği, ancak uç noktalarda hafif sapmalar gözlemlendiği dikkat çekmektedir. Bu durum artıkların normal dağılıma yakın olduğuna işaret etmektedir. Sağ paneldeki Fitted vs Residuals grafiğinde standartlaştırılmış artıkların tahmin edilen değerler boyunca ±2 sınırları içinde rastlantısal biçimde dağıldığı görülmektedir. Loess eğrisi sıfır çizgisine paralel ve yatay bir seyir izlemekte olup bu durum eşvaryanslılık varsayımının karşılandığına işaret etmektedir. Artıklarda belirgin bir örüntü veya sistematik bir sapma gözlemlenmemektedir. Genel olarak değerlendirildiğinde modelin regresyon varsayımlarını yeterli düzeyde karşıladığı söylenebilir.

library(effectsize)

model_fit  <- glance(model)
cohen_f2   <- model_fit$r.squared / (1 - model_fit$r.squared)

tibble(
  İndeks   = c("R²", "Düzeltilmiş R²", "F İstatistiği", "p", "Cohen f²", "Artık Std. Hata"),
  Değer    = c(round(model_fit$r.squared, 3),
               round(model_fit$adj.r.squared, 3),
               round(model_fit$statistic, 3),
               "< .001",
               round(cohen_f2, 3),
               round(model_fit$sigma, 3)),
  Yorum    = c("Varyansın %66.7'si açıklandı",
               "Serbestlik derecesi düzeltmeli",
               "Model anlamlı",
               "p < .001",
               "Büyük etki (f² > 0.35)",
               "Ortalama tahmin hatası")
) %>%
  kable(caption = "Tablo 8. Model Uyum İndeksleri",
        align   = c("l", "c", "l")) %>%
  kable_styling(bootstrap_options = c("hover", "condensed", "bordered"),
                full_width = FALSE, font_size = 13) %>%
  row_spec(0, bold = TRUE, color = "white", background = "#2E4057") %>%
  row_spec(1:6, color = "#1a1e2e", background = "#d6e4f0") %>%
  row_spec(c(1, 5), background = "#c8e6c9", bold = TRUE)
Tablo 8. Model Uyum İndeksleri
İndeks Değer Yorum
0.667 Varyansın %66.7’si açıklandı
Düzeltilmiş R² 0.656 Serbestlik derecesi düzeltmeli
F İstatistiği 62.368 Model anlamlı
p < .001 p < .001
Cohen f² 2.005 Büyük etki (f² > 0.35)
Artık Std. Hata 7.749 Ortalama tahmin hatası

Tablo 8 incelendiğinde modelin güçlü bir açıklayıcılık gücüne sahip olduğu görülmektedir. R² = .667 değeri bağımsız değişkenlerin başarı puanındaki varyansın %66.7’sini açıkladığına işaret etmektedir. Cohen f² = 2.005 değeri 0.35 eşiğinin çok üzerinde olup büyük etki büyüklüğüne karşılık gelmektedir. Model F(9, 280) = 62.37, p < .001 düzeyinde istatistiksel olarak anlamlıdır. Artık standart hata 7.749 olup tahmin hatalarının makul düzeyde olduğunu göstermektedir.

10 Kayıp Veri Çalışmaları

10.1 Tam Veri ile Yapılan Analizlerin Referans Olarak Kaydedilmesi

# Temiz veri regresyon sonuçlarını referans olarak sakla
referans_model <- list(
  R2         = round(glance(model)$r.squared, 3),
  adj_R2     = round(glance(model)$adj.r.squared, 3),
  F_stat     = round(glance(model)$statistic, 3),
  katsayilar = tidy(model) %>% 
    select(term, estimate, std.error, p.value) %>%
    mutate(across(where(is.numeric), ~round(., 3)))
)

cat("Referans model kaydedildi.\n")
## Referans model kaydedildi.
cat("R² =", referans_model$R2, "\n")
## R² = 0.667
cat("Düzeltilmiş R² =", referans_model$adj_R2, "\n")
## Düzeltilmiş R² = 0.656

10.2 Kayıp Veri Setlerinin Oluşturulması

set.seed(42)

kayip_veri_uret <- function(veri, degisken_mcar, degisken_mar, oran) {
  df_kayip <- veri
  n <- nrow(df_kayip)
  
  # MCAR: calisma_suresi - tamamen rastgele
  mcar_idx <- sample(1:n, size = round(n * oran))
  df_kayip[mcar_idx, degisken_mcar] <- NA
  
  # MAR: dikkat_puani - SES düzeyi düşük olanlarda yoğun
  ses_dusuk <- which(df_kayip$ses_duzeyi == "Düşük")
  ses_diger <- which(df_kayip$ses_duzeyi != "Düşük")
  
  n_dusuk <- round(length(ses_dusuk) * oran * 1.8)
  n_diger <- round(length(ses_diger) * oran * 0.4)
  n_dusuk <- min(n_dusuk, length(ses_dusuk))
  n_diger <- min(n_diger, length(ses_diger))
  
  mar_idx <- c(sample(ses_dusuk, n_dusuk), sample(ses_diger, n_diger))
  df_kayip[mar_idx, degisken_mar] <- NA
  
  return(df_kayip)
}

# Üç farklı oranda veri seti oluştur
veri_kayip_07 <- kayip_veri_uret(veri_uc_degersiz3, "calisma_suresi_dk", "dikkat_puani", 0.07)
veri_kayip_10 <- kayip_veri_uret(veri_uc_degersiz3, "calisma_suresi_dk", "dikkat_puani", 0.10)
veri_kayip_13 <- kayip_veri_uret(veri_uc_degersiz3, "calisma_suresi_dk", "dikkat_puani", 0.13)
tibble(
  `Veri Seti`          = c("%7 Kayıp", "%10 Kayıp", "%13 Kayıp"),
  `Çalışma Süresi (MCAR)` = c(
    sum(is.na(veri_kayip_07$calisma_suresi_dk)),
    sum(is.na(veri_kayip_10$calisma_suresi_dk)),
    sum(is.na(veri_kayip_13$calisma_suresi_dk))
  ),
  `MCAR Oran`          = c("% 6.9", "% 10.0", "% 13.1"),
  `Dikkat Puanı (MAR)` = c(
    sum(is.na(veri_kayip_07$dikkat_puani)),
    sum(is.na(veri_kayip_10$dikkat_puani)),
    sum(is.na(veri_kayip_13$dikkat_puani))
  ),
  `MAR Oran`           = c("% 5.9", "% 9.0", "% 11.4")
) %>%
  kable(caption = "Tablo 9. Kayıp Veri Setlerine İlişkin Özet Bilgiler",
        align   = c("l", "c", "c", "c", "c")) %>%
  kable_styling(bootstrap_options = c("hover", "condensed", "bordered"),
                full_width = FALSE, font_size = 13) %>%
  row_spec(0, bold = TRUE, color = "white", background = "#2E4057") %>%
  row_spec(1:3, color = "#1a1e2e", background = "#d6e4f0") %>%
  row_spec(c(1,3), background = "#eaf4fb")
Tablo 9. Kayıp Veri Setlerine İlişkin Özet Bilgiler
Veri Seti Çalışma Süresi (MCAR) MCAR Oran Dikkat Puanı (MAR) MAR Oran
%7 Kayıp 20 % 6.9 17 % 5.9
%10 Kayıp 29 % 10.0 26 % 9.0
%13 Kayıp 38 % 13.1 33 % 11.4

Bu aşamada temiz veri seti üzerinde kontrollü biçimde kayıp veri oluşturulmuştur. İki farklı mekanizma altında üç farklı kayıp oranı uygulanmış; böylece altı farklı kayıp veri koşulu elde edilmiştir. Çalışma süresi değişkenine tamamen rastlantısal kayıp (MCAR) mekanizması altında %7, %10 ve %13 oranlarında kayıp yerleştirilmiştir. Dikkat puanı değişkenine ise rastlantısal kayıp (MAR) mekanizması uygulanmış; kayıp değerler SES düzeyi düşük olan öğrencilerde daha yoğun biçimde dağıtılmıştır. Bu tasarım sayesinde ilerleyen analizlerde hem kayıp oranının hem de kayıp mekanizmasının regresyon sonuçları üzerindeki etkisi karşılaştırmalı olarak incelenebilecektir.

10.3 MCAR Testi

library(naniar)

# MCAR testi: sadece çalışma süresi kayıplı sütunlar için
mcar_test_sonuc <- function(veri, etiket) {
  sonuc <- mcar_test(veri %>% select(where(is.numeric)))
  tibble(
    `Veri Seti`  = etiket,
    `Ki-Kare`    = round(sonuc$statistic, 3),
    `df`         = sonuc$df,
    `p`          = ifelse(sonuc$p.value < .001, "< .001", 
                          as.character(round(sonuc$p.value, 3))),
    `p_val`      = sonuc$p.value,
    `Mekanizma`  = ifelse(sonuc$p.value > .05, "MCAR", "MAR/MNAR")
  )
}

bind_rows(
  mcar_test_sonuc(veri_kayip_07 %>% select(-dikkat_puani), "%7 - Çalışma Süresi (MCAR)"),
  mcar_test_sonuc(veri_kayip_07 %>% select(-calisma_suresi_dk), "%7 - Dikkat Puanı (MAR)"),
  mcar_test_sonuc(veri_kayip_10 %>% select(-dikkat_puani), "%10 - Çalışma Süresi (MCAR)"),
  mcar_test_sonuc(veri_kayip_10 %>% select(-calisma_suresi_dk), "%10 - Dikkat Puanı (MAR)"),
  mcar_test_sonuc(veri_kayip_13 %>% select(-dikkat_puani), "%13 - Çalışma Süresi (MCAR)"),
  mcar_test_sonuc(veri_kayip_13 %>% select(-calisma_suresi_dk), "%13 - Dikkat Puanı (MAR)")
) -> mcar_tablo

mcar_tablo %>%
  select(-p_val) %>%
  kable(caption = "Tablo 10. Little's MCAR Testi Sonuçları",
        align   = c("l", "c", "c", "c", "c")) %>%
  kable_styling(bootstrap_options = c("hover", "condensed", "bordered"),
                full_width = FALSE, font_size = 13) %>%
  row_spec(0, bold = TRUE, color = "white", background = "#2E4057") %>%
  row_spec(1:6, color = "#1a1e2e", background = "#d6e4f0") %>%
  row_spec(c(1, 3, 5), background = "#eaf4fb") %>%
  column_spec(5, bold = TRUE,
              color = ifelse(mcar_tablo$p_val > .05, "darkgreen", "red")) %>%
  pack_rows("% 7 Kayıp", 1, 2, label_row_css = "background-color: #2E4057; color: white;") %>%
  pack_rows("%10 Kayıp", 3, 4, label_row_css = "background-color: #2E4057; color: white;") %>%
  pack_rows("%13 Kayıp", 5, 6, label_row_css = "background-color: #2E4057; color: white;") %>%
  footnote(general = "H₀: Kayıp veri tamamen rastlantısaldır (MCAR). p > .05 MCAR destekler, p < .05 MAR/MNAR'a işaret eder.",
           general_title = "Not:")
Tablo 10. Little’s MCAR Testi Sonuçları
Veri Seti Ki-Kare df p Mekanizma
% 7 Kayıp
%7 - Çalışma Süresi (MCAR) 3.377 2 0.185 MCAR
%7 - Dikkat Puanı (MAR) 2.579 2 0.275 MCAR
%10 Kayıp
%10 - Çalışma Süresi (MCAR) 2.275 2 0.321 MCAR
%10 - Dikkat Puanı (MAR) 2.002 2 0.368 MCAR
%13 Kayıp
%13 - Çalışma Süresi (MCAR) 1.458 2 0.482 MCAR
%13 - Dikkat Puanı (MAR) 8.400 2 0.015 MAR/MNAR
Not:
H₀: Kayıp veri tamamen rastlantısaldır (MCAR). p > .05 MCAR destekler, p < .05 MAR/MNAR’a işaret eder.

Little’s MCAR testi çalışma süresi değişkeni için MCAR mekanizmasını desteklemiştir. Ancak dikkat puanı için beklenen MAR mekanizması tespit edilememiştir. Bunun nedeni testin yalnızca sayısal değişkenler üzerinden çalışması ve kategorik bir değişkene (SES düzeyi) bağlı MAR’ı yakalayamamasıdır. Bu nedenle MAR mekanizmasını doğrulamak amacıyla lojistik regresyon testi uygulanmıştır (Tablo 10b).

# MAR doğrulama: Dikkat puanı kayıp mı SES ile ilişkili mi?
mar_test <- function(veri, etiket) {
  veri$kayip <- as.numeric(is.na(veri$dikkat_puani))
  model_mar  <- glm(kayip ~ ses_duzeyi + cinsiyet + sube, 
                    data = veri, family = binomial)
  s <- summary(model_mar)
  p <- pchisq(s$null.deviance - s$deviance, 
              df = s$df.null - s$df.residual, lower.tail = FALSE)
  tibble(
    `Veri Seti` = etiket,
    `Ki-Kare`   = round(s$null.deviance - s$deviance, 3),
    `p`         = ifelse(p < .001, "< .001", as.character(round(p, 3))),
    `p_val`     = p,
    `Yorum`     = ifelse(p < .05, "MAR destekleniyor", "MAR desteklenmiyor")
  )
}

mar_tablo <- bind_rows(
  mar_test(veri_kayip_07, "%7 Kayıp"),
  mar_test(veri_kayip_10, "%10 Kayıp"),
  mar_test(veri_kayip_13, "%13 Kayıp")
)

mar_tablo %>%
  select(-p_val) %>%
  kable(caption = "Tablo 10b. MAR Doğrulama: Lojistik Regresyon Testi",
        align = c("l", "c", "c", "l")) %>%
  kable_styling(bootstrap_options = c("hover", "condensed", "bordered"),
                full_width = FALSE, font_size = 13) %>%
  row_spec(0, bold = TRUE, color = "white", background = "#2E4057") %>%
  row_spec(1:3, color = "#1a1e2e", background = "#d6e4f0") %>%
  column_spec(4, bold = TRUE,
              color = ifelse(mar_tablo$p_val < .05, "darkgreen", "red")) %>%
  footnote(general = "Kayıp olma durumu kategorik değişkenler tarafından yordanıyorsa MAR mekanizması desteklenir.",
           general_title = "Not:")
Tablo 10b. MAR Doğrulama: Lojistik Regresyon Testi
Veri Seti Ki-Kare p Yorum
%7 Kayıp 11.983 0.062 MAR desteklenmiyor
%10 Kayıp 18.615 0.005 MAR destekleniyor
%13 Kayıp 24.153 < .001 MAR destekleniyor
Not:
Kayıp olma durumu kategorik değişkenler tarafından yordanıyorsa MAR mekanizması desteklenir.

Lojistik regresyon sonuçları %10 ve %13 kayıp oranlarında MAR mekanizmasını doğrulamıştır. %7 oranında p = .062 ile sınırda kalan bulgu, düşük kayıp oranlarında testin istatistiksel gücünün henüz yeterli olmadığına işaret etmektedir. %13 kayıp oranında ise Little’s MCAR testinin de MAR/MNAR’a işaret etmesi, kayıp miktarı arttıkça mekanizmanın her iki test tarafından da yakalanabildiğini göstermektedir.

11 Kayıp Veri İle Başa Çıkma

Bu bölümde üç farklı kayıp oranında (%7, %10 ve %13) ve iki farklı mekanizma (MCAR ve MAR) altında oluşturulan kayıp veri setleri için çeşitli kayıp veri ele alma yöntemleri uygulanmıştır. Her iki değişken için sırasıyla listwise deletion, ortalama atama, regresyon ataması ve çoklu atama (mice) yöntemleri uygulanmış; her yöntem sonrasında aynı çoklu regresyon modeli kurularak elde edilen R², düzeltilmiş R² ve seçilen değişkenlere ait B katsayıları ile standart hatalar kaydedilmiştir. Tüm yöntemlerden elde edilen sonuçlar bölüm sonunda referans model (temiz veri) ile birlikte karşılaştırmalı olarak sunulmuştur.

11.1 Rasgel Kayıp Veri İçin (Çalışma Süresi)

library(mice)

# Sonuçları saklamak için liste
calisma_sonuclar <- list()

# Yardımcı fonksiyon: regresyon sonuçlarını kaydet
reg_sonuc_al <- function(veri, etiket) {
  m <- lm(basari_puani ~ dikkat_puani + calisma_suresi_dk + 
            devamsizlik_gun + cinsiyet + sube + ses_duzeyi,
          data = veri)
  g <- glance(m)
  tibble(
    Yöntem       = etiket,
    R2           = round(g$r.squared, 3),
    Adj_R2       = round(g$adj.r.squared, 3),
    B_calisma    = round(coef(m)["calisma_suresi_dk"], 3),
    SE_calisma   = round(summary(m)$coefficients["calisma_suresi_dk", "Std. Error"], 3),
    B_dikkat     = round(coef(m)["dikkat_puani"], 3),
    SE_dikkat    = round(summary(m)$coefficients["dikkat_puani", "Std. Error"], 3)
  )
}

# === REFERANS (temiz veri) ===
calisma_sonuclar[["Referans"]] <- reg_sonuc_al(veri_uc_degersiz3, "Referans (Temiz Veri)")

# === %7 KAYIP ===
# 1. Listwise deletion
calisma_sonuclar[["LD_07"]] <- reg_sonuc_al(
  veri_kayip_07 %>% drop_na(calisma_suresi_dk), 
  "%7 - Listwise Deletion")

# 2. Ortalama atama
veri_ort_07 <- veri_kayip_07 %>%
  mutate(calisma_suresi_dk = ifelse(
    is.na(calisma_suresi_dk), 
    mean(calisma_suresi_dk, na.rm = TRUE), 
    calisma_suresi_dk))
calisma_sonuclar[["OA_07"]] <- reg_sonuc_al(veri_ort_07, "%7 - Ortalama Atama")

# 3. Regresyon ataması
reg_model <- lm(calisma_suresi_dk ~ dikkat_puani + devamsizlik_gun + 
                  ses_duzeyi + cinsiyet + sube,
                data = veri_kayip_07)
veri_reg_07 <- veri_kayip_07 %>%
  mutate(calisma_suresi_dk = ifelse(
    is.na(calisma_suresi_dk),
    predict(reg_model, newdata = veri_kayip_07)[which(is.na(calisma_suresi_dk))],
    calisma_suresi_dk))
calisma_sonuclar[["RA_07"]] <- reg_sonuc_al(veri_reg_07, "%7 - Regresyon Ataması")

# 4. Çoklu atama (mice)
imp_07 <- mice(veri_kayip_07 %>% select(calisma_suresi_dk, dikkat_puani,
                                         devamsizlik_gun, basari_puani,
                                         cinsiyet, sube, ses_duzeyi),
               m = 5, method = "pmm", seed = 42, printFlag = FALSE)
fit_07 <- with(imp_07, lm(basari_puani ~ dikkat_puani + calisma_suresi_dk +
                             devamsizlik_gun + cinsiyet + sube + ses_duzeyi))
pool_07 <- pool(fit_07)
calisma_sonuclar[["MI_07"]] <- tibble(
  Yöntem     = "%7 - Çoklu Atama (mice)",
  R2         = round(pool.r.squared(fit_07)[1, "est"], 3),
  Adj_R2     = round(pool.r.squared(fit_07, adjusted = TRUE)[1, "est"], 3),
  B_calisma  = round(summary(pool_07) %>% filter(term == "calisma_suresi_dk") %>% pull(estimate), 3),
  SE_calisma = round(summary(pool_07) %>% filter(term == "calisma_suresi_dk") %>% pull(std.error), 3),
  B_dikkat   = round(summary(pool_07) %>% filter(term == "dikkat_puani") %>% pull(estimate), 3),
  SE_dikkat  = round(summary(pool_07) %>% filter(term == "dikkat_puani") %>% pull(std.error), 3)
)

cat("Çalışma süresi %7 atama yöntemleri tamamlandı.\n")
## Çalışma süresi %7 atama yöntemleri tamamlandı.
# === %10 KAYIP ===
calisma_sonuclar[["LD_10"]] <- reg_sonuc_al(
  veri_kayip_10 %>% drop_na(calisma_suresi_dk), "%10 - Listwise Deletion")

veri_ort_10 <- veri_kayip_10 %>%
  mutate(calisma_suresi_dk = ifelse(is.na(calisma_suresi_dk),
    mean(calisma_suresi_dk, na.rm = TRUE), calisma_suresi_dk))
calisma_sonuclar[["OA_10"]] <- reg_sonuc_al(veri_ort_10, "%10 - Ortalama Atama")

reg_model_10 <- lm(calisma_suresi_dk ~ dikkat_puani + devamsizlik_gun +
                     ses_duzeyi + cinsiyet + sube, data = veri_kayip_10)
veri_reg_10 <- veri_kayip_10 %>%
  mutate(calisma_suresi_dk = ifelse(is.na(calisma_suresi_dk),
    predict(reg_model_10, newdata = veri_kayip_10)[which(is.na(calisma_suresi_dk))],
    calisma_suresi_dk))
calisma_sonuclar[["RA_10"]] <- reg_sonuc_al(veri_reg_10, "%10 - Regresyon Ataması")

imp_10 <- mice(veri_kayip_10 %>% select(calisma_suresi_dk, dikkat_puani,
                                         devamsizlik_gun, basari_puani,
                                         cinsiyet, sube, ses_duzeyi),
               m = 5, method = "pmm", seed = 42, printFlag = FALSE)
fit_10 <- with(imp_10, lm(basari_puani ~ dikkat_puani + calisma_suresi_dk +
                             devamsizlik_gun + cinsiyet + sube + ses_duzeyi))
pool_10 <- pool(fit_10)
calisma_sonuclar[["MI_10"]] <- tibble(
  Yöntem     = "%10 - Çoklu Atama (mice)",
  R2         = round(pool.r.squared(fit_10)[1, "est"], 3),
  Adj_R2     = round(pool.r.squared(fit_10, adjusted = TRUE)[1, "est"], 3),
  B_calisma  = round(summary(pool_10) %>% filter(term == "calisma_suresi_dk") %>% pull(estimate), 3),
  SE_calisma = round(summary(pool_10) %>% filter(term == "calisma_suresi_dk") %>% pull(std.error), 3),
  B_dikkat   = round(summary(pool_10) %>% filter(term == "dikkat_puani") %>% pull(estimate), 3),
  SE_dikkat  = round(summary(pool_10) %>% filter(term == "dikkat_puani") %>% pull(std.error), 3)
)

# === %13 KAYIP ===
calisma_sonuclar[["LD_13"]] <- reg_sonuc_al(
  veri_kayip_13 %>% drop_na(calisma_suresi_dk), "%13 - Listwise Deletion")

veri_ort_13 <- veri_kayip_13 %>%
  mutate(calisma_suresi_dk = ifelse(is.na(calisma_suresi_dk),
    mean(calisma_suresi_dk, na.rm = TRUE), calisma_suresi_dk))
calisma_sonuclar[["OA_13"]] <- reg_sonuc_al(veri_ort_13, "%13 - Ortalama Atama")

reg_model_13 <- lm(calisma_suresi_dk ~ dikkat_puani + devamsizlik_gun +
                     ses_duzeyi + cinsiyet + sube, data = veri_kayip_13)
veri_reg_13 <- veri_kayip_13 %>%
  mutate(calisma_suresi_dk = ifelse(is.na(calisma_suresi_dk),
    predict(reg_model_13, newdata = veri_kayip_13)[which(is.na(calisma_suresi_dk))],
    calisma_suresi_dk))
calisma_sonuclar[["RA_13"]] <- reg_sonuc_al(veri_reg_13, "%13 - Regresyon Ataması")

imp_13 <- mice(veri_kayip_13 %>% select(calisma_suresi_dk, dikkat_puani,
                                         devamsizlik_gun, basari_puani,
                                         cinsiyet, sube, ses_duzeyi),
               m = 5, method = "pmm", seed = 42, printFlag = FALSE)
fit_13 <- with(imp_13, lm(basari_puani ~ dikkat_puani + calisma_suresi_dk +
                             devamsizlik_gun + cinsiyet + sube + ses_duzeyi))
pool_13 <- pool(fit_13)
calisma_sonuclar[["MI_13"]] <- tibble(
  Yöntem     = "%13 - Çoklu Atama (mice)",
  R2         = round(pool.r.squared(fit_13)[1, "est"], 3),
  Adj_R2     = round(pool.r.squared(fit_13, adjusted = TRUE)[1, "est"], 3),
  B_calisma  = round(summary(pool_13) %>% filter(term == "calisma_suresi_dk") %>% pull(estimate), 3),
  SE_calisma = round(summary(pool_13) %>% filter(term == "calisma_suresi_dk") %>% pull(std.error), 3),
  B_dikkat   = round(summary(pool_13) %>% filter(term == "dikkat_puani") %>% pull(estimate), 3),
  SE_dikkat  = round(summary(pool_13) %>% filter(term == "dikkat_puani") %>% pull(std.error), 3)
)

cat("Tüm atama yöntemleri tamamlandı.\n")
## Tüm atama yöntemleri tamamlandı.
# Karşılaştırma tablosu
bind_rows(calisma_sonuclar) %>%
  kable(
    caption   = "Tablo 11. Çalışma Süresi (MCAR) - Atama Yöntemleri Karşılaştırması",
    col.names = c("Yöntem", "R²", "Düz. R²", "B (Çalışma)", "SE (Çalışma)", 
                  "B (Dikkat)", "SE (Dikkat)"),
    align     = c("l", "c", "c", "c", "c", "c", "c")
  ) %>%
  kable_styling(bootstrap_options = c("hover", "condensed", "bordered"),
                full_width = TRUE, font_size = 12) %>%
  row_spec(0, bold = TRUE, color = "white", background = "#2E4057") %>%
  row_spec(1, background = "#c8e6c9", bold = TRUE) %>%
  row_spec(2:13, color = "#1a1e2e", background = "#d6e4f0") %>%
  row_spec(c(2,3,4,5), background = "#eaf4fb") %>%
  pack_rows("% 7 Kayıp", 2, 5,  label_row_css = "background-color: #2E4057; color: white;") %>%
  pack_rows("%10 Kayıp", 6, 9,  label_row_css = "background-color: #2E4057; color: white;") %>%
  pack_rows("%13 Kayıp", 10, 13, label_row_css = "background-color: #2E4057; color: white;") %>%
  footnote(general = "Yeşil satır referans modeli (temiz veri) göstermektedir.",
           general_title = "Not:")
Tablo 11. Çalışma Süresi (MCAR) - Atama Yöntemleri Karşılaştırması
Yöntem Düz. R² B (Çalışma) SE (Çalışma) B (Dikkat) SE (Dikkat)
Referans (Temiz Veri) 0.667 0.656 0.123 0.013 2.186 0.121
% 7 Kayıp
%7 - Listwise Deletion 0.668 0.656 0.117 0.013 2.197 0.130
%7 - Ortalama Atama 0.664 0.653 0.116 0.013 2.154 0.126
%7 - Regresyon Ataması 0.662 0.650 0.115 0.013 2.142 0.127
%7 - Çoklu Atama (mice) 0.667 0.656 0.120 0.014 2.217 0.126
%10 Kayıp
%10 - Listwise Deletion 0.668 0.655 0.119 0.014 2.273 0.135
%10 - Ortalama Atama 0.649 0.637 0.116 0.014 2.157 0.129
%10 - Regresyon Ataması 0.653 0.641 0.117 0.014 2.179 0.130
%10 - Çoklu Atama (mice) 0.661 0.651 0.122 0.014 2.200 0.137
%13 Kayıp
%13 - Listwise Deletion 0.649 0.635 0.125 0.015 2.042 0.133
%13 - Ortalama Atama 0.649 0.636 0.125 0.015 2.099 0.126
%13 - Regresyon Ataması 0.651 0.638 0.124 0.015 2.111 0.128
%13 - Çoklu Atama (mice) 0.668 0.658 0.133 0.015 2.104 0.127
Not:
Yeşil satır referans modeli (temiz veri) göstermektedir.

Tablo 11 incelendiğinde çalışma süresi değişkenine uygulanan MCAR mekanizması altında farklı atama yöntemlerinin regresyon sonuçları üzerinde sınırlı bir etki yarattığı görülmektedir. Bu bulgu MCAR mekanizmasının teorik beklentisiyle örtüşmektedir; tamamen rastlantısal kayıp varlığında tüm atama yöntemleri referans modele yakın sonuçlar üretmektedir. Bununla birlikte ortalama atama yönteminin R² değerini hafif düşürdüğü, çoklu atamanın ise referansa en yakın sonucu verdiği dikkat çekmektedir. Kayıp oranı %7’den %13’e yükseldiğinde farklar büyümekle birlikte tüm yöntemlerde sonuçlar kabul edilebilir sınırlar içinde kalmaktadır. Bu bulgular MCAR koşullarında listwise deletion dahil tüm yöntemlerin güvenle kullanılabileceğine işaret etmekte, ancak çoklu atamanın tutarlı biçimde en iyi performansı sergilediğini ortaya koymaktadır.

11.2 SES’e Bağlı Kayıp Veri (MAR) ile İnceleme (Dikkat Puanı)

dikkat_sonuclar <- list()

# Referans zaten var, tekrar ekleyelim
dikkat_sonuclar[["Referans"]] <- reg_sonuc_al(veri_uc_degersiz3, "Referans (Temiz Veri)")

# === %7 KAYIP ===
# 1. Listwise deletion
dikkat_sonuclar[["LD_07"]] <- reg_sonuc_al(
  veri_kayip_07 %>% drop_na(dikkat_puani),
  "%7 - Listwise Deletion")

# 2. Ortalama atama
veri_ort_d07 <- veri_kayip_07 %>%
  mutate(dikkat_puani = ifelse(
    is.na(dikkat_puani),
    mean(dikkat_puani, na.rm = TRUE),
    dikkat_puani))
dikkat_sonuclar[["OA_07"]] <- reg_sonuc_al(veri_ort_d07, "%7 - Ortalama Atama")

# 3. Regresyon ataması
reg_model_d07 <- lm(dikkat_puani ~ calisma_suresi_dk + devamsizlik_gun +
                      ses_duzeyi + cinsiyet + sube,
                    data = veri_kayip_07)
veri_reg_d07 <- veri_kayip_07 %>%
  mutate(dikkat_puani = ifelse(
    is.na(dikkat_puani),
    predict(reg_model_d07, newdata = veri_kayip_07)[which(is.na(dikkat_puani))],
    dikkat_puani))
dikkat_sonuclar[["RA_07"]] <- reg_sonuc_al(veri_reg_d07, "%7 - Regresyon Ataması")

# 4. Çoklu atama
imp_d07 <- mice(veri_kayip_07 %>% select(dikkat_puani, calisma_suresi_dk,
                                          devamsizlik_gun, basari_puani,
                                          cinsiyet, sube, ses_duzeyi),
                m = 5, method = "pmm", seed = 42, printFlag = FALSE)
fit_d07 <- with(imp_d07, lm(basari_puani ~ dikkat_puani + calisma_suresi_dk +
                               devamsizlik_gun + cinsiyet + sube + ses_duzeyi))
pool_d07 <- pool(fit_d07)
dikkat_sonuclar[["MI_07"]] <- tibble(
  Yöntem     = "%7 - Çoklu Atama (mice)",
  R2         = round(pool.r.squared(fit_d07)[1, "est"], 3),
  Adj_R2     = round(pool.r.squared(fit_d07, adjusted = TRUE)[1, "est"], 3),
  B_calisma  = round(summary(pool_d07) %>% filter(term == "calisma_suresi_dk") %>% pull(estimate), 3),
  SE_calisma = round(summary(pool_d07) %>% filter(term == "calisma_suresi_dk") %>% pull(std.error), 3),
  B_dikkat   = round(summary(pool_d07) %>% filter(term == "dikkat_puani") %>% pull(estimate), 3),
  SE_dikkat  = round(summary(pool_d07) %>% filter(term == "dikkat_puani") %>% pull(std.error), 3)
)

# === %10 KAYIP ===
dikkat_sonuclar[["LD_10"]] <- reg_sonuc_al(
  veri_kayip_10 %>% drop_na(dikkat_puani), "%10 - Listwise Deletion")

veri_ort_d10 <- veri_kayip_10 %>%
  mutate(dikkat_puani = ifelse(is.na(dikkat_puani),
    mean(dikkat_puani, na.rm = TRUE), dikkat_puani))
dikkat_sonuclar[["OA_10"]] <- reg_sonuc_al(veri_ort_d10, "%10 - Ortalama Atama")

reg_model_d10 <- lm(dikkat_puani ~ calisma_suresi_dk + devamsizlik_gun +
                      ses_duzeyi + cinsiyet + sube, data = veri_kayip_10)
veri_reg_d10 <- veri_kayip_10 %>%
  mutate(dikkat_puani = ifelse(is.na(dikkat_puani),
    predict(reg_model_d10, newdata = veri_kayip_10)[which(is.na(dikkat_puani))],
    dikkat_puani))
dikkat_sonuclar[["RA_10"]] <- reg_sonuc_al(veri_reg_d10, "%10 - Regresyon Ataması")

imp_d10 <- mice(veri_kayip_10 %>% select(dikkat_puani, calisma_suresi_dk,
                                          devamsizlik_gun, basari_puani,
                                          cinsiyet, sube, ses_duzeyi),
                m = 5, method = "pmm", seed = 42, printFlag = FALSE)
fit_d10 <- with(imp_d10, lm(basari_puani ~ dikkat_puani + calisma_suresi_dk +
                               devamsizlik_gun + cinsiyet + sube + ses_duzeyi))
pool_d10 <- pool(fit_d10)
dikkat_sonuclar[["MI_10"]] <- tibble(
  Yöntem     = "%10 - Çoklu Atama (mice)",
  R2         = round(pool.r.squared(fit_d10)[1, "est"], 3),
  Adj_R2     = round(pool.r.squared(fit_d10, adjusted = TRUE)[1, "est"], 3),
  B_calisma  = round(summary(pool_d10) %>% filter(term == "calisma_suresi_dk") %>% pull(estimate), 3),
  SE_calisma = round(summary(pool_d10) %>% filter(term == "calisma_suresi_dk") %>% pull(std.error), 3),
  B_dikkat   = round(summary(pool_d10) %>% filter(term == "dikkat_puani") %>% pull(estimate), 3),
  SE_dikkat  = round(summary(pool_d10) %>% filter(term == "dikkat_puani") %>% pull(std.error), 3)
)

# === %13 KAYIP ===
dikkat_sonuclar[["LD_13"]] <- reg_sonuc_al(
  veri_kayip_13 %>% drop_na(dikkat_puani), "%13 - Listwise Deletion")

veri_ort_d13 <- veri_kayip_13 %>%
  mutate(dikkat_puani = ifelse(is.na(dikkat_puani),
    mean(dikkat_puani, na.rm = TRUE), dikkat_puani))
dikkat_sonuclar[["OA_13"]] <- reg_sonuc_al(veri_ort_d13, "%13 - Ortalama Atama")

reg_model_d13 <- lm(dikkat_puani ~ calisma_suresi_dk + devamsizlik_gun +
                      ses_duzeyi + cinsiyet + sube, data = veri_kayip_13)
veri_reg_d13 <- veri_kayip_13 %>%
  mutate(dikkat_puani = ifelse(is.na(dikkat_puani),
    predict(reg_model_d13, newdata = veri_kayip_13)[which(is.na(dikkat_puani))],
    dikkat_puani))
dikkat_sonuclar[["RA_13"]] <- reg_sonuc_al(veri_reg_d13, "%13 - Regresyon Ataması")

imp_d13 <- mice(veri_kayip_13 %>% select(dikkat_puani, calisma_suresi_dk,
                                          devamsizlik_gun, basari_puani,
                                          cinsiyet, sube, ses_duzeyi),
                m = 5, method = "pmm", seed = 42, printFlag = FALSE)
fit_d13 <- with(imp_d13, lm(basari_puani ~ dikkat_puani + calisma_suresi_dk +
                               devamsizlik_gun + cinsiyet + sube + ses_duzeyi))
pool_d13 <- pool(fit_d13)
dikkat_sonuclar[["MI_13"]] <- tibble(
  Yöntem     = "%13 - Çoklu Atama (mice)",
  R2         = round(pool.r.squared(fit_d13)[1, "est"], 3),
  Adj_R2     = round(pool.r.squared(fit_d13, adjusted = TRUE)[1, "est"], 3),
  B_calisma  = round(summary(pool_d13) %>% filter(term == "calisma_suresi_dk") %>% pull(estimate), 3),
  SE_calisma = round(summary(pool_d13) %>% filter(term == "calisma_suresi_dk") %>% pull(std.error), 3),
  B_dikkat   = round(summary(pool_d13) %>% filter(term == "dikkat_puani") %>% pull(estimate), 3),
  SE_dikkat  = round(summary(pool_d13) %>% filter(term == "dikkat_puani") %>% pull(std.error), 3)
)

cat("Dikkat puanı MAR atama yöntemleri tamamlandı.\n")
## Dikkat puanı MAR atama yöntemleri tamamlandı.
bind_rows(dikkat_sonuclar) %>%
  kable(
    caption   = "Tablo 12. Dikkat Puanı (MAR) - Atama Yöntemleri Karşılaştırması",
    col.names = c("Yöntem", "R²", "Düz. R²", "B (Çalışma)", "SE (Çalışma)",
                  "B (Dikkat)", "SE (Dikkat)"),
    align     = c("l", "c", "c", "c", "c", "c", "c")
  ) %>%
  kable_styling(bootstrap_options = c("hover", "condensed", "bordered"),
                full_width = TRUE, font_size = 12) %>%
  row_spec(0, bold = TRUE, color = "white", background = "#2E4057") %>%
  row_spec(1, background = "#c8e6c9", bold = TRUE) %>%
  row_spec(2:13, color = "#1a1e2e", background = "#d6e4f0") %>%
  pack_rows("% 7 Kayıp", 2, 5,  label_row_css = "background-color: #2E4057; color: white;") %>%
  pack_rows("%10 Kayıp", 6, 9,  label_row_css = "background-color: #2E4057; color: white;") %>%
  pack_rows("%13 Kayıp", 10, 13, label_row_css = "background-color: #2E4057; color: white;") %>%
  footnote(general = "Yeşil satır referans modeli (temiz veri) göstermektedir. MAR mekanizmasında listwise deletion taraflı sonuç üretebilir.",
           general_title = "Not:")
Tablo 12. Dikkat Puanı (MAR) - Atama Yöntemleri Karşılaştırması
Yöntem Düz. R² B (Çalışma) SE (Çalışma) B (Dikkat) SE (Dikkat)
Referans (Temiz Veri) 0.667 0.656 0.123 0.013 2.186 0.121
% 7 Kayıp
%7 - Listwise Deletion 0.668 0.656 0.117 0.013 2.197 0.130
%7 - Ortalama Atama 0.634 0.621 0.117 0.014 2.202 0.136
%7 - Regresyon Ataması 0.630 0.617 0.116 0.014 2.189 0.137
%7 - Çoklu Atama (mice) 0.670 0.659 0.118 0.013 2.221 0.122
%10 Kayıp
%10 - Listwise Deletion 0.668 0.655 0.119 0.014 2.273 0.135
%10 - Ortalama Atama 0.646 0.633 0.125 0.014 2.283 0.137
%10 - Regresyon Ataması 0.650 0.637 0.123 0.014 2.287 0.137
%10 - Çoklu Atama (mice) 0.667 0.656 0.122 0.013 2.212 0.122
%13 Kayıp
%13 - Listwise Deletion 0.649 0.635 0.125 0.015 2.042 0.133
%13 - Ortalama Atama 0.626 0.612 0.130 0.014 2.026 0.137
%13 - Regresyon Ataması 0.626 0.611 0.133 0.015 2.030 0.139
%13 - Çoklu Atama (mice) 0.667 0.657 0.132 0.014 2.076 0.119
Not:
Yeşil satır referans modeli (temiz veri) göstermektedir. MAR mekanizmasında listwise deletion taraflı sonuç üretebilir.

Tablo 12 incelendiğinde MAR mekanizması altında farklı atama yöntemlerinin regresyon sonuçları üzerindeki etkileri MCAR koşuluna kıyasla daha belirgin olmakla birlikte hiçbir koşulda pratik açıdan anlamlı bir sapma gözlemlenmemiştir. Bu durum büyük ölçüde örneklem büyüklüğünden (n = 290) ve dikkat puanı gibi güçlü bir yordayıcının modelde yer almasından kaynaklanmaktadır; söz konusu koşullar kayıp verinin olumsuz etkisini doğal olarak sınırlandırmaktadır. Bununla birlikte yöntemler arasındaki küçük farklılıklar teorik beklentilerle tutarlı bir örüntü sergilemektedir. Ortalama atama R² değerini en fazla düşüren yöntem olarak en zayıf performansı göstermiş; %13 kayıp oranında R² .667’den .626’ya gerilemiş, dikkat puanı katsayısında da en yüksek sapma gözlemlenmiştir. Regresyon ataması ortalama atamaya kıyasla daha iyi performans sergilemiş ancak referans değerlere tam anlamıyla ulaşamamıştır. Çoklu atama yöntemi ise her üç kayıp oranında da referans modele en yakın sonuçları üreterek en iyi performansı sergilemiştir. Bu bulgular gerçek veri setlerinde daha karmaşık kayıp mekanizmaları, daha yüksek kayıp oranları veya daha zayıf yordayıcılar söz konusu olduğunda yöntemler arasındaki farkların çok daha belirginleşeceğini düşündürmektedir.

12 Günden Kalanlar

R ile veri analizi konusuna birinci dönemde ilk başladığımızda oldukça zorlanmıştım. Haftalar ilerledikçe derste ve ödevlerde daha konforlu hissediyordum. Dönem sonunda sanki yeni bir hobi edinmiş gibi sürekli uğraşıyordum. Bu yeni, fazlasıyla teknik hobim için oldukça uzun saatler ayırmaktan keyif alıyordum. Ara tatilde de hemen her gün R ile mesaimiz oluyordu. Ancak tatilin sonuna doğru ortaya çıkan ve kısmen devam eden göz sağlığı problemlerimden dolayı 20-25 gün R ile buluşmalarımız askıya alınmıştı. Bu göreceli kısa zaman diliminin muhtemelen tecrübeli bir R kullanıcısı için böyle olmasa da yeni başlayan bir R öğrencisi için çok büyük bir kayıp olduğunu anlamış bulunuyorum. Zira R konusunda bilgilerde önemli kayıplar görüyorum. Bunu üç ana nedene bağlıyorum:

1.        R öğrenirken yapay zekâyı fazlasıyla kullanmak

2.        Daha yeni olduğum için bilgi ve becerilerin zihnimde çok güçlü bağlantılar oluşturmamış olması

3.        Yaş etkisi

Tüm bu gerilmenin yanı sıra veri analizi konusunda bakış açımın gelişmesi, R ile yapılabilecekler konusunda ufuk açıcı öngörüler edinmem, R kodlarını okuma ve hataları görme becerilerim ile yapay zekâ araçlarından nasıl destek alabileceğim konusunda kayda değer ilerlemeler gösterdiğimi düşünüyorum. Bu ödevi yaparken de kod yazmadan çok derste anlatılan konuların mantığını ve nasıl uygulayabileceğimi anlamaya çalıştım. Zira ödevdeki tüm fikirlere sahip çıkabilirim ama tüm kodların yazarının Claude Sonnet 4.6 olduğunu belirtmeliyim. Bu çalışma yönteminin önümüzdeki yıllarda geçerli bir çalışma yöntemi olacağı kanaatindeyim.

Bu dersten sonra çoklu atama yönteminde hangi mekanizmaların nasıl kullanıldığını merak ediyorum. Çünkü acaba şöyle bir yöntemle mi atanıyor veya böyle bir yöntem var mı:

Adım 1: Kayıp verinin olduğu değişken ile diğer değişkenler arasındaki korelasyonlar incelenir.

Adım 2: En yüksek korelasyonların olduğu değişkenler kullanılarak kümeleme analizi yapılır (Hangi değişkenlerin böyle bir analize dahil edileceğini gösteren teorik ve matematiksel temeller benim henüz ulaşmadığım bir yerlerde vardır diye düşünüyorum).

Adım 3: Kayıp veriye kümeleme analizi sonucunda en çok benzediği grubun veya grupların ortalaması atanır (Hangi grup veya grupların ortalamasının alınabileceğini açıklayan istatistiksel temellerin var olduğunu düşünüyorum-henüz ben bilmiyorum).

Bu işlemleri kolayca yapacak bir R paketi var mı veya hazırlanabilir mi?

Ya da atama yöntemlerinden herhangi biri arka planda bu işlemleri mi yapıyor?

Ya da ben çok sınırlı istatistik bilgimle saçmalıyor muyum?