Bu çalışmada, Hox, Moerbeek ve van de Schoot (2018) tarafından Multilevel Analysis: Techniques and Applications kitabında kullanılan popülerlik veri seti üzerinde Hiyerarşik Doğrusal Modelleme (HLM) uygulaması yapılacaktır. Analiz, öğrencilerin (Düzey-1) sınıflar (Düzey-2) içinde yuvalandığı iki düzeyli bir veri yapısında, öğrencilerin akranları tarafından değerlendirilen popülerliğini yordayan değişkenler incelenmiştir. Konunun teorik kısmı bir önceki ödev günlüğünde incelendiği için bu günlükte uygulamaya odaklanılmıştır.
Çalışmada kullanılan veri seti, Hox ve arkadaşlarının (2018) çok
düzeyli analiz kitabında öğretim amaçlı olarak sunulan
popular2.sav dosyasıdır. Veri,
Hollanda’daki ilkokul sınıflarında yürütülen bir araştırmadan derlenmiş
ve literatürde HLM uygulamalarının kanonik örneklerinden biri haline
gelmiştir.
Veri yapısı:
Toplam gözlem (Düzey-1): 2.000 öğrenci
Toplam küme (Düzey-2): 100 sınıf
Sınıf başına ortalama öğrenci: 20
Bağımlı değişken: Akran tarafından değerlendirilen popülerlik
Yuvalanma yapısı: Öğrenciler → Sınıflar
Veri setindeki orijinal değişken isimleri İngilizce ve teknik
kısaltmalardan oluşmaktadır (örn. extrav,
texp). Raporun Türkçe anlaşılırlığını artırmak ve
okuyucunun her değişkenin neyi ölçtüğünü kod içinde takip edebilmesi
için tüm değişkenler anlamlı Türkçe karşılıklarıyla yeniden
adlandırılacaktır.
| Orijinal İsim | Türkçe Karşılık | Düzey | Tür | Açıklama |
|---|---|---|---|---|
pupil |
ogrenci_id |
L1 | Kimlik | Öğrenci kimlik numarası |
class |
sinif |
L2 | Kimlik (gruplayıcı) | Sınıf kimlik numarası |
extrav |
disadonukluk |
L1 | Sürekli (1–10) | Öğrencinin dışadönüklük puanı |
sex |
cinsiyet |
L1 | İkili (0/1) | Öğrencinin cinsiyeti |
texp |
ogretmen_deneyimi |
L2 | Sürekli (yıl) | Sınıf öğretmeninin mesleki deneyimi |
popular |
populerlik |
L1 | Sürekli (0–10) | Bağımlı değişken: Akran değerlendirmesi |
popteach |
— | — | — | Bu çalışmaya dahil edilmeyecek |
Modellerde merkezleme stratejileri gereği aşağıdaki değişkenler veri setinden türetilecektir:
| Türetilen İsim | Hesaplanış | Düzey | Amaç |
|---|---|---|---|
disadonukluk_mrk |
disadonukluk − mean(disadonukluk by sinif) |
L1 | Grup-ortalamada merkezleme (CWC) — bireysel etki |
sinif_disadonukluk |
mean(disadonukluk by sinif) |
L2 | Sınıf ortalama dışadönüklük iklimi — bağlamsal etki |
ogretmen_deneyimi_mrk |
ogretmen_deneyimi − mean(ogretmen_deneyimi) |
L2 | Büyük ortalamada merkezleme (CGM) — yorumlanabilir kesişim |
disadonukluk — Dışadönüklük (Ana
yordayıcı): Dışadönüklük, Big Five kişilik modelinin beş temel
boyutundan biridir; sosyal etkileşime yönelme, enerji, atılganlık ve
olumlu duygulanım gibi özellikleri kapsar. Akran popülerliği
literatüründe dışadönüklük, sosyal görünürlüğü ve akran etkileşim
sıklığını artırması bakımından popülerliğin en tutarlı yordayıcılarından
biri olarak belirlenmiştir. Bu değişken grup-ortalamada
merkezleme (CWC) ile dönüştürülecektir; bunun gerekçesi, Enders
ve Tofighi (2007) rehberi uyarınca çapraz düzey etkileşim testi
planlandığında within-group (sınıf içi bireysel) bileşenin saf biçimde
izole edilmesi gereğidir.
cinsiyet — Cinsiyet (Kontrol
değişkeni): İlkokul yaşlarında cinsiyetin akran ilişkilerinde
ve popülerlik atıflarında belirleyici rol oynadığı çokça belgelenmiştir.
Bu değişken, dışadönüklüğün etkisinin cinsiyet üzerinden dolaylı
yürümemesi için modele kontrol değişkeni olarak dahil
edilmekte; ham 0/1 kodlamasıyla bırakılmaktadır çünkü ikili
değişkenlerde merkezleme kesişim yorumunu karmaşıklaştırır.
ogretmen_deneyimi — Öğretmen Deneyimi (Bağlamsal
yordayıcı): Deneyimli öğretmenlerin sınıf yönetimi becerileri,
akran dinamiklerini düzenleme kapasitesi ve öğrencilere sunduğu dengeli
etkileşim ortamı, sınıfın ortalama popülerlik düzeyini ve bireysel
popülerlik yordayıcılarının gücünü etkileyebilir. Hox (2018)’in bu veri
setindeki klasik bulgusu, deneyimli öğretmenlerin sınıflarında
dışadönüklüğün popülerlik üzerindeki etkisinin zayıfladığıdır — yani bu
sınıflarda içedönük çocuklar da popüler olabilmektedir. Bu değişken
büyük-ortalamada merkezleme (CGM) ile
dönüştürülecektir; bu tercih hem kesişim yorumlanabilirliğini artırır
hem de çapraz düzey etkileşimlerin yorumunu kolaylaştırır.
sinif_disadonukluk — Sınıfın Ortalama
Dışadönüklük İklimi (Kompozisyon etkisi): Bir sınıfın “ortalama
dışadönüklük düzeyi” o sınıfın sosyal iklimi hakkında bağlamsal bilgi
verir. Bu değişken olmadan, disadonukluk’un etkisi bireysel
ve bağlamsal bileşenlerin karışımını yansıtır; dahil edildiğinde
within-class (bireysel etki) ve between-class (kompozisyon etkisi)
bileşenleri birbirinden ayrıştırılmış olur (Hox ve diğerleri, 2018).
Büyük-ortalamada merkezleme ile dönüştürülecektir.
lme4 karma modellerin temel paketidir;
REML ve ML tahmini yapar. lmerTest sabit
etki katsayılarına Satterthwaite yaklaşımıyla p-değerleri ekler —
standart lme4 bunları sunmaz.
performance ICC, Nakagawa-Schielzeth R² ve
model tanıları için; broom.mixed model
çıktılarını düzenli veri çerçevesine dönüştürmek için;
gt ile
kableExtra profesyonel tablo üretimi için;
ggplot2 ve
patchwork görselleştirmeler için
kullanılacaktır.
# Veri işleme
library(haven) # SPSS (.sav) dosyası okuma
library(dplyr) # Veri manipülasyonu
library(tidyr) # Veri yeniden şekillendirme
# Karma modeller
library(lme4) # HLM çekirdek paketi (lmer fonksiyonu)
library(lmerTest) # Satterthwaite p-değerleri
library(performance) # ICC, R², model tanıları
# Çıktı düzenleme
library(broom.mixed) # tidy() fonksiyonu karma modeller için
library(gt) # Profesyonel tablolar
library(kableExtra) # Alternatif tablo paketi
# Görselleştirme
library(ggplot2)
library(patchwork) # Çoklu grafik birleştirme
tema_hlm <- theme_minimal(base_size = 13) +
theme(
plot.background = element_rect(fill = "#1a1e2e", color = NA),
panel.background = element_rect(fill = "#1a1e2e", color = NA),
panel.grid.major = element_line(color = "#2e3557"),
panel.grid.minor = element_line(color = "#252a3d"),
text = element_text(color = "#e8e8e8"),
axis.text = element_text(color = "#c9d1d9"),
axis.title = element_text(color = "#9dc9e0", face = "bold"),
plot.title = element_text(color = "#7eb8d4", face = "bold", size = 14),
plot.subtitle = element_text(color = "#b8d4e6"),
legend.background = element_rect(fill = "#1a1e2e", color = NA),
legend.key = element_rect(fill = "#1a1e2e", color = NA),
strip.background = element_rect(fill = "#2e3557", color = NA),
strip.text = element_text(color = "#9dc9e0", face = "bold")
)
# gt tabloları için ortak stil fonksiyonu
stil_gt <- function(tbl) {
tbl |>
tab_options(
table.background.color = "#1a1e2e",
table.font.color = "#e8e8e8",
table.font.size = px(15),
heading.background.color = "#2e3557",
heading.title.font.size = px(17),
column_labels.background.color = "#2e3557",
column_labels.font.weight = "bold",
row.striping.background_color = "#252a3d",
row.striping.include_table_body = TRUE,
table.border.top.color = "#3a4060",
table.border.bottom.color = "#3a4060"
) |>
opt_row_striping()
}# Veri seti orijinal dosya yolundan okunuyor
popular_ham <- read_sav("~/Desktop/OLC733/HLM/popular2.sav")
# Başlangıç kontrolü
cat("Satır sayısı :", nrow(popular_ham), "\n")## Satır sayısı : 2000
## Sütun sayısı : 15
## Değişkenler : pupil, class, extrav, sex, texp, popular, popteach, Zextrav, Zsex, Ztexp, Zpopular, Zpopteach, Cextrav, Ctexp, Csex
# Sadece çalışmamızda kullanacağımız değişkenleri seçip Türkçeleştiriyoruz.
# popteach değişkenini dışarıda bırakıyoruz (bağımlı değişkenle kavramsal üst üste binme).
veri <- popular_ham |>
select(
ogrenci_id = pupil,
sinif = class,
disadonukluk = extrav,
cinsiyet = sex,
ogretmen_deneyimi = texp,
populerlik = popular
) |>
mutate(
# sinif'i faktör olarak işaretliyoruz — lmer gruplayıcı olarak tanıyacak
sinif = as.factor(sinif),
# cinsiyet'i de etiketli faktör yapıyoruz (görsel okunurluk için)
cinsiyet_fct = factor(cinsiyet, levels = c(0, 1), labels = c("Erkek", "Kız"))
)
# Yapı kontrolü
head(veri)# Temel yapı tablosu
ozet_df <- data.frame(
Ozellik = c(
"Toplam öğrenci sayısı (L1)",
"Toplam sınıf sayısı (L2)",
"Sınıf başına minimum öğrenci",
"Sınıf başına maksimum öğrenci",
"Sınıf başına ortalama öğrenci",
"Eksik veri (populerlik)",
"Eksik veri (disadonukluk)",
"Eksik veri (ogretmen_deneyimi)"
),
Deger = c(
nrow(veri),
length(unique(veri$sinif)),
min(table(veri$sinif)),
max(table(veri$sinif)),
round(mean(table(veri$sinif)), 2),
sum(is.na(veri$populerlik)),
sum(is.na(veri$disadonukluk)),
sum(is.na(veri$ogretmen_deneyimi))
)
)
gt(ozet_df) |>
tab_header(title = "Veri Yapısının Özeti") |>
cols_label(Ozellik = "Özellik", Deger = "Değer") |>
stil_gt()| Veri Yapısının Özeti | |
| Özellik | Değer |
|---|---|
| Toplam öğrenci sayısı (L1) | 2000 |
| Toplam sınıf sayısı (L2) | 100 |
| Sınıf başına minimum öğrenci | 16 |
| Sınıf başına maksimum öğrenci | 26 |
| Sınıf başına ortalama öğrenci | 20 |
| Eksik veri (populerlik) | 0 |
| Eksik veri (disadonukluk) | 0 |
| Eksik veri (ogretmen_deneyimi) | 0 |
Veri seti 100 sınıfa dağılmış 2.000 öğrenciden oluşmaktadır. Sınıf başına öğrenci sayısı 16 ile 26 arasında değişmekte olup ortalama 20’dir; bu da sınıflar arası görece dengeli bir dağılıma işaret etmektedir. Popülerlik, dışadönüklük ve öğretmen deneyimi değişkenlerinde eksik veri bulunmamaktadır; dolayısıyla analizlere veri silme ya da atama işlemi uygulanmadan geçilebilir.
betimsel_surekli <- veri |>
summarise(
across(
c(populerlik, disadonukluk, ogretmen_deneyimi),
list(
N = ~sum(!is.na(.)),
Ort = ~round(mean(., na.rm = TRUE), 2),
SS = ~round(sd(., na.rm = TRUE), 2),
Min = ~round(min(., na.rm = TRUE), 2),
Max = ~round(max(., na.rm = TRUE), 2),
Medyan = ~round(median(., na.rm = TRUE), 2)
),
.names = "{.col}__{.fn}"
)
) |>
pivot_longer(everything(), names_to = c("Degisken", "Istatistik"),
names_sep = "__", values_to = "Deger") |>
pivot_wider(names_from = Istatistik, values_from = Deger) |>
mutate(
Degisken = recode(Degisken,
"populerlik" = "Popülerlik",
"disadonukluk" = "Dışadönüklük",
"ogretmen_deneyimi" = "Öğretmen deneyimi"
)
)
gt(betimsel_surekli) |>
tab_header(title = "Sürekli Değişkenlerin Betimsel İstatistikleri") |>
cols_label(Degisken = "Değişken") |>
stil_gt()| Sürekli Değişkenlerin Betimsel İstatistikleri | ||||||
| Değişken | N | Ort | SS | Min | Max | Medyan |
|---|---|---|---|---|---|---|
| Popülerlik | 2000 | 5.08 | 1.38 | 0 | 9.5 | 5.1 |
| Dışadönüklük | 2000 | 5.21 | 1.26 | 1 | 10.0 | 5.0 |
| Öğretmen deneyimi | 2000 | 14.26 | 6.55 | 2 | 25.0 | 15.0 |
Popülerlik (Ort = 5.08) ve dışadönüklük (Ort = 5.21) değişkenleri birbirine yakın ortalamalara ve standart sapmalara sahip olup her ikisinde de ortalama ile medyan neredeyse örtüşmektedir; bu durum yaklaşık simetrik bir dağılıma işaret eder. Öğretmen deneyimi ise ortalama 14.26 yıl ve oldukça yüksek bir standart sapma (6.55) ile geniş bir yayılım göstermektedir; 2 ile 25 yıl arasında değişen bu aralık, örneklemde hem görece yeni hem de deneyimli öğretmenlerin temsil edildiğini ortaya koymaktadır.
g1 <- ggplot(veri, aes(x = populerlik)) +
geom_histogram(fill = "#7eb8d4", color = "#1a1e2e", bins = 25) +
labs(title = "Popülerlik", x = NULL, y = "Frekans") +
tema_hlm
g2 <- ggplot(veri, aes(x = disadonukluk)) +
geom_histogram(fill = "#d4a560", color = "#1a1e2e", bins = 10) +
labs(title = "Dışadönüklük", x = NULL, y = NULL) +
tema_hlm
# ogretmen_deneyimi sınıf düzeyinde; sınıf başına tek değer alıp gösterelim
veri_sinif <- veri |>
group_by(sinif) |>
summarise(ogretmen_deneyimi = first(ogretmen_deneyimi), .groups = "drop")
g3 <- ggplot(veri_sinif, aes(x = ogretmen_deneyimi)) +
geom_histogram(fill = "#8ed47e", color = "#1a1e2e", bins = 15) +
labs(title = "Öğretmen Deneyimi (Sınıf düzeyi)", x = NULL, y = NULL) +
tema_hlm
g1 + g2 + g3cinsiyet_tbl <- veri |>
count(cinsiyet_fct) |>
mutate(Oran = round(n / sum(n) * 100, 1)) |>
rename(Cinsiyet = cinsiyet_fct, Frekans = n, `Yüzde (%)` = Oran)
gt(cinsiyet_tbl) |>
tab_header(title = "Cinsiyet Dağılımı") |>
stil_gt()| Cinsiyet Dağılımı | ||
| Cinsiyet | Frekans | Yüzde (%) |
|---|---|---|
| Erkek | 989 | 49.5 |
| Kız | 1011 | 50.5 |
Yorum: Cinsiyet dağılımı oldukça dengelidir; 989 erkek (%49.5) ve 1011 kız (%50.5) öğrenci ile gruplar arasında neredeyse eşit bir temsil sağlanmıştır. Bu denge, cinsiyet değişkeninin analizlerde güvenilir karşılaştırmalara olanak tanıması açısından olumludur.
kor_df <- veri |>
select(populerlik, disadonukluk, cinsiyet, ogretmen_deneyimi) |>
cor(use = "complete.obs") |>
round(3)
kor_tbl <- as.data.frame(kor_df) |>
tibble::rownames_to_column("Değişken")
gt(kor_tbl) |>
tab_header(title = "Değişkenler Arası Pearson Korelasyonları") |>
data_color(
columns = c(populerlik, disadonukluk, cinsiyet, ogretmen_deneyimi),
colors = scales::col_numeric(
palette = c("#c06060", "#2d2820", "#6ab85a"),
domain = c(-1, 1)
)
) |>
stil_gt()| Değişkenler Arası Pearson Korelasyonları | ||||
| Değişken | populerlik | disadonukluk | cinsiyet | ogretmen_deneyimi |
|---|---|---|---|---|
| populerlik | 1.000 | 0.316 | 0.568 | 0.290 |
| disadonukluk | 0.316 | 1.000 | 0.089 | -0.387 |
| cinsiyet | 0.568 | 0.089 | 1.000 | 0.073 |
| ogretmen_deneyimi | 0.290 | -0.387 | 0.073 | 1.000 |
Yorum: En güçlü ilişki cinsiyet ile popülerlik arasında gözlemlenmektedir (r = 0.568); kız öğrencilerin popülerlik puanları belirgin biçimde daha yüksektir. Popülerlik ile dışadönüklük arasında orta düzeyde pozitif bir ilişki (r = 0.316) bulunurken, dışadönüklük ile öğretmen deneyimi arasında negatif yönlü bir korelasyon (r = −0.387) dikkat çekmektedir — deneyimli öğretmenlerin sınıflarındaki öğrenciler daha düşük dışadönüklük puanları almaktadır. Cinsiyet ile dışadönüklük (r = 0.089) ve cinsiyet ile öğretmen deneyimi (r = 0.073) arasındaki ilişkiler ise pratikte ihmal edilebilir düzeydedir.
HLM modellerinde yordayıcıların nasıl merkezlendiği, hem sabit etki katsayılarının yorumunu hem de çapraz düzey etkileşimlerin anlamlılığını doğrudan etkiler. Bu bölümde, Enders ve Tofighi (2007) rehberi izlenerek her yordayıcı için uygun merkezleme stratejisi uygulanır.
Neden merkezleme şart? Ham skorlarla kurulan bir modelde kesişim (\(\beta_0\)), “tüm yordayıcıların sıfır olduğu” varsayımsal bir bireyin değerini verir. Dışadönüklük puanı 0 olan bir öğrenci ya da deneyimi 0 yıl olan bir öğretmen veri aralığında bulunmadığından bu değer anlamsızdır. Merkezleme, kesişimi teorik olarak yorumlanabilir bir referans noktasına (ortalamaya) taşır.
Enders ve Tofighi (2007) rehberi:
L1 yordayıcı + çapraz düzey etkileşim testi varsa → CWC (grup-ortalamada merkezleme). Çünkü CWC, L1 değişkeninin yalnızca within-group bileşenini izole eder; between-group bileşeni L2 değişkeni olarak ayrıca modele girer. Bu, çapraz düzey etkileşimin “saf” bir testini sağlar.
L2 yordayıcıları → CGM (büyük ortalamada merkezleme). L2’de zaten tek bir ortalama vardır; CGM yalnızca kesişim yorumunu kolaylaştırır, parametre yorumunu değiştirmez.
veri <- veri |>
group_by(sinif) |>
mutate(
# L2: Sınıfın ortalama dışadönüklüğü (bağlamsal değişken — her öğrenci satırında tekrarlanır)
sinif_disadonukluk = mean(disadonukluk, na.rm = TRUE),
# L1: Grup-ortalamada merkezlenmiş dışadönüklük (CWC)
disadonukluk_mrk = disadonukluk - sinif_disadonukluk
) |>
ungroup() |>
mutate(
# L2: Büyük-ortalamada merkezlenmiş öğretmen deneyimi (CGM)
ogretmen_deneyimi_mrk = ogretmen_deneyimi - mean(ogretmen_deneyimi, na.rm = TRUE),
# sinif_disadonukluk'u da CGM ile merkezleyelim (L2 değişkeni olarak)
sinif_disadonukluk_mrk = sinif_disadonukluk - mean(sinif_disadonukluk, na.rm = TRUE)
)
# Merkezleme sonrası kontrol: merkezlenmiş değişkenlerin ortalamaları 0 civarında olmalı
kontrol <- data.frame(
Degisken = c("disadonukluk_mrk", "ogretmen_deneyimi_mrk", "sinif_disadonukluk_mrk"),
Ortalama = c(
round(mean(veri$disadonukluk_mrk, na.rm = TRUE), 4),
round(mean(veri$ogretmen_deneyimi_mrk, na.rm = TRUE), 4),
round(mean(veri$sinif_disadonukluk_mrk, na.rm = TRUE), 4)
),
SS = c(
round(sd(veri$disadonukluk_mrk, na.rm = TRUE), 3),
round(sd(veri$ogretmen_deneyimi_mrk, na.rm = TRUE), 3),
round(sd(veri$sinif_disadonukluk_mrk, na.rm = TRUE), 3)
),
Aciklama = c(
"CWC: sınıf içi bireysel dışadönüklük",
"CGM: büyük-ortalamadan sapma (yıl)",
"CGM: sınıf ikliminin genel ortalamadan sapması"
)
)
gt(kontrol) |>
tab_header(
title = "Merkezlenmiş Değişkenlerin Kontrolü",
subtitle = "Merkezleme sonrası ortalamalar 0'a çok yakın olmalıdır"
) |>
cols_label(
Degisken = "Değişken",
Ortalama = "Ortalama",
SS = "Standart Sapma",
Aciklama = "Açıklama"
) |>
stil_gt()| Merkezlenmiş Değişkenlerin Kontrolü | |||
| Merkezleme sonrası ortalamalar 0'a çok yakın olmalıdır | |||
| Değişken | Ortalama | Standart Sapma | Açıklama |
|---|---|---|---|
| disadonukluk_mrk | 0 | 1.059 | CWC: sınıf içi bireysel dışadönüklük |
| ogretmen_deneyimi_mrk | 0 | 6.552 | CGM: büyük-ortalamadan sapma (yıl) |
| sinif_disadonukluk_mrk | 0 | 0.687 | CGM: sınıf ikliminin genel ortalamadan sapması |
Merkezlenmiş değişkenlerin ortalamalarının tam olarak 0 çıkması beklenen bir durumdur; merkezleme işlemi her gözlemden grup ortalamasını çıkardığı için sonuç matematiksel olarak her zaman sıfırdır. Standart sapmalar ise ham değişkenlerle aynı kalmaktadır çünkü merkezleme dağılımın şeklini ve yayılımını değiştirmez, yalnızca konumunu kaydırır. Bu tablo, CWC (sınıf içi) ve CGM (büyük ortalama) merkezleme işlemlerinin doğru uygulandığını teyit etmektedir.
Hiçbir yordayıcının olmadığı bu model, popülerlikteki toplam varyansı iki bileşene ayırır: sınıf-içi varyans (\(\sigma^2\)) ve sınıflar-arası varyans (\(\tau_{00}\)). Bu modelin temel çıktısı Sınıfiçi Korelasyon Katsayısı’dır (ICC) — HLM’ye geçmenin gerekli olup olmadığının kanıtı.
Boş Model:
(1) ICC olmadan HLM’ye gerek olup olmadığı bilinemez;
(2) sonraki modellerin açıklayacağı varyansa bir temel (baseline) oluşturur — “L1 yordayıcıları sınıf-içi varyansın yüzde kaçını açıkladı?” sorusu ancak bu modelin varyansına referansla cevaplanabilir;
(3) deviance, AIC, BIC değerleri sonraki modellerle karşılaştırma için kaydedilir.
Düzey 1 (Öğrenci): \[populerlik_{ij} = \beta_{0j} + r_{ij}\]
Düzey 2 (Sınıf): \[\beta_{0j} = \gamma_{00} + u_{0j}\]
Birleşik: \[populerlik_{ij} = \gamma_{00} + u_{0j} + r_{ij}\]
Burada \(\gamma_{00}\) tüm örneklemin ortalama popülerliği; \(u_{0j}\) sınıfların bu ortalamadan sapması; \(r_{ij}\) öğrencinin kendi sınıfının ortalamasından sapmasıdır.
sabit_1 <- broom.mixed::tidy(model_1, effects = "fixed", conf.int = TRUE) |>
mutate(
Terim = "γ₀₀ (Genel kesişim)",
across(c(estimate, std.error, statistic, conf.low, conf.high),
~round(.x, 3)),
p.value = ifelse(is.na(p.value), "—", format.pval(p.value, digits = 3))
) |>
select(Terim, estimate, std.error, statistic, df, p.value, conf.low, conf.high)
gt(sabit_1) |>
tab_header(title = "Model 1 — Sabit Etkiler") |>
cols_label(
estimate = "Kestirim", std.error = "SE", statistic = "t",
df = "df", p.value = "p",
conf.low = "95% Alt", conf.high = "95% Üst"
) |>
stil_gt()| Model 1 — Sabit Etkiler | |||||||
| Terim | Kestirim | SE | t | df | p | 95% Alt | 95% Üst |
|---|---|---|---|---|---|---|---|
| γ₀₀ (Genel kesişim) | 5.078 | 0.087 | 58.103 | 98.90973 | <2e-16 | 4.904 | 5.251 |
Yorum: Hiçbir yordayıcı eklenmeden öğrencilerin genel popülerlik ortalaması 5.078 olarak kestirilmiştir (p < .001). %95 güven aralığı [4.904 – 5.251] oldukça dar olup genel kesişim kestiriminin yüksek hassasiyetle elde edildiğini göstermektedir. Bu değer, sonraki modellerde yordayıcıların etkisini karşılaştırmak için referans noktası işlevi görecektir.
# Varyans bileşenleri
vc_1 <- as.data.frame(VarCorr(model_1))
tau00_1 <- vc_1$vcov[vc_1$grp == "sinif"]
sigma2_1 <- vc_1$vcov[vc_1$grp == "Residual"]
icc_1 <- tau00_1 / (tau00_1 + sigma2_1)
varyans_1 <- data.frame(
Bilesen = c("τ₀₀ — Sınıflar arası kesişim varyansı",
"σ² — Sınıf içi artık varyans",
"Toplam varyans (τ₀₀ + σ²)",
"ICC (Sınıfiçi Korelasyon)"),
Deger = c(round(tau00_1, 3),
round(sigma2_1, 3),
round(tau00_1 + sigma2_1, 3),
round(icc_1, 3)),
Yorum = c(
"Sınıfların ortalama popülerlikte farklılaşma düzeyi",
"Sınıf içi bireysel farklılıkların büyüklüğü",
"Popülerlikteki toplam varyans",
"Toplam varyansın sınıflar arası olan oranı"
)
)
gt(varyans_1) |>
tab_header(title = "Model 1 — Varyans Bileşenleri ve ICC") |>
cols_label(Bilesen = "Bileşen", Deger = "Değer", Yorum = "Yorum") |>
stil_gt()| Model 1 — Varyans Bileşenleri ve ICC | ||
| Bileşen | Değer | Yorum |
|---|---|---|
| τ₀₀ — Sınıflar arası kesişim varyansı | 0.702 | Sınıfların ortalama popülerlikte farklılaşma düzeyi |
| σ² — Sınıf içi artık varyans | 1.222 | Sınıf içi bireysel farklılıkların büyüklüğü |
| Toplam varyans (τ₀₀ + σ²) | 1.924 | Popülerlikteki toplam varyans |
| ICC (Sınıfiçi Korelasyon) | 0.365 | Toplam varyansın sınıflar arası olan oranı |
Yorum: ICC = 0.365 değeri, popülerlikteki toplam varyansın yaklaşık %37’sinin sınıflar arasındaki farklılıklardan kaynaklandığını göstermektedir. Bu oran, öğrencilerin hangi sınıfta olduğunun popülerlik düzeylerini önemli ölçüde etkilediğine işaret etmekte olup çok düzeyli modelleme kullanımını açıkça gerekli kılmaktadır.
n_bar <- mean(table(veri$sinif))
guvenirlik_1 <- tau00_1 / (tau00_1 + sigma2_1 / n_bar)
guv_df <- data.frame(
Olcu = c("Ortalama sınıf büyüklüğü (n̄)",
"Kesişim güvenirliği (λ₀₀)"),
Deger = c(round(n_bar, 2), round(guvenirlik_1, 3)),
Kriter = c("—", "λ > .70 → yüksek; > .90 → mükemmel")
)
gt(guv_df) |>
tab_header(title = "Model 1 — Kesişim Güvenirliği") |>
cols_label(Olcu = "Ölçü", Deger = "Değer", Kriter = "Kriter") |>
stil_gt()| Model 1 — Kesişim Güvenirliği | ||
| Ölçü | Değer | Kriter |
|---|---|---|
| Ortalama sınıf büyüklüğü (n̄) | 20.00 | — |
| Kesişim güvenirliği (λ₀₀) | 0.92 | λ > .70 → yüksek; > .90 → mükemmel |
sişim güvenirliği λ₀₀ = 0.92 olup “mükemmel” düzeyin üzerindedir. Bu, sınıf ortalamalarının birbirinden güvenilir biçimde ayırt edilebildiğini ve sınıf düzeyindeki farklılıkların rastgele dalgalanmadan değil gerçek yapısal farklardan kaynaklandığını göstermektedir. Sınıf başına ortalama 20 öğrencilik grup büyüklüğü bu yüksek güvenirliğe önemli katkı sağlamaktadır.
gamma00_1 <- fixef(model_1)[1]
alt <- gamma00_1 - 1.96 * sqrt(tau00_1)
ust <- gamma00_1 + 1.96 * sqrt(tau00_1)
pvr_df <- data.frame(
Olcu = c("γ₀₀ (Genel ortalama popülerlik)",
"%95 Olası Değerler Alt Sınırı",
"%95 Olası Değerler Üst Sınırı",
"Aralık Genişliği"),
Deger = c(round(gamma00_1, 3),
round(alt, 3),
round(ust, 3),
round(ust - alt, 3))
)
gt(pvr_df) |>
tab_header(
title = "Sınıflar Arası %95 Olası Değerler Aralığı",
subtitle = "γ₀₀ ± 1.96 × √τ₀₀ — sınıfların ortalama popülerlikte hangi aralıkta yayıldığını gösterir"
) |>
cols_label(Olcu = "Ölçü", Deger = "Değer") |>
stil_gt()| Sınıflar Arası %95 Olası Değerler Aralığı | |
| γ₀₀ ± 1.96 × √τ₀₀ — sınıfların ortalama popülerlikte hangi aralıkta yayıldığını gösterir | |
| Ölçü | Değer |
|---|---|
| γ₀₀ (Genel ortalama popülerlik) | 5.078 |
| %95 Olası Değerler Alt Sınırı | 3.436 |
| %95 Olası Değerler Üst Sınırı | 6.720 |
| Aralık Genişliği | 3.285 |
Yorum: Sınıf ortalamaları %95 olasılıkla 3.436 ile 6.720 arasında yayılmaktadır. Yaklaşık 3.3 puanlık bu aralık, sınıflar arasında popülerlik açısından kayda değer farklılıklar olduğunu somutlaştırmaktadır — en düşük ortalamaya sahip sınıf ile en yüksek arasında neredeyse ölçek genişliğinin üçte biri kadar fark vardır. Bu durum, sınıf düzeyinde yordayıcılar (örn. öğretmen deneyimi) eklenerek bu farklılığın açıklanmasının gerekliliğini desteklemektedir.
uyum_1 <- data.frame(
Olcu = c("Deviance (−2LL)", "AIC", "BIC", "logLik"),
Deger = c(round(-2 * as.numeric(logLik(model_1)), 2),
round(AIC(model_1), 2),
round(BIC(model_1), 2),
round(as.numeric(logLik(model_1)), 2))
)
gt(uyum_1) |>
tab_header(title = "Model 1 — Uyum İstatistikleri") |>
cols_label(Olcu = "Ölçü", Deger = "Değer") |>
stil_gt()| Model 1 — Uyum İstatistikleri | |
| Ölçü | Değer |
|---|---|
| Deviance (−2LL) | 6330.51 |
| AIC | 6336.51 |
| BIC | 6353.31 |
| logLik | -3165.25 |
Deviance (6330.51), AIC (6336.51) ve BIC (6353.31) değerleri boş modelin temel uyum düzeyini yansıtmaktadır. Bu değerler tek başlarına yorumlanmazlar; sonraki modellerde yordayıcılar eklendikçe bu referans değerleriyle karşılaştırılarak modelin iyileşip iyileşmediği değerlendirilecektir. Deviance farkı ki-kare testiyle, AIC ve BIC ise “küçük olan daha iyi” ilkesiyle karşılaştırılacaktır.
Boş model sonuçlarına göre örneklemdeki öğrencilerin genel popülerlik ortalaması 5.078’dir (p < .001). ICC = 0.365 değeri, popülerlikteki toplam varyansın yaklaşık %37’sinin sınıflar arasındaki farklılıklardan kaynaklandığını ortaya koymaktadır; bu oran, HLM kullanımını gerekli kılan eşik olan .05’in çok üzerindedir. Kesişim güvenirliği λ₀₀ = 0.92 ile mükemmel düzeyde olup sınıf ortalamalarının güvenilir biçimde ayırt edilebildiğini göstermektedir. Sınıf ortalamaları %95 olasılıkla 3.44 ile 6.72 arasında yayılmakta, bu da yaklaşık 3.3 puanlık pratik açıdan anlamlı bir farklılığa işaret etmektedir. Bir sonraki adımda bu sınıflar arası farklılığı açıklamak üzere Level-1 yordayıcılar (cinsiyet, dışadönüklük) modele eklenecektir.
Bu modelde Düzey-2 yordayıcıları (ogretmen_deneyimi_mrk
ve sinif_disadonukluk_mrk) kesişim üzerine eklenir. Amaç,
sınıflar arası popülerlik farklılıklarının ne kadarının bu sınıf
özellikleriyle açıklanabildiğini test etmektir.
Önce L2 yordayıcılarını eklemek hocanın ve Hox (2018)’in önerdiği yoldur. Bu sıralama Düzey-2 varyansını (\(\tau_{00}\)) açıklama sorusuna odaklanır. L1 yordayıcılarını eklemeden önce sınıflar-arası farklılıkların bağlamsal kaynaklarını görmek, modelin hiyerarşik mantığıyla uyumludur.
Düzey 1: \[populerlik_{ij} = \beta_{0j} + r_{ij}\]
Düzey 2: \[\beta_{0j} = \gamma_{00} + \gamma_{01} \cdot ogretmen\_deneyimi\_mrk_j + \gamma_{02} \cdot sinif\_disadonukluk\_mrk_j + u_{0j}\]
sabit_2 <- broom.mixed::tidy(model_2, effects = "fixed", conf.int = TRUE) |>
mutate(
Terim = recode(term,
"(Intercept)" = "γ₀₀ (Kesişim)",
"ogretmen_deneyimi_mrk" = "γ₀₁ (Öğretmen deneyimi)",
"sinif_disadonukluk_mrk" = "γ₀₂ (Sınıf dışadönüklük iklimi)"
),
across(c(estimate, std.error, statistic, conf.low, conf.high),
~round(.x, 3)),
p.value = ifelse(is.na(p.value), "—", format.pval(p.value, digits = 3))
) |>
select(Terim, estimate, std.error, statistic, df, p.value, conf.low, conf.high)
gt(sabit_2) |>
tab_header(title = "Model 2 — Sabit Etkiler") |>
cols_label(
estimate = "Kestirim", std.error = "SE", statistic = "t",
df = "df", p.value = "p",
conf.low = "95% Alt", conf.high = "95% Üst"
) |>
stil_gt()| Model 2 — Sabit Etkiler | |||||||
| Terim | Kestirim | SE | t | df | p | 95% Alt | 95% Üst |
|---|---|---|---|---|---|---|---|
| γ₀₀ (Kesişim) | 5.074 | 0.067 | 75.227 | 96.82318 | < 2e-16 | 4.941 | 5.208 |
| γ₀₁ (Öğretmen deneyimi) | 0.121 | 0.015 | 8.311 | 96.85760 | 5.89e-13 | 0.092 | 0.150 |
| γ₀₂ (Sınıf dışadönüklük iklimi) | 0.803 | 0.140 | 5.751 | 96.66547 | 1.04e-07 | 0.526 | 1.080 |
Düzey-2 yordayıcıları eklendiğinde genel kesişim (γ₀₀ = 5.074) boş modeldeki değerle (5.078) neredeyse aynı kalmıştır; bu beklenen bir durumdur çünkü her iki yordayıcı da büyük ortalamaya göre merkezlenmiştir. Öğretmen deneyimi istatistiksel olarak anlamlı bir yordayıcıdır (γ₀₁ = 0.121, p < .001): öğretmen deneyimi genel ortalamadan 1 yıl fazla olan sınıflarda popülerlik ortalaması 0.12 puan daha yüksektir. Sınıf dışadönüklük iklimi ise daha güçlü bir etkiye sahiptir (γ₀₂ = 0.803, p < .001): sınıfın ortalama dışadönüklüğü genel ortalamadan 1 birim yüksek olduğunda sınıf popülerlik ortalaması yaklaşık 0.8 puan artmaktadır. Her iki katsayının güven aralıkları da sıfırı içermemekte olup etkilerin güvenilirliğini desteklemektedir.
vc_2 <- as.data.frame(VarCorr(model_2))
tau00_2 <- vc_2$vcov[vc_2$grp == "sinif"]
sigma2_2 <- vc_2$vcov[vc_2$grp == "Residual"]
icc_2 <- tau00_2 / (tau00_2 + sigma2_2)
varyans_2 <- data.frame(
Bilesen = c("τ₀₀ — Sınıflar arası artık kesişim varyansı",
"σ² — Sınıf içi artık varyans",
"Koşullu ICC"),
M1_Deger = c(round(tau00_1, 3), round(sigma2_1, 3), round(icc_1, 3)),
M2_Deger = c(round(tau00_2, 3), round(sigma2_2, 3), round(icc_2, 3))
)
gt(varyans_2) |>
tab_header(title = "Varyans Bileşenlerinin Model 1 ↔ Model 2 Değişimi") |>
cols_label(Bilesen = "Bileşen", M1_Deger = "Model 1", M2_Deger = "Model 2") |>
stil_gt()| Varyans Bileşenlerinin Model 1 ↔ Model 2 Değişimi | ||
| Bileşen | Model 1 | Model 2 |
|---|---|---|
| τ₀₀ — Sınıflar arası artık kesişim varyansı | 0.702 | 0.393 |
| σ² — Sınıf içi artık varyans | 1.222 | 1.222 |
| Koşullu ICC | 0.365 | 0.244 |
Sınıflar arası kesişim varyansı (τ₀₀) boş modeldeki 0.702’den 0.393’e düşmüştür — bu, öğretmen deneyimi ve sınıf dışadönüklük ikliminin sınıflar arası varyansın yaklaşık %44’ünü [(0.702 − 0.393) / 0.702] açıkladığı anlamına gelir. Sınıf içi varyans (σ² = 1.222) beklendiği gibi değişmemiştir çünkü bu modelde henüz Düzey-1 yordayıcısı eklenmemiştir. Koşullu ICC’nin 0.365’ten 0.244’e düşmesi, sınıf düzeyindeki yordayıcıların sınıflar arası farklılıkların önemli bir kısmını başarıyla açıkladığını göstermektedir; ancak hâlâ %24’lük açıklanmamış sınıf düzeyi varyansı kalmaktadır.
Raudenbush ve Bryk (2002) R²₂ formülü, L2 yordayıcılarının kesişim varyansında açıkladığı oranı verir: \[R^2_2 = \frac{\tau_{00}^{M1} - \tau_{00}^{M2}}{\tau_{00}^{M1}}\] Bu değer, sınıflar arası popülerlik farklılıklarının ne kadarının öğretmen deneyimi ve sınıf dışadönüklük iklimi ile açıklanabildiğini gösterir.
R2_L2 <- (tau00_1 - tau00_2) / tau00_1
r2_tbl <- data.frame(
Olcu = c("τ₀₀ (Model 1)",
"τ₀₀ (Model 2)",
"Azalma miktarı",
"R²₂ (Düzey-2 açıklanan varyans)"),
Deger = c(round(tau00_1, 3),
round(tau00_2, 3),
round(tau00_1 - tau00_2, 3),
paste0(round(R2_L2 * 100, 1), " %"))
)
gt(r2_tbl) |>
tab_header(title = "Düzey-2 Açıklanan Varyans Oranı (Raudenbush & Bryk, 2002)") |>
cols_label(Olcu = "Ölçü", Deger = "Değer") |>
stil_gt()| Düzey-2 Açıklanan Varyans Oranı (Raudenbush & Bryk, 2002) | |
| Ölçü | Değer |
|---|---|
| τ₀₀ (Model 1) | 0.702 |
| τ₀₀ (Model 2) | 0.393 |
| Azalma miktarı | 0.309 |
| R²₂ (Düzey-2 açıklanan varyans) | 44 % |
uyum_2 <- data.frame(
Olcu = c("Deviance (−2LL)", "AIC", "BIC", "logLik"),
Deger = c(round(-2 * as.numeric(logLik(model_2)), 2),
round(AIC(model_2), 2),
round(BIC(model_2), 2),
round(as.numeric(logLik(model_2)), 2))
)
gt(uyum_2) |>
tab_header(title = "Model 2 — Uyum İstatistikleri") |>
cols_label(Olcu = "Ölçü", Deger = "Değer") |>
stil_gt()| Model 2 — Uyum İstatistikleri | |
| Ölçü | Değer |
|---|---|
| Deviance (−2LL) | 6286.69 |
| AIC | 6296.69 |
| BIC | 6324.69 |
| logLik | -3143.34 |
Model 2’nin tüm uyum istatistikleri boş modele göre iyileşmiştir. Deviance 6330.51’den 6286.69’a düşmüştür (ΔDeviance = 43.82, Δdf = 2, p < .001); bu fark ki-kare testi ile değerlendirildiğinde iki Düzey-2 yordayıcısının modele anlamlı katkı sağladığını göstermektedir. AIC (6336.51 → 6296.69) ve BIC (6353.31 → 6324.69) değerlerindeki düşüş de model iyileşmesini desteklemekte olup, BIC gibi parametre sayısını daha ağır cezalandıran ölçütte bile iyileşmenin sürmesi, eklenen yordayıcıların gereksiz karmaşıklık yaratmadığını doğrulamaktadır.
Model 1 ↔︎ Model 2 Karşılaştırması
LRT (Likelihood Ratio Test), iç içe (nested) iki modelin deviance farkını karşılaştırır: \[\chi^2 = -2LL_{M1} - (-2LL_{M2})\] Deviance farkı, eklenen parametre sayısı kadar serbestlik derecesiyle χ² dağılımına uyar. Anlamlı bir fark, yeni modelin veriye önceki modelden anlamlı şekilde daha iyi uyduğunu gösterir. Not: Sabit etki farkı test ediliyorsa ML, yalnızca rastgele etki farkı test ediliyorsa REML kullanılır. Burada sabit etki farkı testi söz konusu olduğu için modelleri ML ile yeniden tahmin ediyoruz.
# Sabit etki farkı test edildiği için ML ile yeniden tahmin
model_1_ML <- update(model_1, REML = FALSE)
model_2_ML <- update(model_2, REML = FALSE)
anova_m1m2 <- anova(model_1_ML, model_2_ML)
kars_m1m2 <- data.frame(
Model = c("Model 1 (Boş)", "Model 2 (L2 yordayıcılı)"),
npar = anova_m1m2$npar,
AIC = round(anova_m1m2$AIC, 2),
BIC = round(anova_m1m2$BIC, 2),
logLik = round(anova_m1m2$logLik, 2),
Deviance = round(-2 * as.numeric(anova_m1m2$logLik), 2),
Chisq = c("—", round(anova_m1m2$Chisq[2], 3)),
Chi_df = c("—", anova_m1m2$Df[2]),
p = c("—", format.pval(anova_m1m2$`Pr(>Chisq)`[2], digits = 3))
)
gt(kars_m1m2) |>
tab_header(
title = "Model 1 vs Model 2 — Olabilirlik Oranı Testi (LRT)",
subtitle = "Tahmin yöntemi: ML (Sabit etki farkı testi için)"
) |>
cols_label(
npar = "npar", Deviance = "Deviance",
Chisq = "χ²", Chi_df = "Δdf", p = "p"
) |>
stil_gt()| Model 1 vs Model 2 — Olabilirlik Oranı Testi (LRT) | ||||||||
| Tahmin yöntemi: ML (Sabit etki farkı testi için) | ||||||||
| Model | npar | AIC | BIC | logLik | Deviance | χ² | Δdf | p |
|---|---|---|---|---|---|---|---|---|
| Model 1 (Boş) | 3 | 6333.47 | 6350.27 | -3163.73 | 6327.47 | — | — | — |
| Model 2 (L2 yordayıcılı) | 5 | 6283.67 | 6311.67 | -3136.83 | 6273.67 | 53.8 | 2 | 2.08e-12 |
Olabilirlik oranı testi (LRT), Model 2’nin Model 1’e göre istatistiksel olarak anlamlı biçimde daha iyi uyum sağladığını göstermektedir (χ² = 53.8, Δdf = 2, p < .001). Deviance 6327.47’den 6273.67’ye düşmüş, AIC ve BIC değerleri de paralel olarak azalmıştır. İki ek parametre (öğretmen deneyimi ve sınıf dışadönüklük iklimi) modele anlamlı katkı sağlamakta olup Model 2 tercih edilmelidir. Not: Buradaki deviance değerleri bireysel model tablolarından farklıdır çünkü LRT karşılaştırması ML tahmini ile yapılırken model tabloları REML tahminine dayanmaktadır; bu, iç içe modellerin sabit etkiler açısından karşılaştırılabilmesi için standart uygulamadır.
Bu modelde Düzey-1 yordayıcıları (disadonukluk_mrk ve
cinsiyet) eklenir. Ayrıca disadonukluk_mrk
için rastgele eğim belirlenerek, dışadönüklüğün popülerlik üzerindeki
etkisinin sınıftan sınıfa farklılaşıp farklılaşmadığı test edilir.
Düzey 1: \[populerlik_{ij} = \beta_{0j} + \beta_{1j} \cdot disadonukluk\_mrk_{ij} + \beta_{2j} \cdot cinsiyet_{ij} + r_{ij}\]
Düzey 2: \[\beta_{0j} = \gamma_{00} + u_{0j}\] \[\beta_{1j} = \gamma_{10} + u_{1j}\] \[\beta_{2j} = \gamma_{20}\]
sabit_3 <- broom.mixed::tidy(model_3, effects = "fixed", conf.int = TRUE) |>
mutate(
Terim = recode(term,
"(Intercept)" = "γ₀₀ (Kesişim)",
"disadonukluk_mrk" = "γ₁₀ (Dışadönüklük eğimi)",
"cinsiyet" = "γ₂₀ (Cinsiyet)"
),
across(c(estimate, std.error, statistic, conf.low, conf.high),
~round(.x, 3)),
p.value = ifelse(is.na(p.value), "—", format.pval(p.value, digits = 3))
) |>
select(Terim, estimate, std.error, statistic, df, p.value, conf.low, conf.high)
gt(sabit_3) |>
tab_header(title = "Model 3 — Sabit Etkiler") |>
cols_label(
estimate = "Kestirim", std.error = "SE", statistic = "t",
df = "df", p.value = "p",
conf.low = "95% Alt", conf.high = "95% Üst"
) |>
stil_gt()| Model 3 — Sabit Etkiler | |||||||
| Terim | Kestirim | SE | t | df | p | 95% Alt | 95% Üst |
|---|---|---|---|---|---|---|---|
| γ₀₀ (Kesişim) | 4.444 | 0.076 | 58.716 | 111.36789 | <2e-16 | 4.294 | 4.594 |
| γ₁₀ (Dışadönüklük eğimi) | 0.452 | 0.025 | 18.394 | 95.15161 | <2e-16 | 0.403 | 0.501 |
| γ₂₀ (Cinsiyet) | 1.252 | 0.037 | 34.236 | 1908.36206 | <2e-16 | 1.180 | 1.324 |
Düzey-1 yordayıcıları eklendiğinde genel kesişim γ₀₀ = 4.444’e düşmüştür; bu değer artık ortalama dışadönüklüğe sahip bir erkek öğrencinin beklenen popülerlik puanını ifade etmektedir (cinsiyet = 0 → erkek, dışadönüklük CWC ile merkezlenmiş → 0 = sınıf ortalaması). Dışadönüklük anlamlı bir yordayıcıdır (γ₁₀ = 0.452, p < .001): kendi sınıf ortalamasından 1 birim daha dışadönük olan öğrencilerin popülerliği 0.45 puan daha yüksektir. Cinsiyet ise en güçlü Düzey-1 etkisini göstermektedir (γ₂₀ = 1.252, p < .001): diğer değişkenler sabit tutulduğunda kız öğrenciler erkeklerden ortalama 1.25 puan daha popülerdir. Her iki katsayının güven aralıkları da oldukça dar olup kestirimlerin hassasiyetini desteklemektedir. Boş modeldeki genel kesişimle (5.078) karşılaştırıldığında düşüş, cinsiyet ve dışadönüklük kontrol edildikten sonra erkek referans grubunun ortalamasını yansıtmaktadır.
vc_3 <- as.data.frame(VarCorr(model_3))
# Rastgele etkiler: intercept varyansı, eğim varyansı, kovaryans
tau00_3 <- vc_3$vcov[vc_3$grp == "sinif" & vc_3$var1 == "(Intercept)" & is.na(vc_3$var2)]
tau11_3 <- vc_3$vcov[vc_3$grp == "sinif" & vc_3$var1 == "disadonukluk_mrk" & is.na(vc_3$var2)]
tau01_3 <- vc_3$vcov[vc_3$grp == "sinif" & !is.na(vc_3$var2)]
sigma2_3 <- vc_3$vcov[vc_3$grp == "Residual"]
# Korelasyon (standart sapmalar üzerinden)
kor_01_3 <- tau01_3 / (sqrt(tau00_3) * sqrt(tau11_3))
varyans_3 <- data.frame(
Bilesen = c("τ₀₀ — Kesişim varyansı (sınıflar arası)",
"τ₁₁ — Eğim varyansı (dışadönüklük eğiminin sınıflar arası farklılaşması)",
"τ₀₁ — Kesişim-eğim kovaryansı",
"r(τ₀₁) — Kesişim-eğim korelasyonu",
"σ² — Sınıf içi artık varyans"),
Deger = c(round(tau00_3, 3),
round(tau11_3, 4),
round(tau01_3, 4),
round(kor_01_3, 3),
round(sigma2_3, 3))
)
gt(varyans_3) |>
tab_header(title = "Model 3 — Varyans Bileşenleri") |>
cols_label(Bilesen = "Bileşen", Deger = "Değer") |>
stil_gt()| Model 3 — Varyans Bileşenleri | |
| Bileşen | Değer |
|---|---|
| τ₀₀ — Kesişim varyansı (sınıflar arası) | 0.5110 |
| τ₁₁ — Eğim varyansı (dışadönüklük eğiminin sınıflar arası farklılaşması) | 0.0341 |
| τ₀₁ — Kesişim-eğim kovaryansı | -0.0694 |
| r(τ₀₁) — Kesişim-eğim korelasyonu | -0.5260 |
| σ² — Sınıf içi artık varyans | 0.5520 |
Düzey-1 yordayıcıları (cinsiyet ve dışadönüklük) eklendikten sonra sınıf içi artık varyans (σ²) 1.222’den 0.552’ye düşmüştür; bu, öğrenci düzeyindeki varyansın yaklaşık %55’inin [(1.222 − 0.552) / 1.222] bu iki yordayıcıyla açıklandığını göstermektedir. Kesişim varyansının (τ₀₀ = 0.511) Model 2’ye göre (0.393) artmış görünmesi şaşırtıcı değildir; bu, Düzey-1 yordayıcılarının eklenmesiyle kesişimin anlamının değişmesinden kaynaklanır (artık “koşulsuz sınıf ortalaması” değil, “ortalama dışadönüklükteki erkek öğrencinin beklenen puanı”dır). Dışadönüklük eğiminin sınıflar arası varyansı (τ₁₁ = 0.034) küçük olmakla birlikte sıfırdan farklıdır; dışadönüklüğün popülerliğe etkisi sınıflar arasında bir miktar değişmektedir.
Raudenbush ve Bryk (2002) R²₁ formülü, L1 yordayıcılarının sınıf içi artık varyansta açıkladığı oranı verir: \[R^2_1 = \frac{\sigma^2_{M1} - \sigma^2_{M3}}{\sigma^2_{M1}}\] Boş modele referansla sınıf içi bireysel popülerlik farklılıklarının ne kadarının dışadönüklük ve cinsiyet ile açıklanabildiğini gösterir.
R2_L1 <- (sigma2_1 - sigma2_3) / sigma2_1
r2_L1_tbl <- data.frame(
Olcu = c("σ² (Model 1)",
"σ² (Model 3)",
"Azalma miktarı",
"R²₁ (Düzey-1 açıklanan varyans)"),
Deger = c(round(sigma2_1, 3),
round(sigma2_3, 3),
round(sigma2_1 - sigma2_3, 3),
paste0(round(R2_L1 * 100, 1), " %"))
)
gt(r2_L1_tbl) |>
tab_header(title = "Düzey-1 Açıklanan Varyans Oranı (Raudenbush & Bryk, 2002)") |>
cols_label(Olcu = "Ölçü", Deger = "Değer") |>
stil_gt()| Düzey-1 Açıklanan Varyans Oranı (Raudenbush & Bryk, 2002) | |
| Ölçü | Değer |
|---|---|
| σ² (Model 1) | 1.222 |
| σ² (Model 3) | 0.552 |
| Azalma miktarı | 0.67 |
| R²₁ (Düzey-1 açıklanan varyans) | 54.8 % |
Hesaplanan R²₁ = %54.8, cinsiyet ve dışadönüklüğün sınıf içi bireysel farklılıkların yarısından fazlasını açıkladığını göstermektedir. Bu oldukça yüksek bir orandır; özellikle cinsiyetin tek başına güçlü etkisi (γ₂₀ = 1.252) düşünüldüğünde bu sonuç beklenen bir bulgudur. Geriye kalan ~%45’lik açıklanmamış sınıf içi varyans, modele dahil edilmeyen diğer bireysel faktörlere atfedilebilir.
Rastgele eğim modelinin çıktısını görsel olarak kavramanın en iyi yolu, sınıfların BLUP (Best Linear Unbiased Predictors) kestirimlerini görmektir. Her sınıfın kendi içsel dışadönüklük eğimi ne kadar farklılaşıyor?
# Sınıflara özgü rastgele etki kestirimleri
blup_3 <- ranef(model_3)$sinif |>
tibble::rownames_to_column("sinif") |>
rename(u0 = `(Intercept)`, u1 = disadonukluk_mrk)
gamma10 <- fixef(model_3)["disadonukluk_mrk"]
blup_3$sinif_egim <- gamma10 + blup_3$u1
# Sınıflara özgü eğimlerin histogramı
ggplot(blup_3, aes(x = sinif_egim)) +
geom_histogram(fill = "#7eb8d4", color = "#1a1e2e", bins = 25) +
geom_vline(xintercept = gamma10, color = "#d4a560", linewidth = 1, linetype = "dashed") +
annotate("text", x = gamma10, y = Inf, vjust = 2,
label = paste0("Sabit eğim γ₁₀ = ", round(gamma10, 3)),
color = "#d4a560", size = 4.5, hjust = -0.1) +
labs(
title = "Sınıflara Özgü Dışadönüklük Eğimlerinin Dağılımı",
subtitle = "Her çubuk bir sınıfın BLUP-tabanlı eğim kestirimi (γ₁₀ + u₁ⱼ)",
x = "Dışadönüklük Eğimi",
y = "Sınıf Sayısı"
) +
tema_hlmHistogram, 100 sınıfın her birinin dışadönüklük eğimini (γ₁₀ + u₁ⱼ) göstermektedir. Tüm eğimler pozitiftir (yaklaşık 0.15 ile 0.85 arasında); yani dışadönüklük her sınıfta popülerliği artırmaktadır, ancak bu etkinin büyüklüğü sınıftan sınıfa önemli ölçüde değişmektedir. Sabit eğim (γ₁₀ = 0.452) etrafında dağılım yaklaşık simetrik görünmekle birlikte, bazı sınıflarda etki genel ortalamanın neredeyse yarısı kadarken bazılarında neredeyse iki katıdır. Bu görsel, τ₁₁ = 0.034 varyans değerini somutlaştırmakta ve çapraz düzey etkileşimlerle (Model 4) bu farklılığın sınıf düzeyindeki hangi özelliklerle ilişkili olduğunun araştırılmasını gerekçelendirmektedir.
uyum_3 <- data.frame(
Olcu = c("Deviance (−2LL)", "AIC", "BIC", "logLik"),
Deger = c(round(-2 * as.numeric(logLik(model_3)), 2),
round(AIC(model_3), 2),
round(BIC(model_3), 2),
round(as.numeric(logLik(model_3)), 2))
)
gt(uyum_3) |>
tab_header(title = "Model 3 — Uyum İstatistikleri") |>
cols_label(Olcu = "Ölçü", Deger = "Değer") |>
stil_gt()| Model 3 — Uyum İstatistikleri | |
| Ölçü | Değer |
|---|---|
| Deviance (−2LL) | 4864.50 |
| AIC | 4878.50 |
| BIC | 4917.71 |
| logLik | -2432.25 |
Model 3’ün tüm uyum ölçütleri önceki modellere göre çarpıcı biçimde iyileşmiştir. Deviance, Model 2’deki 6286.69’dan 4864.50’ye düşmüştür (ΔDeviance ≈ 1422); AIC (6296.69 → 4878.50) ve BIC (6324.69 → 4917.71) değerlerindeki büyük düşüş, Düzey-1 yordayıcılarının (cinsiyet ve dışadönüklük) modele çok güçlü katkı sağladığını göstermektedir.
Model 2 ↔︎ Model 3 Karşılaştırması (Yalnızca Bilgi Ölçütleri)
Neden LRT yapılmıyor? Model 2 yalnızca L2 yordayıcılarını, Model 3 ise yalnızca L1 yordayıcılarını + rastgele eğimi içerir. Birinin yordayıcı kümesi diğerinin alt kümesi değildir — bu nedenle modeller iç içe (nested) değildir ve olabilirlik oranı testi (LRT) geçersizdir. İç içe olmayan modeller yalnızca bilgi ölçütleri (AIC, BIC) aracılığıyla bilgilendirici biçimde karşılaştırılabilir; düşük AIC/BIC değeri olan model aynı veri üzerinde göreli olarak daha iyi uyum sağlar.
# LRT yapılamayacağı için yalnızca bilgi ölçütlerini karşılaştırıyoruz
# Tahmin yöntemi ML (karşılaştırılabilirlik için)
model_3_ML <- update(model_3, REML = FALSE)
kars_m2m3 <- data.frame(
Model = c("Model 2 (Yalnız L2)",
"Model 3 (Yalnız L1 + rastgele eğim)"),
npar = c(attr(logLik(model_2_ML), "df"),
attr(logLik(model_3_ML), "df")),
AIC = c(round(AIC(model_2_ML), 2),
round(AIC(model_3_ML), 2)),
BIC = c(round(BIC(model_2_ML), 2),
round(BIC(model_3_ML), 2)),
logLik = c(round(as.numeric(logLik(model_2_ML)), 2),
round(as.numeric(logLik(model_3_ML)), 2)),
Deviance = c(round(-2 * as.numeric(logLik(model_2_ML)), 2),
round(-2 * as.numeric(logLik(model_3_ML)), 2))
)
gt(kars_m2m3) |>
tab_header(
title = "Model 2 vs Model 3 — Bilgi Ölçütleri Karşılaştırması",
subtitle = "Modeller iç içe olmadığı için LRT yerine yalnızca AIC/BIC bilgi amaçlı sunulmuştur"
) |>
cols_label(
npar = "npar", Deviance = "Deviance"
) |>
stil_gt()| Model 2 vs Model 3 — Bilgi Ölçütleri Karşılaştırması | |||||
| Modeller iç içe olmadığı için LRT yerine yalnızca AIC/BIC bilgi amaçlı sunulmuştur | |||||
| Model | npar | AIC | BIC | logLik | Deviance |
|---|---|---|---|---|---|
| Model 2 (Yalnız L2) | 5 | 6283.67 | 6311.67 | -3136.83 | 6273.67 |
| Model 3 (Yalnız L1 + rastgele eğim) | 7 | 4864.59 | 4903.79 | -2425.29 | 4850.59 |
Model 3, AIC (4864.59 vs 6283.67) ve BIC (4903.79 vs 6311.67) açısından Model 2’den açık ara daha iyi uyum sağlamaktadır. Ancak bu iki model birbirinin alternatifi değil, tamamlayıcısıdır: Model 2 sınıflar arası farklılıkları (τ₀₀) Düzey-2 yordayıcılarıyla açıklarken, Model 3 sınıf içi farklılıkları (σ²) Düzey-1 yordayıcılarıyla açıklar ve eğim heterojenliğini ortaya koyar. Bu nedenle burada “hangisi daha iyi” sorusu yerine “her biri neyi açıklıyor” sorusu önemlidir.
# Aynı sabit etkilerle, rastgele eğim OLMAYAN alternatif model
model_3_sadece_kesisim <- lmer(
populerlik ~ 1 + disadonukluk_mrk + cinsiyet + (1 | sinif),
data = veri, REML = FALSE
)
anova_re <- anova(model_3_sadece_kesisim, model_3_ML)
kars_re <- data.frame(
Model = c("Yalnız rastgele kesişim", "Rastgele kesişim + eğim (Model 3)"),
npar = anova_re$npar,
AIC = round(anova_re$AIC, 2),
BIC = round(anova_re$BIC, 2),
logLik = round(anova_re$logLik, 2),
Deviance = round(-2 * as.numeric(anova_re$logLik), 2),
Chisq = c("—", round(anova_re$Chisq[2], 3)),
Chi_df = c("—", anova_re$Df[2]),
p = c("—", format.pval(anova_re$`Pr(>Chisq)`[2], digits = 3))
)
gt(kars_re) |>
tab_header(
title = "Rastgele Eğimin Anlamlılık Testi (LRT)",
subtitle = "Dışadönüklük eğiminin sınıflar arası farklılaşmasının istatistiksel anlamlılığı"
) |>
cols_label(
npar = "npar", Deviance = "Deviance",
Chisq = "χ²", Chi_df = "Δdf", p = "p"
) |>
stil_gt()| Rastgele Eğimin Anlamlılık Testi (LRT) | ||||||||
| Dışadönüklük eğiminin sınıflar arası farklılaşmasının istatistiksel anlamlılığı | ||||||||
| Model | npar | AIC | BIC | logLik | Deviance | χ² | Δdf | p |
|---|---|---|---|---|---|---|---|---|
| Yalnız rastgele kesişim | 5 | 4923.65 | 4951.65 | -2456.83 | 4913.65 | — | — | — |
| Rastgele kesişim + eğim (Model 3) | 7 | 4864.59 | 4903.79 | -2425.29 | 4850.59 | 63.062 | 2 | 2.02e-14 |
LRT sonucu, dışadönüklük eğiminin sınıflar arasında rastgele farklılaşmasının istatistiksel olarak anlamlı olduğunu göstermektedir (χ² = 63.062, Δdf = 2, p < .001). İki ek parametre (eğim varyansı τ₁₁ ve kesişim-eğim kovaryansı τ₀₁) modele anlamlı katkı sağlamaktadır. AIC (4923.65 → 4864.59) ve BIC (4951.65 → 4903.79) değerlerindeki düşüş de bunu desteklemektedir. Bu bulgu, dışadönüklüğün popülerliğe etkisinin tüm sınıflarda aynı olmadığını doğrulamakta ve Model 4’te bu farklılaşmayı sınıf düzeyindeki özelliklerle (öğretmen deneyimi, sınıf dışadönüklük iklimi) açıklamaya yönelik çapraz düzey etkileşimlerinin araştırılmasını meşrulaştırmaktadır.
Bu son modelde çapraz düzey etkileşim
(ogretmen_deneyimi_mrk × disadonukluk_mrk) eklenir. Amaç,
dışadönüklüğün popülerlik üzerindeki etkisinin öğretmen deneyimine bağlı
olarak nasıl değiştiğini test etmektir.
Çapraz düzey etkileşim HLM’nin gücünü en iyi gösteren özelliktir: “L1’deki bir ilişki (dışadönüklük → popülerlik) L2’deki bir değişken (öğretmen deneyimi) tarafından düzenleniyor mu?” sorusuna yanıt verir.
Düzey 1: \[populerlik_{ij} = \beta_{0j} + \beta_{1j} \cdot disadonukluk\_mrk_{ij} + \beta_{2j} \cdot cinsiyet_{ij} + r_{ij}\]
Düzey 2: \[\beta_{0j} = \gamma_{00} + \gamma_{01} \cdot ogretmen\_deneyimi\_mrk_j + \gamma_{02} \cdot sinif\_disadonukluk\_mrk_j + u_{0j}\] \[\beta_{1j} = \gamma_{10} + \gamma_{11} \cdot ogretmen\_deneyimi\_mrk_j + u_{1j}\] \[\beta_{2j} = \gamma_{20}\]
Burada \(\gamma_{11}\) çapraz düzey etkileşim katsayısıdır — öğretmen deneyimindeki bir birimlik artışın dışadönüklük eğimi üzerindeki etkisini verir.
sabit_4 <- broom.mixed::tidy(model_4, effects = "fixed", conf.int = TRUE) |>
mutate(
Terim = recode(term,
"(Intercept)" = "γ₀₀ (Kesişim)",
"ogretmen_deneyimi_mrk" = "γ₀₁ (Öğretmen deneyimi)",
"sinif_disadonukluk_mrk" = "γ₀₂ (Sınıf dışadönüklük iklimi)",
"disadonukluk_mrk" = "γ₁₀ (Dışadönüklük eğimi)",
"cinsiyet" = "γ₂₀ (Cinsiyet)",
"disadonukluk_mrk:ogretmen_deneyimi_mrk" = "γ₁₁ (Dışadönüklük × Öğretmen deneyimi)"
),
across(c(estimate, std.error, statistic, conf.low, conf.high),
~round(.x, 3)),
p.value = ifelse(is.na(p.value), "—", format.pval(p.value, digits = 3))
) |>
select(Terim, estimate, std.error, statistic, df, p.value, conf.low, conf.high)
gt(sabit_4) |>
tab_header(title = "Model 4 — Sabit Etkiler") |>
cols_label(
estimate = "Kestirim", std.error = "SE", statistic = "t",
df = "df", p.value = "p",
conf.low = "95% Alt", conf.high = "95% Üst"
) |>
stil_gt() |>
tab_style(
style = cell_fill(color = "#3a2d3d"),
locations = cells_body(rows = Terim == "γ₁₁ (Dışadönüklük × Öğretmen deneyimi)")
)| Model 4 — Sabit Etkiler | |||||||
| Terim | Kestirim | SE | t | df | p | 95% Alt | 95% Üst |
|---|---|---|---|---|---|---|---|
| γ₀₀ (Kesişim) | 4.446 | 0.060 | 74.564 | 117.56096 | < 2e-16 | 4.328 | 4.564 |
| γ₀₁ (Öğretmen deneyimi) | 0.101 | 0.012 | 8.260 | 97.33043 | 7.34e-13 | 0.077 | 0.126 |
| γ₀₂ (Sınıf dışadönüklük iklimi) | 0.629 | 0.117 | 5.360 | 96.96665 | 5.64e-07 | 0.396 | 0.862 |
| γ₁₀ (Dışadönüklük eğimi) | 0.452 | 0.018 | 25.574 | 83.29378 | < 2e-16 | 0.417 | 0.487 |
| γ₂₀ (Cinsiyet) | 1.242 | 0.036 | 34.262 | 1939.10432 | < 2e-16 | 1.171 | 1.313 |
| ogretmen_deneyimi_mrk:disadonukluk_mrk | -0.025 | 0.003 | -9.501 | 76.88996 | 1.32e-14 | -0.030 | -0.020 |
Yorum: Tam modelde tüm sabit etkiler istatistiksel olarak anlamlıdır (p < .001). Düzey-1 yordayıcılarının kestirimleri Model 3’e göre neredeyse sabit kalmıştır: dışadönüklük eğimi (γ₁₀ = 0.452) ve cinsiyet etkisi (γ₂₀ = 1.242) değişmemiştir — bu, L2 yordayıcılarının eklenmesinin L1 etkilerini bozmadığını gösterir. Düzey-2 yordayıcıları da Model 2’deki yönlerini korumuş ancak kestirimleri biraz değişmiştir: öğretmen deneyimi (γ₀₁ = 0.101) ve sınıf dışadönüklük iklimi (γ₀₂ = 0.629) hâlâ anlamlıdır; sınıf ikliminin etkisinin Model 2’deki 0.803’ten 0.629’a düşmesi, bu etkinin bir kısmının Düzey-1 dışadönüklük değişkeniyle paylaşıldığını göstermektedir.
En kritik bulgu çapraz düzey etkileşimidir: öğretmen deneyimi × dışadönüklük (γ = −0.025, p < .001) negatif ve anlamlıdır. Deneyimli öğretmenlerin sınıflarında dışadönüklüğün popülerliğe etkisi daha zayıftır; başka bir deyişle, deneyimli öğretmenler dışadönüklük avantajını “eşitleyici” bir rol oynayarak azaltmaktadır.
vc_4 <- as.data.frame(VarCorr(model_4))
tau00_4 <- vc_4$vcov[vc_4$grp == "sinif" & vc_4$var1 == "(Intercept)" & is.na(vc_4$var2)]
tau11_4 <- vc_4$vcov[vc_4$grp == "sinif" & vc_4$var1 == "disadonukluk_mrk" & is.na(vc_4$var2)]
tau01_4 <- vc_4$vcov[vc_4$grp == "sinif" & !is.na(vc_4$var2)]
sigma2_4 <- vc_4$vcov[vc_4$grp == "Residual"]
varyans_4 <- data.frame(
Bilesen = c("τ₀₀ — Kesişim varyansı",
"τ₁₁ — Eğim varyansı",
"τ₀₁ — Kesişim-eğim kovaryansı",
"σ² — Artık varyans"),
M3_Deger = c(round(tau00_3, 4), round(tau11_3, 4), round(tau01_3, 4), round(sigma2_3, 3)),
M4_Deger = c(round(tau00_4, 4), round(tau11_4, 4), round(tau01_4, 4), round(sigma2_4, 3))
)
gt(varyans_4) |>
tab_header(title = "Varyans Bileşenlerinin Model 3 ↔ Model 4 Değişimi") |>
cols_label(Bilesen = "Bileşen", M3_Deger = "Model 3", M4_Deger = "Model 4") |>
stil_gt()| Varyans Bileşenlerinin Model 3 ↔ Model 4 Değişimi | ||
| Bileşen | Model 3 | Model 4 |
|---|---|---|
| τ₀₀ — Kesişim varyansı | 0.5107 | 0.2941 |
| τ₁₁ — Eğim varyansı | 0.0341 | 0.0059 |
| τ₀₁ — Kesişim-eğim kovaryansı | -0.0694 | -0.0057 |
| σ² — Artık varyans | 0.5520 | 0.5520 |
Düzey-2 yordayıcıları ve çapraz düzey etkileşim eklendikten sonra her iki sınıf düzeyi varyans bileşeni önemli ölçüde azalmıştır. Kesişim varyansı (τ₀₀) 0.511’den 0.294’e düşmüştür — Düzey-2 yordayıcıları, sınıflar arası kesişim varyansının yaklaşık %42’sini [(0.511 − 0.294) / 0.511] açıklamıştır. Daha çarpıcı olan eğim varyansındaki düşüştür: τ₁₁ 0.034’ten 0.006’ya gerilemiştir — öğretmen deneyimi ile dışadönüklük arasındaki çapraz düzey etkileşim, eğim varyansının yaklaşık %83’ünü [(0.034 − 0.006) / 0.034] açıklamıştır. Yani sınıflar arasındaki dışadönüklük eğimi farklılığının büyük bölümü öğretmen deneyimindeki farklardan kaynaklanmaktadır. Sınıf içi artık varyans (σ² = 0.552) beklendiği gibi değişmemiştir çünkü yeni Düzey-1 yordayıcısı eklenmemiştir.
Çapraz düzey etkileşimin varlığı, dışadönüklük eğiminin sınıftan sınıfa farklılaşmasının (τ₁₁) öğretmen deneyimi tarafından ne kadar açıklandığını gösterir: \[R^2_{slope} = \frac{\tau_{11}^{M3} - \tau_{11}^{M4}}{\tau_{11}^{M3}}\]
R2_slope <- (tau11_3 - tau11_4) / tau11_3
r2_slope_tbl <- data.frame(
Olcu = c("τ₁₁ (Model 3)",
"τ₁₁ (Model 4)",
"Azalma miktarı",
"R²_slope (Eğim varyansında açıklanan)"),
Deger = c(round(tau11_3, 4),
round(tau11_4, 4),
round(tau11_3 - tau11_4, 4),
paste0(round(R2_slope * 100, 1), " %"))
)
gt(r2_slope_tbl) |>
tab_header(title = "Eğim Varyansında Açıklanan Oran") |>
cols_label(Olcu = "Ölçü", Deger = "Değer") |>
stil_gt()| Eğim Varyansında Açıklanan Oran | |
| Ölçü | Değer |
|---|---|
| τ₁₁ (Model 3) | 0.0341 |
| τ₁₁ (Model 4) | 0.0059 |
| Azalma miktarı | 0.0282 |
| R²_slope (Eğim varyansında açıklanan) | 82.8 % |
Öğretmen deneyimi × dışadönüklük çapraz düzey etkileşimi, dışadönüklük eğiminin sınıflar arası varyansının %82.8’ini açıklamıştır. Bu son derece yüksek bir orandır ve şunu göstermektedir: sınıflar arasında dışadönüklüğün popülerliğe etkisinin neden farklılaştığı sorusunun cevabı büyük ölçüde öğretmen deneyimidir. Geriye kalan ~%17’lik açıklanmamış eğim varyansı (τ₁₁ = 0.006) artık oldukça küçüktür ve pratikte ihmal edilebilir düzeye yaklaşmıştır.
Çapraz düzey etkileşimi grafikle göstermek yorumu somutlaştırır. Farklı öğretmen deneyimi düzeylerinde (örn. düşük/orta/yüksek) dışadönüklük eğiminin nasıl değiştiğini görmek, γ₁₁ katsayısının pratik anlamını netleştirir.
# Etkileşim teriminin adını otomatik bul (sıralama fark etmez)
fe <- fixef(model_4)
etkilesim_adi <- grep("disadonukluk_mrk.*ogretmen|ogretmen.*disadonukluk_mrk",
names(fe), value = TRUE)
# Üç temsili öğretmen deneyimi değeri: düşük (-1SD), orta (0), yüksek (+1SD)
sd_texp <- sd(veri$ogretmen_deneyimi_mrk)
deneyim_duzey <- c(-sd_texp, 0, sd_texp)
etiket_duzey <- c("Düşük deneyim (−1SD)", "Orta deneyim (ortalama)", "Yüksek deneyim (+1SD)")
# Dışadönüklük aralığı
disadonukluk_grid <- seq(min(veri$disadonukluk_mrk), max(veri$disadonukluk_mrk), length.out = 100)
# Tahmin veri çerçevesi
tahmin_df <- expand.grid(
disadonukluk_mrk = disadonukluk_grid,
deneyim = deneyim_duzey
) |>
mutate(
etiket = factor(deneyim,
levels = deneyim_duzey,
labels = etiket_duzey),
populerlik_tahmin = fe["(Intercept)"] +
fe["ogretmen_deneyimi_mrk"] * deneyim +
fe["disadonukluk_mrk"] * disadonukluk_mrk +
fe[etkilesim_adi] * disadonukluk_mrk * deneyim
)
# Grafik
ggplot(tahmin_df, aes(x = disadonukluk_mrk, y = populerlik_tahmin, color = etiket)) +
geom_line(linewidth = 1.2) +
scale_color_manual(values = c("#c06060", "#d4a560", "#8ed47e")) +
labs(
title = "Çapraz Düzey Etkileşim: Dışadönüklük × Öğretmen Deneyimi",
subtitle = "Deneyimli öğretmenlerin sınıflarında dışadönüklük eğimi farklılaşır",
x = "Dışadönüklük (CWC)",
y = "Popülerlik (tahmin)",
color = NULL
) +
tema_hlm +
theme(legend.position = "bottom")Grafik, çapraz düzey etkileşimini görsel olarak doğrulamaktadır. Üç çizginin eğimleri farklıdır: düşük deneyimli öğretmenlerin sınıflarında (kırmızı) dışadönüklük eğimi en dik, yüksek deneyimli öğretmenlerin sınıflarında (yeşil) ise en yatıktır. Deneyimli öğretmenler dışadönüklüğün popülerlik üzerindeki etkisini “yumuşatmakta” — yani içedönük öğrencilerin de popülerlik kazanabildiği bir sınıf ortamı yaratmaktadır.
uyum_4 <- data.frame(
Olcu = c("Deviance (−2LL)", "AIC", "BIC", "logLik"),
Deger = c(round(-2 * as.numeric(logLik(model_4)), 2),
round(AIC(model_4), 2),
round(BIC(model_4), 2),
round(as.numeric(logLik(model_4)), 2))
)
gt(uyum_4) |>
tab_header(title = "Model 4 — Uyum İstatistikleri") |>
cols_label(Olcu = "Ölçü", Deger = "Değer") |>
stil_gt()| Model 4 — Uyum İstatistikleri | |
| Ölçü | Değer |
|---|---|
| Deviance (−2LL) | 4783.69 |
| AIC | 4803.69 |
| BIC | 4859.70 |
| logLik | -2391.85 |
Model 3 ↔︎ Model 4 Karşılaştırması
model_4_ML <- update(model_4, REML = FALSE)
anova_m3m4 <- anova(model_3_ML, model_4_ML)
kars_m3m4 <- data.frame(
Model = c("Model 3 (Rastgele eğim)",
"Model 4 (Çapraz düzey etkileşim)"),
npar = anova_m3m4$npar,
AIC = round(anova_m3m4$AIC, 2),
BIC = round(anova_m3m4$BIC, 2),
logLik = round(anova_m3m4$logLik, 2),
Deviance = round(-2 * as.numeric(anova_m3m4$logLik), 2),
Chisq = c("—", round(anova_m3m4$Chisq[2], 3)),
Chi_df = c("—", anova_m3m4$Df[2]),
p = c("—", format.pval(anova_m3m4$`Pr(>Chisq)`[2], digits = 3))
)
gt(kars_m3m4) |>
tab_header(
title = "Model 3 vs Model 4 — Olabilirlik Oranı Testi (LRT)",
subtitle = "Tahmin yöntemi: ML"
) |>
cols_label(
npar = "npar", Deviance = "Deviance",
Chisq = "χ²", Chi_df = "Δdf", p = "p"
) |>
stil_gt()| Model 3 vs Model 4 — Olabilirlik Oranı Testi (LRT) | ||||||||
| Tahmin yöntemi: ML | ||||||||
| Model | npar | AIC | BIC | logLik | Deviance | χ² | Δdf | p |
|---|---|---|---|---|---|---|---|---|
| Model 3 (Rastgele eğim) | 7 | 4864.59 | 4903.79 | -2425.29 | 4850.59 | — | — | — |
| Model 4 (Çapraz düzey etkileşim) | 10 | 4768.52 | 4824.53 | -2374.26 | 4748.52 | 102.065 | 3 | <2e-16 |
LRT, Model 4’ün Model 3’e göre istatistiksel olarak anlamlı biçimde daha iyi uyum sağladığını göstermektedir (χ² = 102.065, Δdf = 3, p < .001). Üç ek parametre — iki Düzey-2 yordayıcı (öğretmen deneyimi, sınıf dışadönüklük iklimi) ve bir çapraz düzey etkileşim (öğretmen deneyimi × dışadönüklük) — modele anlamlı katkı sağlamıştır. AIC (4864.59 → 4768.52) ve BIC (4903.79 → 4824.53) değerlerindeki düşüş de bu iyileşmeyi desteklemektedir. Bu bulgu, varyans bileşenlerindeki değişimlerle de tutarlıdır: çapraz düzey etkileşimi tek başına eğim varyansının %83’ünü açıklamıştı. Parsimoni açısından da Model 4 haklı çıkmaktadır; 3 ek parametre karşılığında deviance’ta 102 puanlık düşüş, parametre başına çok yüksek bir kazanımdır.
HLM’nin temel varsayımları iki grupta toplanır: (1) Hata terimlerine yönelik varsayımlar — L1 kalıntılarının normalliği, bağımsızlığı, sabit varyansı; L2 rastgele etkilerinin çok değişkenli normalliği; düzeyler arası hata bağımsızlığı. (2) Yapısal varsayımlar — yordayıcı-hata bağımsızlığı, doğrusallık, çoklu bağlantı olmaması. Yapısal ihlaller katsayıları yanlı hale getirirken, hata varsayımı ihlalleri standart hataları bozar — her iki durum da yorumların güvenilirliğini farklı biçimde etkiler.
# L1 kalıntıları
L1_kalinti <- residuals(model_4)
L1_tahmin <- fitted(model_4)
kalinti_df <- data.frame(
kalinti = L1_kalinti,
tahmin = L1_tahmin
)
# Q-Q plot
g_qq <- ggplot(kalinti_df, aes(sample = kalinti)) +
stat_qq(color = "#7eb8d4", alpha = 0.4, size = 1.3) +
stat_qq_line(color = "#d4a560", linewidth = 0.8) +
labs(
title = "Düzey-1 Kalıntıları Q-Q Grafiği",
subtitle = "Normallik varsayımı — doğruya yakın olmalı",
x = "Teorik Niceliklar",
y = "Örnek Niceliklar"
) +
tema_hlm
# Kalıntı vs tahmin
g_rt <- ggplot(kalinti_df, aes(x = tahmin, y = kalinti)) +
geom_point(color = "#7eb8d4", alpha = 0.35, size = 1.3) +
geom_hline(yintercept = 0, color = "#d4a560", linetype = "dashed") +
geom_smooth(method = "loess", se = FALSE, color = "#8ed47e", linewidth = 0.8) +
labs(
title = "Kalıntılar vs Tahmin Değerleri",
subtitle = "Homoskedastisite — yayılım sabit olmalı, örüntü göstermemeli",
x = "Tahmin",
y = "Kalıntı"
) +
tema_hlm
g_qq + g_rt# L2 rastgele etkileri (BLUPs)
ranef_4 <- ranef(model_4)$sinif |>
tibble::rownames_to_column("sinif")
# u₀ (kesişim sapması) Q-Q
g_u0 <- ggplot(ranef_4, aes(sample = `(Intercept)`)) +
stat_qq(color = "#7eb8d4", size = 1.7) +
stat_qq_line(color = "#d4a560", linewidth = 0.8) +
labs(
title = "u₀ — Rastgele Kesişim Q-Q",
subtitle = "L2 çok değişkenli normallik (kesişim boyutu)",
x = "Teorik", y = "Örnek"
) +
tema_hlm
# u₁ (eğim sapması) Q-Q
g_u1 <- ggplot(ranef_4, aes(sample = disadonukluk_mrk)) +
stat_qq(color = "#8ed47e", size = 1.7) +
stat_qq_line(color = "#d4a560", linewidth = 0.8) +
labs(
title = "u₁ — Rastgele Eğim Q-Q",
subtitle = "L2 çok değişkenli normallik (eğim boyutu)",
x = "Teorik", y = "Örnek"
) +
tema_hlm
g_u0 + g_u1# Karma modellerde VIF — performance paketi ile
vif_sonuc <- performance::check_collinearity(model_4)
vif_df <- as.data.frame(vif_sonuc) |>
mutate(
VIF = round(VIF, 3),
SE_Factor = round(SE_factor, 3),
Yorum = case_when(
VIF < 5 ~ "✓ Sorun yok",
VIF < 10 ~ "⚠ Dikkat",
TRUE ~ "✗ Ciddi çoklu bağlantı"
)
) |>
select(Term, VIF, SE_Factor, Yorum)
gt(vif_df) |>
tab_header(
title = "Çoklu Bağlantı Kontrolü (VIF)",
subtitle = "VIF < 5 ideal; 5-10 arası dikkat; > 10 ciddi sorun"
) |>
cols_label(Term = "Terim") |>
stil_gt()| Çoklu Bağlantı Kontrolü (VIF) | |||
| VIF < 5 ideal; 5-10 arası dikkat; > 10 ciddi sorun | |||
| Terim | VIF | SE_Factor | Yorum |
|---|---|---|---|
| ogretmen_deneyimi_mrk | 2.032 | 1.425 | ✓ Sorun yok |
| sinif_disadonukluk_mrk | 2.028 | 1.424 | ✓ Sorun yok |
| disadonukluk_mrk | 1.006 | 1.003 | ✓ Sorun yok |
| cinsiyet | 1.009 | 1.004 | ✓ Sorun yok |
| ogretmen_deneyimi_mrk:disadonukluk_mrk | 1.004 | 1.002 | ✓ Sorun yok |
# Cook's distance — sınıf düzeyinde influential grupları tespit
library(influence.ME)
# Hesaplama uzun sürebilir, sınıf düzeyinde yapıyoruz
infl <- influence(model_4, group = "sinif")
cook_d <- cooks.distance(infl)
# influence.ME versiyonuna göre cook_d bazen 1-sütunlu matris, bazen adsız vektör döner.
# Güvenli biçimde sınıf isimlerini çıkaralım:
cook_vec <- as.numeric(cook_d)
sinif_isim <- if (is.matrix(cook_d) && !is.null(rownames(cook_d))) {
rownames(cook_d)
} else if (!is.null(names(cook_d))) {
names(cook_d)
} else {
# Son çare: influence objesindeki grup sırasını kullan
rownames(infl$alt.fixed)
}
# Yine de isimler boşsa sıralı numara
if (length(sinif_isim) != length(cook_vec)) {
sinif_isim <- as.character(seq_along(cook_vec))
}
cook_df <- data.frame(
sinif = sinif_isim,
cook = cook_vec
) |>
arrange(desc(cook)) |>
mutate(index = row_number())
# Cutoff: 4/n
cutoff <- 4 / length(unique(veri$sinif))
ggplot(cook_df, aes(x = index, y = cook)) +
geom_segment(aes(xend = index, y = 0, yend = cook), color = "#7eb8d4", alpha = 0.7) +
geom_point(color = "#7eb8d4", size = 1.5) +
geom_hline(yintercept = cutoff, color = "#c06060", linetype = "dashed") +
annotate("text", x = max(cook_df$index) * 0.7, y = cutoff * 1.3,
label = paste0("Eşik: 4/n = ", round(cutoff, 3)),
color = "#c06060", size = 4) +
labs(
title = "Sınıf Düzeyi Cook's Distance Değerleri",
subtitle = "Eşiği aşan sınıflar model kestirimlerini orantısız etkileyebilir",
x = "Sınıf (sıralı)",
y = "Cook's D"
) +
tema_hlm# Shapiro-Wilk testleri
sw_L1 <- shapiro.test(sample(L1_kalinti, min(5000, length(L1_kalinti))))
sw_u0 <- shapiro.test(ranef_4$`(Intercept)`)
sw_u1 <- shapiro.test(ranef_4$disadonukluk_mrk)
varsayim_tbl <- data.frame(
Varsayim = c(
"L1 kalıntılarının normalliği (Shapiro-Wilk)",
"L2 u₀ (kesişim) normalliği",
"L2 u₁ (eğim) normalliği",
"Çoklu bağlantı (maksimum VIF)",
"Etkili gözlem sayısı (Cook > 4/n)"
),
Deger = c(
paste0("W = ", round(sw_L1$statistic, 3), ", p = ", format.pval(sw_L1$p.value, digits = 3)),
paste0("W = ", round(sw_u0$statistic, 3), ", p = ", format.pval(sw_u0$p.value, digits = 3)),
paste0("W = ", round(sw_u1$statistic, 3), ", p = ", format.pval(sw_u1$p.value, digits = 3)),
round(max(vif_df$VIF), 3),
sum(cook_df$cook > cutoff)
)
)
gt(varsayim_tbl) |>
tab_header(title = "Varsayım Kontrollerinin Özeti") |>
cols_label(Varsayim = "Varsayım", Deger = "Sonuç") |>
stil_gt()| Varsayım Kontrollerinin Özeti | |
| Varsayım | Sonuç |
|---|---|
| L1 kalıntılarının normalliği (Shapiro-Wilk) | W = 0.999, p = 0.479 |
| L2 u₀ (kesişim) normalliği | W = 0.988, p = 0.473 |
| L2 u₁ (eğim) normalliği | W = 0.995, p = 0.96 |
| Çoklu bağlantı (maksimum VIF) | 2.032 |
| Etkili gözlem sayısı (Cook > 4/n) | 4 |
Tüm varsayım kontrolleri olumlu sonuç vermiştir. Düzey-1 kalıntıları (W = 0.999, p = .479), Düzey-2 kesişim rastgele etkileri (W = 0.988, p = .473) ve eğim rastgele etkileri (W = 0.995, p = .96) normal dağılım varsayımını karşılamaktadır — üç testte de sıfır hipotezi reddedilememiştir. Çoklu bağlantı sorunu yoktur; maksimum VIF = 2.032 olup genel kabul görmüş 5 (ya da katı eşik olan 10) değerinin oldukça altındadır. Cook uzaklığına göre yalnızca 4 etkili gözlem tespit edilmiştir (4/n eşiği); 2.000 öğrencilik örneklemde bu sayı ihmal edilebilir düzeydedir ve sonuçları bozma riski taşımamaktadır. Genel olarak Model 4’ün varsayım ihlallerinden bağımsız, güvenilir kestirimler ürettiği söylenebilir.
# Nakagawa-Schielzeth marjinal ve koşullu R²
r2_m1 <- performance::r2(model_1)
r2_m2 <- performance::r2(model_2)
r2_m3 <- performance::r2(model_3)
r2_m4 <- performance::r2(model_4)
r2_tablo <- data.frame(
Model = c("Model 1 (Boş)", "Model 2 (Yalnız L2)", "Model 3 (Yalnız L1)", "Model 4 (Tam)"),
Marjinal_R2 = c(
ifelse(is.null(r2_m1$R2_marginal), "—", round(as.numeric(r2_m1$R2_marginal), 3)),
round(as.numeric(r2_m2$R2_marginal), 3),
round(as.numeric(r2_m3$R2_marginal), 3),
round(as.numeric(r2_m4$R2_marginal), 3)
),
Kosullu_R2 = c(
round(as.numeric(r2_m1$R2_conditional), 3),
round(as.numeric(r2_m2$R2_conditional), 3),
round(as.numeric(r2_m3$R2_conditional), 3),
round(as.numeric(r2_m4$R2_conditional), 3)
)
)
gt(r2_tablo) |>
tab_header(
title = "Nakagawa-Schielzeth R² Değerleri",
subtitle = "Marjinal = yalnızca sabit etkiler ; Koşullu = sabit + rastgele etkiler"
) |>
cols_label(
Marjinal_R2 = "Marjinal R²",
Kosullu_R2 = "Koşullu R²"
) |>
stil_gt()| Nakagawa-Schielzeth R² Değerleri | ||
| Marjinal = yalnızca sabit etkiler ; Koşullu = sabit + rastgele etkiler | ||
| Model | Marjinal R² | Koşullu R² |
|---|---|---|
| Model 1 (Boş) | 0.000 | 0.365 |
| Model 2 (Yalnız L2) | 0.162 | 0.366 |
| Model 3 (Yalnız L1) | 0.378 | 0.688 |
| Model 4 (Tam) | 0.540 | 0.702 |
Nakagawa-Schielzeth R² değerleri modellerin açıklama gücündeki kademeli artışı özetlemektedir. Marjinal R² (yalnızca sabit etkiler) Model 1’de sıfırdan (yordayıcı yok) Model 4’te 0.540’a ulaşmıştır; yani sabit etkiler tek başına toplam varyansın %54’ünü açıklamaktadır. Koşullu R² (sabit + rastgele etkiler) ise 0.365’ten 0.702’ye yükselmiştir; modelin bütünü toplam varyansın %70’ini açıklamaktadır.
Model 2’de marjinal R² 0.162’ye çıkarken koşullu R² (0.366) boş modelle neredeyse aynı kalmıştır — bu, L2 yordayıcılarının sınıflar arası varyansı açıkladığını ancak toplam açıklanan varyansa rastgele etkiler hesaba katıldığında fazla bir şey eklemediğini gösterir. Asıl sıçrama Model 3’te gerçekleşmiştir (koşullu R² = 0.688): Düzey-1 yordayıcıları hem marjinal hem koşullu açıklama gücünü büyük ölçüde artırmıştır. Model 4’te marjinal ve koşullu R² arasındaki fark (0.702 − 0.540 = 0.162) kalan açıklanmamış sınıf düzeyi varyansına karşılık gelmektedir.
Bu günlüğü yayınlamadan önce RPubs’ta ilk hazırladığım günlüğü inceledim. Belki yapay zeka kullandığım için sizin beklediğiniz ölçüde ilerleme gösteremediğimi düşünüyorsunuz. Ancak o günlük ile bu günlük, kendime o gün sorduğum sorular ile bu gün sorduğum sorular, istatistiğe o gün ki bakış açımla bu gün ki bakış açım arasında uçurum var. Ve bu ilerleme sizin desteğinizle mümkün oldu. Siz çok iyi bir akademisyen ve öğretmensiniz. Kattıklarınız için çok teşekkür ederim.
HLM’nin tarihçesini okurken başka pek çok ileri analiz tekniğinin tarihçesinde olduğu gibi “Teknik çok önceden biliniyordu. Ancak bilgisayarların gelişmesiyle birlikte daha hızlı ve kolay hesaplama olanağı doğduğu için çok yaygın bir şekilde kullanılmaya başlandı.” anlamına gelcek ifadelerle karşılaştım. Ben şu an da öyle bir dönemden geçtiğimiz kanaatindeyim. Google gibi büyük şirketlerin algoritmlarla bizim nereye gideceğimizi ve ne satın alacağımız çoğu zaman doğru bir şekilde tahmin ettiği artık günlük sohbetlerimizin bir parçası. Yapay zeka ve güçlü bilgisayarların bireylerin kullanımına sunulmasıyla birlikte bizlerde bu analizleri veya bunlara yakın analizleri yapabileceğiz. Belki 20 yıl sonra istatistik kitaplarında 2020’li yılların ortalarında yapay zekanın güçlü bir şekilde kullanılmaya başlamasıyla birlikte X analizi yaygın bir şekilde kullanılmaya başlandı tarzı ifadeler olacak. Bu anlamda bize sağladığınız “Karar Ağaçları ve Yapay Sinir Ağları” konulu etkinlik çok ufuk açıcı oldu. Orada öğrendiğim bazı kavramlar için yaptığım araştırmalar rastgele orman ile madde yanlılığı tespiti, gradient boosting ile öğrenci başarı tahmini gibi makine öğrenmesi uygulamalarının yanı sıra gizil uzay madde tepki modellemesi (LSIRM), topolojik veri analizi (TDA) ve ağ psikometrisi gibi tekniklerin son zamanlarda psikometride kullanıldığını ve bunları kullanmanın benim için de mümkün olabileceğini gösterdi.
Bu haftaki konumuza gelince YL tezim de hata yaptığımı düşünmüş olsam da hata yapmadığımı görmüş oldum, sadece veri hipotezimi desteklemedi. Çünkü bende aslında HLM ile ortaya konmaya çalışılan “etki her yerde aynı mı?” temel sorusuna cevap aramıştım. Şimdi öğrendim ki HLM yapmanın aslında temel mantığı bu. Bu uygulamada kullandığım veri setinde de -muhtemelen bu soruya cevabı net bir şekilde göstermek için kurgulanmış bir veri veya gerçek böyle- öğretmen deneyiminin, dışadönüklüğün popülerlik üzerindeki etkisini azalttığını net bir şekilde gördüm. Eğitim verilerinde bu tür etkileşimlerin çok fazla olduğunu ve çok fazla araştırma yapılabileceğini -tabi doğru veriyi toplama meselesi en büyük enegel- düşünüyorum.
Tezimi yaparken boş modelden sonra düzey1 değişken eklemiş daha sonra düzey2 değişkenlerle model kurmuştum. Ancak sizin derste takip ettiğiniz sıralmanın -boş modelden sonra düzey2 değişkneleri ile model kurulması- mantıksal açıdan daha doğru olduğunu gördüm. Ben tezi yazarken bu kısımda Sedat hocanın kitabını takip etmiştim am şimdi baktığım da Hox, sizin sıralamanız ile ilerlemiş. ICC ’yi sadece gruplar arası farklılığın varlığı ve HLM ’ye gerek var mı yok mu sorusun cevap için kullandığımızı düşünüyordum. Oysa yaptığımz eklemelerle daha sonraki adımlar için hesapladığımız koşullu ICC değeri eklediğim yordayıcıların işe yaraıp yarmadığını da gösteriyormuş.
Bu konu ile ilgili ilk fırsatta öğrenmek istediğim iki husus:
1.Çok düzeyli yol analizi
2.PV’lerin R ile uygulamasının nasıl olacağı.
Enders, C. K., & Tofighi, D. (2007). Centering predictor variables in cross-sectional multilevel models: A new look at an old issue. Psychological Methods, 12(2), 121–138.
Finch, W. H., & Bolin, J. E. (2017). Multilevel modeling using Mplus. CRC Press.
Finch, W. H., Bolin, J. E., & Kelley, K. (2024). Multilevel modeling using R (3rd ed.). CRC Press.
Heck, R. H., Thomas, S. L., & Tabata, L. N. (2014). Multilevel and longitudinal modeling with IBM SPSS (2nd ed.). Routledge.
Hox, J. J., Moerbeek, M., & van de Schoot, R. (2018). Multilevel analysis: Techniques and applications (3rd ed.). Routledge.
Huang, F. L. (2022). Practical multilevel modeling using R. SAGE Publications.
Nakagawa, S., & Schielzeth, H. (2013). A general and simple method for obtaining R² from generalized linear mixed-effects models. Methods in Ecology and Evolution, 4(2), 133–142.
Raudenbush, S. W., & Bryk, A. S. (2002). Hierarchical linear models: Applications and data analysis methods (2nd ed.). Sage Publications.