Regresyon Discontinuity Tasarımları (RD)

İnsanların birbirlerine uyguladığı keyfi kural ve kanunlar bizim deney yapmamıza olanak sağlıyor.

RD (regresyon discontinuity) tasarımı, bu kurallardan faydalanan bir yöntemdir. Fuzzy ve sharp olmak üzere iki farklı şekli vardır. Sharp tasarımı, gözlemlediğimiz bir olayda kuralların tedavi ve kontrol gruplarını kesin olarak belirlemek üzerine kuruludur. Fuzzy tasarım ise bu grupları ayırabilmek için araç değişkenler gibi bir yapıya ihtiyaç duyar.

6.1.1 üç ayrı grafikten oluşuyor. Doğrusal, doğrusal olmayan, süreksiz olmakla karıştırılan doğrusal olmayan RD tasarımları. İlk olarak bu üç tasarım için veri oluşturuyoruz.

Her biri veri için 100 gözlem belirleyelim

n=100

Rasgele x verisi oluşturulalım

set.seed(1149)
x <- runif(n)

Rasgele veri oluşturduktan sonra bu verilerin ilk altı satrını görmek adına head() fonksiyonu, kullanalım

head(x)
## [1] 0.901608043 0.508481772 0.003583934 0.644593220 0.051421000 0.273405757

Koşullara göre 3 tane y oluşturun. Eşik değeri 0.5 olarak belirlenmiştir.

y_dogrusal <- x + (x > 0.5) * 0.25 + rnorm(n, mean = 0, sd = 0.1)
y_dogrusal_olmayan <- 0.5 * sin(6 * (x - 0.5)) + 0.5 + (x > 0.5) * 0.25 + rnorm(n, mean = 0, sd = 0.1)
y_hatalı <- 1 / (1 + exp(-25 * (x - 0.5))) + rnorm(n, mean = 0, sd = 0.1)

x ve y değişkenlerini doğrusal bir grafik çizmek için bir data frame içinde birleştirirsek

df <- data.frame(x = x, y_dogrusal = y_dogrusal)

Bu dataframe’i eşik değerine göre ikiye bölelim

df_alt <- df[df$x < 0.5, ]
df_ust <- df[df$x > 0.5, ]

1.grafik, doğrusal sharp tasarım

paketi yükledikten sonra çalıştırmak için aşağıdaki işlemi uygulayabiliriz.

library(plotrix)
A <- plot(df_alt$x, df_alt$y_dogrusal, xlim = c(0, 1), ylim = c(0, 2), pch = 16, cex = 0.5, col = "black", main = "A. Doğrusal E[Y|X]", xlab = "x", ylab = "Y")
points(df_ust$x, df_ust$y_dogrusal, pch = 16, cex = 0.5, col = "black")
lm_alt <- lm(y_dogrusal ~ x, data = df_alt)
lm_ust <- lm(y_dogrusal ~ x, data = df_ust)
ablineclip(lm_alt, x1 = 0,x2 = .5, col = "black", lwd = 2)
ablineclip(lm_ust, x1 = .5,x2 = 1, col = "black", lwd = 2)
abline(v = 0.5, lty = 2)

  1. Grafik için doğrusal olmayan tasarım.
df_dogrusal_olmayan <- data.frame(x = x, y_dogrusal_olmayan = y_dogrusal_olmayan)

Dogrusal olmayan veri setini ikiye ayıralım

df_dogrusal_olmayan_alt <- df_dogrusal_olmayan[df_dogrusal_olmayan$x < 0.5, ]
df_dogrusal_olmayan_ust <- df_dogrusal_olmayan[df_dogrusal_olmayan$x > 0.5, ]

Bu sefer plot fonksiyonu yerine ggplot2 paketini kullanabiliriz. (Not: Bu ders notunun amacı kullanılan paketleri öğretmek değil. Paketlerin detayları için ayrı bir ders hazırlanabilir.)

library(ggplot2)
B<- ggplot() +
  geom_smooth(data = df_dogrusal_olmayan_alt, aes(x = x, y = y_dogrusal_olmayan), method = "lm", formula = y ~ poly(x, 2), se = FALSE, color = "black")+
  geom_point(data = df_dogrusal_olmayan_alt, aes(x = x, y = y_dogrusal_olmayan), size = 1, shape = 16, color = "black") +
  geom_smooth(data = df_dogrusal_olmayan_ust, aes(x = x, y = y_dogrusal_olmayan), method = "lm", formula = y ~ poly(x, 2), se = FALSE, color = "black") +
  geom_point(data = df_dogrusal_olmayan_ust, aes(x = x, y = y_dogrusal_olmayan), size = 1, shape = 16, color = "black") +
  labs(title = "B. Doğrusal Olmayan E[Y|X]", y = "Y", x = "x") +
  theme_bw() +
  theme(legend.position = "none") +
  geom_vline(xintercept = 0.5, linetype = "dashed") +
  xlim(0, 1)

3.grafik RD ile karıştırılma ihtimali olan tasarım.

df_hatalı <- data.frame(x = x, y_hatalı = y_hatalı)
df_hatalı_alt <- df_hatalı[df_hatalı$x < 0.5, ]
df_hatalı_ust <- df_hatalı[df_hatalı$x >= 0.5, ]

Quadratic fonksiyon yerine, bir süreksizlik fonksiyonu belirlenmiş

discontinuity <- function(x) {
  1 / (1 + exp(-25 * (x - 0.5)))
}
C<- ggplot() +
  geom_smooth(data = df_hatalı_alt, aes(x = x, y = y_hatalı), method = "lm", se = FALSE, color = "black") +
  geom_smooth(data = df_hatalı_ust, aes(x = x, y = y_hatalı), method = "lm", se = FALSE, color = "black") +
  geom_function(fun = discontinuity, linetype = "dashed") +
  geom_point(data = df_hatalı, aes(x = x, y = y_hatalı), size = 1, shape = 16, color = "black") +
  labs(title = "C. Doğrusal olmama durumunun süreksiz olmakla karıştırılması", y = "Y", x = "x") +
  theme_bw() +
  theme(legend.position = "none") +
  geom_vline(xintercept = 0.5, linetype = "dashed") +
  xlim(0, 1)

Bu gösterim yerine, 2 grafiği birleştirerek göstermek isterseniz cowplot paketini kullanabilirsiniz.

Bunun için ilk olarak cowplot paketini indirelim. Ardından indirilen paketi çalıştıralım. Bunun için de library() fonksiyonunu kullanacağız.

library(cowplot)
cowplot::plot_grid(B, C, ncol = 1, align = "h")
## `geom_smooth()` using formula = 'y ~ x'
## `geom_smooth()` using formula = 'y ~ x'

Şekil 6.1.2 tekrarı

Lee’nin (2008) parti görevinin yeniden seçilme olasılıkları üzerindeki etkisini incelediği keskin RD tasarımını göstermektedir.

Soru:

ABD Temsilciler Meclisi’nde bir koltuk için Demokrat adayın partisinin geçen sefer sandalyeyi kazanması durumunda bir sonraki seçim için avantajının olup olmadığıyla ilgilenmektedir

Lee, görevde olmanın nedensel etkisini yakalamak için bir önceki seçimdeki göreli oy paylarını kazanma olasılığına bağlı olarak inceliyor. Özellikle, bir seçimi kazananın \(Di=1(xi≥0)\) şeklinde belirlendiği gerçeğinden yararlanıyor; burada \(x_i\), kazananın oy payı marjını temsil etmektedir. \(D_i\), \(x_i\) ’nin deterministik bir fonksiyonu olduğundan, \(x_i\) dışında başka bir karıştırıcı değişkenin olmadığına dikkat edilmelidir. Bu, RD tasarımının sinyal özelliğidir.

library(haven)
library(data.table)
library(ggplot2)
library(gridExtra)

veri setini indirelim.

download.file('https://economics.mit.edu/people/faculty/josh-angrist/mhe-data-archive', 'Lee2008.zip')
library(haven)
individ_final.dta <- read_dta("C:/Users/User1/OneDrive/Masaüstü/Lee2008/individ_final.dta")
View(individ_final.dta)
library(data.table)
lee <- data.table(read_dta('individ_final.dta'))
library(dplyr)
## 
## Attaching package: 'dplyr'
## The following object is masked from 'package:gridExtra':
## 
##     combine
## The following objects are masked from 'package:data.table':
## 
##     between, first, last
## The following objects are masked from 'package:stats':
## 
##     filter, lag
## The following objects are masked from 'package:base':
## 
##     intersect, setdiff, setequal, union
library(DT)
data.table(lee)
##        yearel myoutcome second myoutcomenext use    difshare difgrp
##     1:   1946         1     NA             0  NA  0.06148815    212
##     2:   1946         0      1             0   1 -0.06148815    187
##     3:   1948         1     NA             1   1  0.10486948    220
##     4:   1948         0      1             0  NA -0.10486948    179
##     5:   1948         0     NA             0  NA -0.53572100     92
##    ---                                                             
## 27172:   1996         1     NA             0  NA  0.19821346    239
## 27173:   1996         0      1             1   1 -0.19821346    160
## 27174:   1996         0     NA             0  NA -0.21053660    157
## 27175:   1998         1     NA            NA  NA  0.60390604    320
## 27176:   1998         0      1            NA  NA -0.60390604     79
##        mmyoutcomenext mrunagain mofficeexp melectexp mpmyoutcomenext mprunagain
##     1:             NA        NA         NA        NA              NA         NA
##     2:     0.10714286 0.2142857  2.0535715 2.3392856     0.069917142  0.2855549
##     3:     0.74358976 0.8717949  3.2564104 3.4615386     0.749363303  0.8693877
##     4:             NA        NA         NA        NA              NA         NA
##     5:             NA        NA         NA        NA              NA         NA
##    ---                                                                         
## 27172:             NA        NA         NA        NA              NA         NA
## 27173:     0.05405406 0.2702703  0.2972973 0.5405405     0.009250412  0.1554371
## 27174:             NA        NA         NA        NA              NA         NA
## 27175:             NA        NA         NA        NA              NA         NA
## 27176:             NA        NA         NA        NA              NA         NA
##        mpofficeexp mpelectexp
##     1:          NA         NA
##     2:   0.6714829  0.9329183
##     3:   2.6508601  2.8722246
##     4:          NA         NA
##     5:          NA         NA
##    ---                       
## 27172:          NA         NA
## 27173:   0.1880660  0.3967127
## 27174:          NA         NA
## 27175:          NA         NA
## 27176:          NA         NA

2- Verisetini sadece 2 değişkene indirin. Oy farkı (Running variable, x, ve sonuç değişkeni (Y).

df <- lee %>%
  select(myoutcomenext, difshare) %>%
  na.omit()
head(df)
##    myoutcomenext    difshare
## 1:             0  0.06148815
## 2:             0 -0.06148815
## 3:             1  0.10486948
## 4:             0 -0.10486948
## 5:             0 -0.53572100
## 6:             0  0.16446409

D değişkenini oluşturun.

df <- df %>%
  mutate(D = as.numeric(difshare >= 0))
head(df)
##    myoutcomenext    difshare D
## 1:             0  0.06148815 1
## 2:             0 -0.06148815 0
## 3:             1  0.10486948 1
## 4:             0 -0.10486948 0
## 5:             0 -0.53572100 0
## 6:             0  0.16446409 1

D değişkeni, Oy farkı (difshare) pozitifse 1 değilse 0 şeklinde oluşturuldu.

4- 4. dereceden logit regresyonu tahmin edin.

logit <- glm(formula = myoutcomenext ~ poly(difshare, degree = 4) +
               poly(difshare, degree = 4) * D,
             family = binomial(link = "logit"),
             data = df)
df <- df %>%
  mutate(pmyoutcomenext = predict(logit, type = "response"))
head(df)
##    myoutcomenext    difshare D pmyoutcomenext
## 1:             0  0.06148815 1    0.695785959
## 2:             0 -0.06148815 0    0.057708113
## 3:             1  0.10486948 1    0.738774903
## 4:             0 -0.10486948 0    0.029672513
## 5:             0 -0.53572100 0    0.001221896
## 6:             0  0.16446409 1    0.778284984

5- 0.005 aralıklarla yerel ortalamalar oluşturun.

breaks <- round(seq(-1, 1, by = 0.005), 3)
df <- df  %>%
  mutate(i005 = cut(difshare, breaks = breaks, labels = head(breaks, -1), right = TRUE),
         i005 = as.numeric(as.character(i005))) %>%
  group_by(i005) %>%
  mutate(m_next = mean(myoutcomenext),
         mp_next = mean(pmyoutcomenext)) %>%
  ungroup() %>%
  filter(i005 > -0.251 & i005 < 0.251)
head(df)
## # A tibble: 6 × 7
##   myoutcomenext difshare     D pmyoutcomenext   i005 m_next mp_next
##           <dbl>    <dbl> <dbl>          <dbl>  <dbl>  <dbl>   <dbl>
## 1             0   0.0615     1         0.696   0.06  0.72    0.697 
## 2             0  -0.0615     0         0.0577 -0.065 0.0594  0.0570
## 3             1   0.105      1         0.739   0.1   0.678   0.737 
## 4             0  -0.105      0         0.0297 -0.105 0.0556  0.0308
## 5             0   0.164      1         0.778   0.16  0.792   0.777 
## 6             0  -0.164      0         0.0130 -0.165 0       0.0133

6- Grafikler

KO <- ggplot(data = df, aes(x = i005)) +
  geom_point(aes(y = m_next)) +
  geom_line(aes(y = mp_next, group = i005 >= 0)) +
  geom_vline(xintercept = 0, linetype = 'longdash') +
  xlab('Demokratların kazanma oy oranları marjini, t seçimi') +
  ylab('Kazanma Olasılığı, t+1 Seçimi') +
  ggtitle('A')
KO

2.grafik için iki ayrı grup oluşturun

df2 <- lee %>%
  mutate(i005 = cut(difshare, breaks = breaks, labels = head(breaks, -1), right = TRUE),
         i005 = as.numeric(as.character(i005))) %>%
  group_by(i005) %>%
  summarize(m_vic = mean(mofficeexp, na.rm = TRUE),
            mp_vic = mean(mpofficeexp, na.rm = TRUE)) %>%
  ungroup() %>%
  filter(i005 > -0.251 & i005 < 0.251)
head(df2)
## # A tibble: 6 × 3
##     i005  m_vic mp_vic
##    <dbl>  <dbl>  <dbl>
## 1 -0.25  0.0513 0.0995
## 2 -0.245 0.315  0.106 
## 3 -0.24  0      0.114 
## 4 -0.235 0      0.121 
## 5 -0.23  0.0698 0.130 
## 6 -0.225 0      0.138
OM <- ggplot(data = df2, aes(x = i005)) +
  geom_point(aes(y = m_vic)) +
  geom_line(aes(y = mp_vic, group = i005 >= 0)) +
  geom_vline(xintercept = 0, linetype = 'longdash') +
  xlab('Demokratların kazanma oy oranları marjini, t seçimi') +
  ylab('t seçimiyle birlikte geçmiş kazanma sayısı') +
  ggtitle('B')
OM

lee.p <- grid.arrange(KO, OM, ncol = 1)

Bulanık Kesikli Rassal Deney (Fuzzy RD)

STAR deneyi

Tablo 2.2.1 Replikasyonu

Veri seti Kruger (1999) çalışmasında ele alınan veri seti indirilmiştir.

Stata veri setini R’a yüklemek için haven paketini indiriyoruz.

library(haven)
webstar_7_ <- read_dta("C:/Users/User1/Downloads/webstar (7).dta")
data.table(webstar_7_)
##         newid ssex srace sbirthq sbirthy stark star1 star2 star3 cltypek
##     1:   1122    2     2       3    1979     2     2     2     1      NA
##     2:   1137    2     1       1    1980     1     1     1     1       1
##     3:   1143    2     2       4    1979     1     1     1     1       1
##     4:   1160    1     1       4    1979     2     2     2     1      NA
##     5:   1183    1     2       1    1980     1     2     2     2       3
##    ---                                                                  
## 11594: 186650    1     1       3    1979     1     1     1     1       1
## 11595: 186665    2     1       3    1980     1     1     1     1       2
## 11596: 186687    1     1       1    1980     2     1     1     1      NA
## 11597: 186705    2     2       1    1980     1     1     1     1       2
## 11598: 186718    1     2       2    1980     1     1     1     1       3
##        cltype1 cltype2 cltype3 schtypek hdegk cladk totexpk tracek treadssk
##     1:      NA      NA       2       NA    NA    NA      NA     NA       NA
##     2:       1       1       1        3     2     1       7      1      447
##     3:       1       3       3        2     2     1      21      1      450
##     4:      NA      NA       1       NA    NA    NA      NA     NA       NA
##     5:      NA      NA      NA        1     2     6       0      1      439
##    ---                                                                     
## 11594:       1       1       1        3     2     1       8      1      483
## 11595:       2       2       2        3     2     6       0      1      437
## 11596:       2       2       2       NA    NA    NA      NA     NA       NA
## 11597:       3       2       3        1     2     1      24      2      431
## 11598:       3       3       3        1     2    NA       2      1      421
##        tmathssk sesk schtype1 trace1 hdeg1 clad1 totexp1 treadss1 tmathss1 ses1
##     1:       NA   NA       NA     NA    NA    NA      NA       NA       NA   NA
##     2:      473    2        3      1     1     4       7      507      538    1
##     3:      536    2        2      2     2     3      32      579      592   NA
##     4:       NA   NA       NA     NA    NA    NA      NA       NA       NA   NA
##     5:      463    1       NA     NA    NA    NA      NA       NA       NA   NA
##    ---                                                                         
## 11594:      559    2        3      1     2     4      13      590      584    2
## 11595:      513    1        3      1     1     4       7      533      557    1
## 11596:       NA   NA        2      1     1     3       0      571      557    2
## 11597:      478    1        1      2     1     4      27      475      486    1
## 11598:      449    2        1      1     1     4      10      468      486    1
##        schtype2 trace2 hdeg2 clad2 totexp2 treadss2 tmathss2 ses2 schtype3
##     1:       NA     NA    NA    NA      NA       NA       NA   NA        2
##     2:        3      1     1     2       3      568      579    2        3
##     3:        2      2     1     4       4      588      579    2        2
##     4:       NA     NA    NA    NA      NA       NA       NA   NA        3
##     5:       NA     NA    NA    NA      NA       NA       NA   NA       NA
##    ---                                                                    
## 11594:        3      1     2     6      15      650      648    2        3
## 11595:        3      1     1     2       1      586      611    1        3
## 11596:        2      1     1     4       8      604      620    2        2
## 11597:        1      2     1     4       7      542      541    1        1
## 11598:        1      1     1     4      14      571      568    1        1
##        treadss3 tmathss3 ses3 trace3 hdeg3 clad3 totexp3 sysidkn sysid1n
##     1:      580      564    1      1     1     4      30      NA      NA
##     2:      587      593    1      1     1     2       1      30      30
##     3:      644      639    2      1     1     4       4      11      11
##     4:      686      667    2      1     1     4      10      NA      NA
##     5:       NA       NA   NA     NA    NA    NA      NA      11      NA
##    ---                                                                  
## 11594:      675      678    2      1     2     4      17      21      21
## 11595:      654      651    1      1     1     1       7      33      33
## 11596:      595      672    2      1     1     4      22      NA      25
## 11597:      624      610    1      1     2     3      12      11      11
## 11598:      580      577    2      2     2     4      33      11      11
##        sysid2n sysid3n schidkn schid1n schid2n schid3n
##     1:      NA      22      NA      NA      NA      54
##     2:      30      30      63      63      63      63
##     3:      11      11      20      20      20      20
##     4:      NA       6      NA      NA      NA       8
##     5:      NA      NA      19      NA      NA      NA
##    ---                                                
## 11594:      21      21      49      49      49      49
## 11595:      33      33      67      67      67      67
## 11596:      25      25      NA      58      58      58
## 11597:      11      11      22      22      22      22
## 11598:      11      11      32      32      32      32

srace değişkeninin açıklamaları

value label 1 white 2 black 3 asian 4 hispanic 5 am. indian 6 other 9 missing

srace değişkeni NA’leri çıkar.

webstar_7_ <- data.frame(webstar_7_)
webstar_7_ <- webstar_7_[!is.na(webstar_7_$srace), ]

Gerekli değişiklikleri yapılacak.

library(dplyr)
webstar_7_ <- as.data.frame(webstar_7_)
webstar_7_ <- webstar_7_ %>% mutate(white_asian = case_when(srace==1 | srace==3 ~ 1 , TRUE ~ 0))
data.table(webstar_7_)
##         newid ssex srace sbirthq sbirthy stark star1 star2 star3 cltypek
##     1:   1122    2     2       3    1979     2     2     2     1      NA
##     2:   1137    2     1       1    1980     1     1     1     1       1
##     3:   1143    2     2       4    1979     1     1     1     1       1
##     4:   1160    1     1       4    1979     2     2     2     1      NA
##     5:   1183    1     2       1    1980     1     2     2     2       3
##    ---                                                                  
## 11449: 186650    1     1       3    1979     1     1     1     1       1
## 11450: 186665    2     1       3    1980     1     1     1     1       2
## 11451: 186687    1     1       1    1980     2     1     1     1      NA
## 11452: 186705    2     2       1    1980     1     1     1     1       2
## 11453: 186718    1     2       2    1980     1     1     1     1       3
##        cltype1 cltype2 cltype3 schtypek hdegk cladk totexpk tracek treadssk
##     1:      NA      NA       2       NA    NA    NA      NA     NA       NA
##     2:       1       1       1        3     2     1       7      1      447
##     3:       1       3       3        2     2     1      21      1      450
##     4:      NA      NA       1       NA    NA    NA      NA     NA       NA
##     5:      NA      NA      NA        1     2     6       0      1      439
##    ---                                                                     
## 11449:       1       1       1        3     2     1       8      1      483
## 11450:       2       2       2        3     2     6       0      1      437
## 11451:       2       2       2       NA    NA    NA      NA     NA       NA
## 11452:       3       2       3        1     2     1      24      2      431
## 11453:       3       3       3        1     2    NA       2      1      421
##        tmathssk sesk schtype1 trace1 hdeg1 clad1 totexp1 treadss1 tmathss1 ses1
##     1:       NA   NA       NA     NA    NA    NA      NA       NA       NA   NA
##     2:      473    2        3      1     1     4       7      507      538    1
##     3:      536    2        2      2     2     3      32      579      592   NA
##     4:       NA   NA       NA     NA    NA    NA      NA       NA       NA   NA
##     5:      463    1       NA     NA    NA    NA      NA       NA       NA   NA
##    ---                                                                         
## 11449:      559    2        3      1     2     4      13      590      584    2
## 11450:      513    1        3      1     1     4       7      533      557    1
## 11451:       NA   NA        2      1     1     3       0      571      557    2
## 11452:      478    1        1      2     1     4      27      475      486    1
## 11453:      449    2        1      1     1     4      10      468      486    1
##        schtype2 trace2 hdeg2 clad2 totexp2 treadss2 tmathss2 ses2 schtype3
##     1:       NA     NA    NA    NA      NA       NA       NA   NA        2
##     2:        3      1     1     2       3      568      579    2        3
##     3:        2      2     1     4       4      588      579    2        2
##     4:       NA     NA    NA    NA      NA       NA       NA   NA        3
##     5:       NA     NA    NA    NA      NA       NA       NA   NA       NA
##    ---                                                                    
## 11449:        3      1     2     6      15      650      648    2        3
## 11450:        3      1     1     2       1      586      611    1        3
## 11451:        2      1     1     4       8      604      620    2        2
## 11452:        1      2     1     4       7      542      541    1        1
## 11453:        1      1     1     4      14      571      568    1        1
##        treadss3 tmathss3 ses3 trace3 hdeg3 clad3 totexp3 sysidkn sysid1n
##     1:      580      564    1      1     1     4      30      NA      NA
##     2:      587      593    1      1     1     2       1      30      30
##     3:      644      639    2      1     1     4       4      11      11
##     4:      686      667    2      1     1     4      10      NA      NA
##     5:       NA       NA   NA     NA    NA    NA      NA      11      NA
##    ---                                                                  
## 11449:      675      678    2      1     2     4      17      21      21
## 11450:      654      651    1      1     1     1       7      33      33
## 11451:      595      672    2      1     1     4      22      NA      25
## 11452:      624      610    1      1     2     3      12      11      11
## 11453:      580      577    2      2     2     4      33      11      11
##        sysid2n sysid3n schidkn schid1n schid2n schid3n white_asian
##     1:      NA      22      NA      NA      NA      54           0
##     2:      30      30      63      63      63      63           1
##     3:      11      11      20      20      20      20           0
##     4:      NA       6      NA      NA      NA       8           1
##     5:      NA      NA      19      NA      NA      NA           0
##    ---                                                            
## 11449:      21      21      49      49      49      49           1
## 11450:      33      33      67      67      67      67           1
## 11451:      25      25      NA      58      58      58           1
## 11452:      11      11      22      22      22      22           0
## 11453:      11      11      32      32      32      32           0

cltypek değişkeninin açıklamaları.

value label 1 small class 2 regular class 3 regular + aide class

webstar_7_<- webstar_7_[!is.na(webstar_7_$cltypek), ]
library(car)
## Zorunlu paket yükleniyor: carData
## 
## Attaching package: 'car'
## The following object is masked from 'package:dplyr':
## 
##     recode
res.ftest <- fligner.test(white_asian ~ cltypek, data = webstar_7_)
res.ftest
## 
##  Fligner-Killeen test of homogeneity of variances
## 
## data:  white_asian by cltypek
## Fligner-Killeen:med chi-squared = 2.7615, df = 2, p-value = 0.2514

sesk değişkenin açıklamarı.

value label 1 free lunch 2 non-free lunch

webstar_7_ <- webstar_7_[!is.na(webstar_7_$sesk), ]
webstar_7_ <- webstar_7_ %>% mutate(free_lunch = case_when(sesk==1 ~ 1 , sesk==2 ~ 0))
webstar_7_ %>%
  group_by(cltypek) %>%
  summarise_at(c("white_asian", "free_lunch", "treadssk", "tmathssk"), mean, na.rm = TRUE)
## # A tibble: 3 × 5
##   cltypek                  white_asian free_lunch treadssk tmathssk
##   <dbl+lbl>                      <dbl>      <dbl>    <dbl>    <dbl>
## 1 1 [small class]                0.682      0.471     441.     491.
## 2 2 [regular class]              0.675      0.477     435.     483.
## 3 3 [regular + aide class]       0.660      0.503     435.     483.
res.ftest <- fligner.test(free_lunch ~ cltypek, data = webstar_7_)
res.ftest
## 
##  Fligner-Killeen test of homogeneity of variances
## 
## data:  free_lunch by cltypek
## Fligner-Killeen:med chi-squared = 3.2153, df = 2, p-value = 0.2004

The Angrist and Lavy (1999) replikasyonu

library(haven)
final4 <- read_dta("C:/Users/User1/Downloads/final4.dta")
View(final4)
datatable(final4)
library(haven)
final5 <- read_dta("C:/Users/User1/Downloads/final5.dta")
View(final5)
datatable(final5)

Angrist ve Lavy (1999) makalesinde, İbn Meymun’un kuralının İsrail devlet okullarında sınıf mevcudu belirlemek için kullanıldığından bahsediyorlar. Bu kurala göre, en fazla 40 öğrenci bir sınıfa kaydedilebilir. Makalede, bu kuralın varyasyonlarına dayanarak sınıf mevcudunun öğrenci başarısı üzerindeki etkisini tahmin etmek mümkün olduğunu belirtiyorlar.

İbn Meymun’un kuralına göre, sınıf mevcudu 40 öğrenciye kadar kayıtla bire bir artar. Ancak 41 öğrenci kaydolduğunda, ortalama sınıf mevcudu 20.5’e düşer. Benzer şekilde, 80 öğrenci kaydolduğunda ortalama sınıf mevcudu 40 olurken, 81 öğrenci kaydolduğunda ortalama sınıf mevcudu 27’ye düşer.

Bu varyasyonları kullanarak, araştırmacılar İsrailli öğrencilerin başarısı üzerinde sınıf mevcudunun etkisini tahmin etmek için bu kuralı kullanmışlardır. Bu, sınıf mevcudu değişkeninin doğal bir deneyim gibi işlev görmesini sağlar, çünkü kayıt sayısının belirli bir eşik değeri aşıldığında sınıf mevcudu beklenmedik şekilde değişir.

Angrist ve Lavy, bu tahminleri kullanarak sınıf mevcudunun öğrenci başarısı üzerindeki etkisini değerlendirmişler ve bu etkinin pozitif olduğunu bulmuşlardır. Daha küçük sınıflarda öğrenim gören öğrencilerin genellikle daha iyi performans gösterdiği sonucuna varmışlardır. Bu bulgular, daha küçük sınıfların öğrenci başarısını artırabileceği fikrini desteklemektedir.

library(tidyr)
final4 %>% 
  select(classize, c_size, tip_a, verbsize, mathsize, avgverb, avgmath) %>%
  rename("Enrollment" = "c_size", "Percent disadvantaged" = "tip_a", "Class size" = "classize", "Reading size" = "verbsize", "Math size" = "mathsize", "Average verbal" = "avgverb", "Average math" = "avgmath") %>%
  mutate_at(c('Enrollment', 'Class size','Math size', 'Reading size', 'Average math','Average verbal', 'Percent disadvantaged'), as.numeric) %>%
  summarise(across(where(is.numeric), .fns = 
                     list(Mean = ~mean(.,na.rm=TRUE),
                          S.D. = ~sd(.,na.rm=TRUE),
                          Q10 = ~quantile(., 0.10, na.rm=TRUE),
                          Q25 = ~quantile(., 0.25, na.rm=TRUE),
                          Q50 = ~quantile(., 0.25, na.rm=TRUE),
                          Q75 = ~quantile(., 0.75, na.rm=TRUE),
                          Q90 = ~quantile(., 0.90, na.rm=TRUE)))) %>%
  pivot_longer(everything(), names_sep='_', names_to=c('variable', '.value')) %>%
  mutate(across(where(is.numeric), round, 2))
## Warning: There was 1 warning in `mutate()`.
## ℹ In argument: `across(where(is.numeric), round, 2)`.
## Caused by warning:
## ! The `...` argument of `across()` is deprecated as of dplyr 1.1.0.
## Supply arguments directly to `.fns` through an anonymous function instead.
## 
##   # Previously
##   across(a:b, mean, na.rm = TRUE)
## 
##   # Now
##   across(a:b, \(x) mean(x, na.rm = TRUE))
## # A tibble: 7 × 8
##   variable               Mean  S.D.   Q10   Q25   Q50   Q75   Q90
##   <chr>                 <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 Class size             30.3  6.41  22    26    26    35    38  
## 2 Enrollment             78.4 37.9   30    51    51   102   128  
## 3 Percent disadvantaged  13.9 13.4    2     4     4    19    35  
## 4 Reading size           27.6  6.55  19    24    24    32    36  
## 5 Math size              28.1  6.56  19    24    24    33    36  
## 6 Average verbal         72.5  7.99  62.2  67.7  67.7  78.2  82  
## 7 Average math           68.9  8.77  57.5  63.6  63.6  75.0  79.4
final5 %>% 
  select(classize, c_size, tip_a, verbsize, mathsize, avgverb, avgmath) %>%
  rename("Enrollment" = "c_size", "Percent disadvantaged" = "tip_a", "Class size" = "classize", "Reading size" = "verbsize", "Math size" = "mathsize", "Average verbal" = "avgverb", "Average math" = "avgmath") %>%
  mutate_at(c('Enrollment', 'Class size','Math size', 'Reading size', 'Average math','Average verbal', 'Percent disadvantaged'), as.numeric) %>%
  summarise(across(where(is.numeric), .fns = 
                     list(Mean = ~mean(.,na.rm=TRUE),
                          S.D. = ~sd(.,na.rm=TRUE),
                          Q10 = ~quantile(., 0.10, na.rm=TRUE),
                          Q25 = ~quantile(., 0.25, na.rm=TRUE),
                          Q50 = ~quantile(., 0.25, na.rm=TRUE),
                          Q75 = ~quantile(., 0.75, na.rm=TRUE),
                          Q90 = ~quantile(., 0.90, na.rm=TRUE)))) %>%
  pivot_longer(everything(), names_sep='_', names_to=c('variable', '.value')) %>%
  mutate(across(where(is.numeric), round, 2))
## # A tibble: 7 × 8
##   variable               Mean  S.D.   Q10   Q25   Q50   Q75   Q90
##   <chr>                 <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 Class size             30.0  6.6   21    26    26    35    38  
## 2 Enrollment             77.9 39.1   31    50    50   100   128. 
## 3 Percent disadvantaged  14.1 13.6    2     4     4    20    35  
## 4 Reading size           27.3  6.62  19    23    23    32    36  
## 5 Math size              27.7  6.68  19    23    23    33    36  
## 6 Average verbal         74.4  8.08  64.2  69.9  69.9  79.8  83.3
## 7 Average math           67.3 10.0   54.8  61.1  61.1  74.1  79.4
final4ek<- final4 %>% 
  filter(classize > 1, classize < 45, c_size>5)
final4ek %>% 
  select(classize, c_size, tip_a, verbsize, mathsize, avgverb, avgmath) %>%
  rename("Enrollment" = "c_size", "Percent disadvantaged" = "tip_a", "Class size" = "classize", "Reading size" = "verbsize", "Math size" = "mathsize", "Average verbal" = "avgverb", "Average math" = "avgmath") %>%
  mutate_at(c('Enrollment', 'Class size','Math size', 'Reading size', 'Average math','Average verbal', 'Percent disadvantaged'), as.numeric) %>%
  summarise(across(where(is.numeric), .fns = 
                     list(Mean = ~mean(.,na.rm=TRUE),
                          S.D. = ~sd(.,na.rm=TRUE),
                          Q10 = ~quantile(., 0.10, na.rm=TRUE),
                          Q25 = ~quantile(., 0.25, na.rm=TRUE),
                          Q50 = ~quantile(., 0.25, na.rm=TRUE),
                          Q75 = ~quantile(., 0.75, na.rm=TRUE),
                          Q90 = ~quantile(., 0.90, na.rm=TRUE)))) %>%
  pivot_longer(everything(), names_sep='_', names_to=c('variable', '.value')) %>%
  mutate(across(where(is.numeric), round, 2))
## # A tibble: 7 × 8
##   variable               Mean  S.D.   Q10   Q25   Q50   Q75   Q90
##   <chr>                 <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 Class size             30.3  6.35  22    26    26    35    38  
## 2 Enrollment             78.3 37.9   30    51    51   102   128. 
## 3 Percent disadvantaged  13.9 13.4    2     4     4    19    35  
## 4 Reading size           27.7  6.54  19    24    24    32    36  
## 5 Math size              28.1  6.55  19    24    24    33    36  
## 6 Average verbal         72.5  7.99  62.2  67.7  67.7  78.2  82  
## 7 Average math           68.9  8.77  57.5  63.6  63.6  75.0  79.4
final5ek<- final5 %>% 
  filter(classize > 1, classize < 45, c_size>5)
final5ek %>% 
  select(classize, c_size, tip_a, verbsize, mathsize, avgverb, avgmath) %>%
  rename("Enrollment" = "c_size", "Percent disadvantaged" = "tip_a", "Class size" = "classize", "Reading size" = "verbsize", "Math size" = "mathsize", "Average verbal" = "avgverb", "Average math" = "avgmath") %>%
  mutate_at(c('Enrollment', 'Class size','Math size', 'Reading size', 'Average math','Average verbal', 'Percent disadvantaged'), as.numeric) %>%
  summarise(across(where(is.numeric), .fns = 
                     list(Mean = ~mean(.,na.rm=TRUE),
                          S.D. = ~sd(.,na.rm=TRUE),
                          Q10 = ~quantile(., 0.10, na.rm=TRUE),
                          Q25 = ~quantile(., 0.25, na.rm=TRUE),
                          Q50 = ~quantile(., 0.25, na.rm=TRUE),
                          Q75 = ~quantile(., 0.75, na.rm=TRUE),
                          Q90 = ~quantile(., 0.90, na.rm=TRUE)))) %>%
  pivot_longer(everything(), names_sep='_', names_to=c('variable', '.value')) %>%
  mutate(across(where(is.numeric), round, 2))
## # A tibble: 7 × 8
##   variable               Mean  S.D.   Q10   Q25   Q50   Q75   Q90
##   <chr>                 <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 Class size             29.9  6.54  21    26    26    35    38  
## 2 Enrollment             77.9 39.1   31    50    50   100   129. 
## 3 Percent disadvantaged  14.1 13.6    2     4     4    20    35  
## 4 Reading size           27.3  6.58  19    23    23    32    36  
## 5 Math size              27.7  6.64  19    23    23    33    36  
## 6 Average verbal         74.4  8.08  64.2  69.8  69.8  79.8  83.3
## 7 Average math           67.3 10.0   54.8  61.1  61.1  74.1  79.4
final4ekdis<- final4ek %>% 
  filter(c_size>35 & c_size<46 | c_size>75 & c_size<86 | c_size>115 & c_size<125)
final4ekdis %>% 
  select(classize, c_size, tip_a, verbsize, mathsize, avgverb, avgmath) %>%
  rename("Enrollment" = "c_size", "Percent disadvantaged" = "tip_a", "Class size" = "classize", "Reading size" = "verbsize", "Math size" = "mathsize", "Average verbal" = "avgverb", "Average math" = "avgmath") %>%
  mutate_at(c('Enrollment', 'Class size','Math size', 'Reading size', 'Average math','Average verbal', 'Percent disadvantaged'), as.numeric) %>%
  summarise(across(where(is.numeric), .fns = 
                     list(Mean = ~mean(.,na.rm=TRUE),
                          S.D. = ~sd(.,na.rm=TRUE),
                          Q10 = ~quantile(., 0.10, na.rm=TRUE),
                          Q25 = ~quantile(., 0.25, na.rm=TRUE),
                          Q50 = ~quantile(., 0.25, na.rm=TRUE),
                          Q75 = ~quantile(., 0.75, na.rm=TRUE),
                          Q90 = ~quantile(., 0.90, na.rm=TRUE)))) %>%
  pivot_longer(everything(), names_sep='_', names_to=c('variable', '.value')) %>%
  mutate(across(where(is.numeric), round, 2))
## # A tibble: 7 × 8
##   variable               Mean  S.D.   Q10   Q25   Q50   Q75   Q90
##   <chr>                 <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 Class size             31.0  7.24  21    25    25    38    40  
## 2 Enrollment             77.9 29.6   41    43    43   116   119  
## 3 Percent disadvantaged  13.0 12.4    1     4     4    18    32  
## 4 Reading size           28.2  7.71  18    22    22    35    37.2
## 5 Math size              28.6  7.69  18    23    23    35    38  
## 6 Average verbal         72.4  7.88  61.9  67.0  67.0  78.4  81.7
## 7 Average math           68.7  9.14  56.8  62.6  62.6  75.4  79.7
final5ekdis<- final5ek %>% 
  filter(c_size>35 & c_size<46 | c_size>75 & c_size<86 | c_size>115 & c_size<125)
final5ekdis %>% 
  select(classize, c_size, tip_a, verbsize, mathsize, avgverb, avgmath) %>%
  rename("Enrollment" = "c_size", "Percent disadvantaged" = "tip_a", "Class size" = "classize", "Reading size" = "verbsize", "Math size" = "mathsize", "Average verbal" = "avgverb", "Average math" = "avgmath") %>%
  mutate_at(c('Enrollment', 'Class size','Math size', 'Reading size', 'Average math','Average verbal', 'Percent disadvantaged'), as.numeric) %>%
  summarise(across(where(is.numeric), .fns = 
                     list(Mean = ~mean(.,na.rm=TRUE),
                          S.D. = ~sd(.,na.rm=TRUE),
                          Q10 = ~quantile(., 0.10, na.rm=TRUE),
                          Q25 = ~quantile(., 0.25, na.rm=TRUE),
                          Q50 = ~quantile(., 0.25, na.rm=TRUE),
                          Q75 = ~quantile(., 0.75, na.rm=TRUE),
                          Q90 = ~quantile(., 0.90, na.rm=TRUE)))) %>%
  pivot_longer(everything(), names_sep='_', names_to=c('variable', '.value')) %>%
  mutate(across(where(is.numeric), round, 2))
## # A tibble: 7 × 8
##   variable               Mean  S.D.   Q10   Q25   Q50   Q75   Q90
##   <chr>                 <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
## 1 Class size             30.7  7.43  21    24    24    38    40  
## 2 Enrollment             75.8 29.2   40.4  43    43    85   119  
## 3 Percent disadvantaged  13.7 13.2    2     4     4    17    36  
## 4 Reading size           28.1  7.35  18    21    21    35    38  
## 5 Math size              28.5  7.46  18    22    22    35    38  
## 6 Average verbal         74.5  8.22  63.8  69.6  69.6  80.5  83.6
## 7 Average math           67.0 10.3   54.5  60.8  60.8  74.1  80.0

Şekil 6.2.1 replikasyonu

Meymun_rule <- function(x) {x / (floor((x - 1)/40) + 1)}

Bu grafiği tekrarlayabilmek için ortalamarı bulmalıyız.

final4Enrollmentmeans <- final4ek %>%
  group_by(c_size) %>%
  summarise(mean_class_size = mean(classize, na.rm = TRUE))
ggplot(data = final4Enrollmentmeans, aes(x = c_size)) + geom_line(aes(y = mean_class_size)) +
           stat_function(fun      = Meymun_rule,
                         linetype = "dashed")           +
           expand_limits(y = 0)                         +
           scale_x_continuous(breaks = seq(0, 240, 40)) +
           ylab("Class size")                           +
           xlab("Enrollment count")                     +
           ggtitle("B. Fourth grade")

final5Enrollmentmeans <- final5ek %>%
  group_by(c_size) %>%
  summarise(mean_class_size = mean(classize, na.rm = TRUE))
ggplot(data = final5Enrollmentmeans, aes(x = c_size)) + geom_line(aes(y = mean_class_size)) +
           stat_function(fun      = Meymun_rule,
                         linetype = "dashed")           +
           expand_limits(y = 0)                         +
           scale_x_continuous(breaks = seq(0, 240, 40)) +
           ylab("Class size")                           +
           xlab("Enrollment count")                     +
           ggtitle("A. Fifth grade")

40, 80 ve 120’lik kayıt seviyelerinde sınıf mevcudunda belirgin düşüşler var.İbn Meymun kuralı kesikli çizgilerle gösterilmiş. Bu kural araç değişkeni olarak kullanılabilir.

library(sandwich)
library(lmtest)
## Zorunlu paket yükleniyor: zoo
## 
## Attaching package: 'zoo'
## The following objects are masked from 'package:base':
## 
##     as.Date, as.Date.numeric
library(AER)
## Zorunlu paket yükleniyor: survival

Araç değişken regresyonu için estimatr paketini kullanacağız.

library(estimatr)

Tüm Veri Regresyon sonuçları

final5ek = final5ek %>% 
       mutate(avgmath = case_when(avgmath >100 ~ avgmath - 100,
                             TRUE ~ avgmath))
final5ek <- filter(final5ek,c_leom==1 & c_pik<3)
final5ek <- filter(final5ek,classize>1 & classize<45 & c_size>5)
final5ek <- filter(final5ek,mathsize>0)
ols1 <- lm_robust(avgmath ~ classize, data = final5ek, clusters = final5ek$schlcode,se_type = "stata")
ols2 <- lm_robust(avgmath ~ classize + tipuach , data = final5ek, clusters = final5ek$schlcode,se_type = "stata")
ols3 <- lm_robust(avgmath ~ classize + tipuach + c_size , data = final5ek, clusters = final5ek$schlcode, se_type = "stata")

Süreksizlik Örneklemi

olsdis1 <- lm_robust(avgmath ~ classize, data = final5ekdis, clusters = final5ekdis$schlcode,se_type = "stata")
olsdis2 <- lm_robust(avgmath ~ classize + tipuach , data = final5ekdis, clusters = final5ekdis$schlcode,se_type = "stata")
olsdis3 <- lm_robust(avgmath ~ classize + tipuach + c_size , data = final5ekdis, clusters = final5ekdis$schlcode, se_type = "stata")
library(huxtable)
## 
## Attaching package: 'huxtable'
## The following object is masked from 'package:dplyr':
## 
##     add_rownames
## The following object is masked from 'package:ggplot2':
## 
##     theme_grey
huxreg(ols1, ols2, ols3,
       error_format = "[{statistic}]", 
       note         = "{stars}. T statistics in brackets.", number_format = 2)
## Warning in huxreg(ols1, ols2, ols3, error_format = "[{statistic}]", note = "{stars}. T statistics in brackets.", : Unrecognized statistics: logLik, AIC
## Try setting `statistics` explicitly in the call to `huxreg()`
(1)(2)(3)
(Intercept)57.66 ***69.81 ***70.09 ***
[46.24]   [59.49]   [59.94]   
classize0.32 ***0.08 *  0.02    
[8.01]   [2.12]   [0.44]   
tipuach       -0.34 ***-0.33 ***
       [-18.63]   [-17.76]   
c_size              0.02 *  
              [2.27]   
N2018       2018       2018       
R20.05    0.25    0.25    
*** p < 0.001; ** p < 0.01; * p < 0.05. T statistics in brackets.
huxreg(olsdis1, olsdis2, olsdis3,
       error_format = "[{statistic}]", 
       note         = "{stars}. T statistics in brackets.", number_format = 2)
## Warning in huxreg(olsdis1, olsdis2, olsdis3, error_format = "[{statistic}]", : Unrecognized statistics: logLik, AIC
## Try setting `statistics` explicitly in the call to `huxreg()`
(1)(2)(3)
(Intercept)55.80 ***69.59 ***69.04 ***
[21.30]   [28.04]   [27.55]   
classize0.37 ***0.10    0.06    
[4.56]   [1.36]   [0.74]   
tipuach       -0.40 ***-0.39 ***
       [-9.89]   [-9.33]   
c_size              0.02    
              [0.94]   
N465       465       465       
R20.07    0.30    0.30    
*** p < 0.001; ** p < 0.01; * p < 0.05. T statistics in brackets.

Araç Değişken Regresyonları

Araç değişkeni oluşturun.

final5ek$f <- final5ek$c_size / (floor((final5ek$c_size - 1) / 40) + 1)
final5ekdis$f <- final5ekdis$c_size / (floor((final5ekdis$c_size - 1) / 40) + 1)

Tüm veri seti için araç değişken tahminleri

iv1 <- iv_robust(avgmath ~ classize  | f , data = final5ek, clusters = final5ek$schlcode,se_type = "stata")
iv2 <- iv_robust(avgmath ~ classize + tipuach  | f + tipuach , data = final5ek, clusters = final5ek$schlcode,se_type = "stata")
iv3 <- iv_robust(avgmath ~ classize + tipuach + c_size  | f + tipuach + c_size , data = final5ek, clusters = final5ek$schlcode,se_type = "stata")
huxreg(iv1, iv2, iv3,
       error_format = "[{statistic}]", 
       note         = "{stars}. T statistics in brackets.")
## Warning in huxreg(iv1, iv2, iv3, error_format = "[{statistic}]", note = "{stars}. T statistics in brackets."): Unrecognized statistics: logLik, AIC
## Try setting `statistics` explicitly in the call to `huxreg()`
(1)(2)(3)
(Intercept)58.490 ***72.687 ***75.956 ***
[32.412]   [39.395]   [32.259]   
classize0.294 ***-0.013    -0.231 *  
[4.878]   [-0.226]   [-2.344]   
tipuach        -0.355 ***-0.350 ***
        [-17.905]   [-17.505]   
c_size                0.041 ***
                [3.512]   
N2018        2018        2018        
R20.048    0.245    0.234    
*** p < 0.001; ** p < 0.01; * p < 0.05. T statistics in brackets.

Süreksiz örneklem araç regresyonları

ivdis1 <- iv_robust(avgmath ~ classize  | f , data = final5ekdis, clusters = final5ekdis$schlcode,se_type = "stata")
ivdis2 <- iv_robust(avgmath ~ classize + tipuach  | f + tipuach , data = final5ekdis, clusters = final5ekdis$schlcode,se_type = "stata")
ivdis3 <- iv_robust(avgmath ~ classize + tipuach + c_size  | f + tipuach + c_size , data = final5ekdis, clusters = final5ekdis$schlcode,se_type = "stata")
huxreg(ivdis1, ivdis2, ivdis3,
       error_format = "[{statistic}]", 
       note         = "{stars}. T statistics in brackets.")
## Warning in huxreg(ivdis1, ivdis2, ivdis3, error_format = "[{statistic}]", : Unrecognized statistics: logLik, AIC
## Try setting `statistics` explicitly in the call to `huxreg()`
(1)(2)(3)
(Intercept)58.824 ***79.183 ***81.031 ***
[13.022]   [15.272]   [13.857]   
classize0.267    -0.189    -0.476    
[1.808]   [-1.225]   [-1.884]   
tipuach        -0.462 ***-0.437 ***
        [-8.911]   [-8.633]   
c_size                0.087 *  
                [2.299]   
N465        465        465        
R20.065    0.262    0.201    
*** p < 0.001; ** p < 0.01; * p < 0.05. T statistics in brackets.

Son olarak 3. modellerin hepsini bir tabloda gösterip karşılaştıralım.

huxreg(ols3, olsdis3, iv3, ivdis3,
       error_format = "[{statistic}]", 
       note         = "{stars}. T statistics in brackets.")
## Warning in huxreg(ols3, olsdis3, iv3, ivdis3, error_format = "[{statistic}]", : Unrecognized statistics: logLik, AIC
## Try setting `statistics` explicitly in the call to `huxreg()`
(1)(2)(3)(4)
(Intercept)70.085 ***69.039 ***75.956 ***81.031 ***
[59.937]   [27.546]   [32.259]   [13.857]   
classize0.019    0.060    -0.231 *  -0.476    
[0.440]   [0.740]   [-2.344]   [-1.884]   
tipuach-0.332 ***-0.390 ***-0.350 ***-0.437 ***
[-17.761]   [-9.334]   [-17.505]   [-8.633]   
c_size0.017 *  0.020    0.041 ***0.087 *  
[2.273]   [0.941]   [3.512]   [2.299]   
N2018        465        2018        465        
R20.251    0.300    0.234    0.201    
*** p < 0.001; ** p < 0.01; * p < 0.05. T statistics in brackets.

Angrist ve Lavy’nin bahsettiği “Mostly Harmless” kitabındaki 6.2.1 tablosunda, beşinci sınıf matematik puanları için tahminler kontrolsüz ve kontrollü durumda karşılaştırılmıştır. Kontrolsüz tahminlerde, sınıf mevcudu ile test puanları arasında güçlü bir pozitif ilişki olduğu görülmektedir.

Ancak, kontrol olarak dezavantajlı öğrencilerin yüzdesi dahil edildiğinde, pozitif ilişki anlamlılığını kaybetmektedir. Yani, daha büyük sınıflardaki öğrencilerin yüksek puanlarının, dezavantajlı öğrenci oranındaki farklılıklardan kaynaklanabileceği sonucuna varılmaktadır.

Ancak, 2SLS (iki aşamalı en küçük kareler) tahminleri, OLS (en küçük kareler) tahminlerinden farklı bir sonuç vermektedir. 2SLS tahminleri, daha küçük sınıfların test puanlarını artırdığını göstermektedir. Bu sonuç, Tennessee STAR randomize çalışmasının sonuçlarıyla uyumlu olduğunu ifade etmektedir.

Sonuç olarak, bahsedilen çalışmalardan elde edilen bulgular, sınıf mevcudunun öğrenci başarısı üzerindeki etkisinin karmaşık olduğunu göstermektedir. Daha küçük sınıfların avantajları ve dezavantajları dikkate alınmalı ve bu konuda daha fazla araştırma yapılması gerekmektedir.