knitr::opts_chunk$set(echo = TRUE)
rm(list=ls())
library(readxl)
library(readr)
library(dplyr)
library(ggplot2)
library(stringr)
library(corrplot)
library(car)
library(tidyr)
library(fixest)
library(tigris)
library(sf)
library(modelsummary)
library(tinytable)
library(knitr)
library(kableExtra)
library(webshot2)
census09 <- read_excel("elsec09.xls")
census10<- read_excel("elsec10.xls")
census11<- read_excel("elsec11.xls")
census12<- read_excel("elsec12.xls")
census13<- read_excel("elsec13.xls")
census14<- read_excel("elsec14.xls")
census15<- read_excel("elsec15.xls")
census16<- read_excel("elsec16.xls")
census17<- read_excel("elsec17.xls")
census18 <- read_excel("elsec18.xls")
census19<- read_excel("elsec19.xls")
seda <- read.csv("seda_admindist_annualsub_cs_6.0.csv")
seda_cov <- read.csv("seda_cov_admindist_annual_6.0.csv")
clean_census <- function(df) {
df <- df[, c("IDCENSUS", "NAME", "CONUM", "NCESID", "TOTALREV",
"YRDATA", "TFEDREV", "TSTREV", "TLOCREV", "TOTALEXP")]
colnames(df) <- tolower(colnames(df))
colnames(df) <- c("census_id", "district_name", "county_num", "nces_id",
"total_rev", "year", "fed_rev", "state_rev", "local_rev", "total_exp")
df
}
census09 <- clean_census(census09)
census10 <- clean_census(census10)
census11 <- clean_census(census11)
census12 <- clean_census(census12)
census13 <- clean_census(census13)
census14 <- clean_census(census14)
census15 <- clean_census(census15)
census16 <- clean_census(census16)
census17 <- clean_census(census17)
census18 <- clean_census(census18)
census19 <- clean_census(census19)
census <- rbind(census09, census10, census11, census12, census13, census14, census15, census16, census17, census18, census19)
census$census_id <- as.factor(census$census_id)
census$county_num <- as.factor(census$county_num)
census$nces_id <- as.factor(census$nces_id)
census$year <- as.numeric(census$year)
census$year <- census$year + 2000
census2 <- census %>%
mutate(nces_id = as.numeric(as.character(nces_id))) %>%
mutate(year = as.numeric(year)) %>%
rename("ID" = nces_id)
seda2 <- seda %>%
mutate(sedaadmin = as.numeric(sedaadmin)) %>%
mutate(year = as.numeric(year)) %>%
rename("ID" = sedaadmin)
seda_cov <- seda_cov %>%
mutate(sedaadmin = as.numeric(sedaadmin)) %>%
mutate(year = as.numeric(year)) %>%
rename("ID" = sedaadmin)
almost <- left_join(seda2, census2, by = c("ID", "year"))
data <- left_join(almost, seda_cov, by = c("ID", "year"))
ca <- data %>%
filter(fips.x==06) %>%
filter(subgroup == "all") %>%
mutate(state_funding_per_pupil = state_rev / totenrl) %>%
mutate(local_funding_per_pupil = local_rev / totenrl) %>%
mutate(fed_funding_per_pupil = fed_rev / totenrl)
blk_scores <- data %>%
filter(fips.x==06) %>%
filter(subgroup=="blk") %>%
select("ID", "year", "cs_mn_avg_mth_ol", "cs_mn_avg_rla_ol")
wht_scores <- data %>%
filter(fips.x==06) %>%
filter(subgroup=="wht") %>%
select("ID", "year", "cs_mn_avg_mth_ol", "cs_mn_avg_rla_ol")
hsp_scores <- data %>%
filter(fips.x==06) %>%
filter(subgroup=="hsp") %>%
select("ID", "year", "cs_mn_avg_mth_ol", "cs_mn_avg_rla_ol")
blk <- ca %>%
inner_join(
blk_scores,
by = c("ID", "year")
) %>%
rename(all_math = cs_mn_avg_mth_ol.x) %>%
rename(all_reading = cs_mn_avg_rla_ol.x)
blk <- blk %>%
rename(blk_math = cs_mn_avg_mth_ol.y) %>%
rename(blk_reading = cs_mn_avg_rla_ol.y) %>%
rename(stateabb = stateabb.x) %>%
mutate(post = as.integer(year>=2013))
wht <- ca %>%
inner_join(
wht_scores,
by = c("ID", "year")
) %>%
rename(all_math = cs_mn_avg_mth_ol.x) %>%
rename(all_reading = cs_mn_avg_rla_ol.x)
wht <- wht %>%
rename(wht_math = cs_mn_avg_mth_ol.y) %>%
rename(wht_reading = cs_mn_avg_rla_ol.y) %>%
rename(stateabb = stateabb.x) %>%
mutate(post = as.integer(year>=2013))
hsp <- ca %>%
inner_join(
hsp_scores,
by = c("ID", "year")
) %>%
rename(all_math = cs_mn_avg_mth_ol.x) %>%
rename(all_reading = cs_mn_avg_rla_ol.x)
hsp <- hsp %>%
rename(hsp_math = cs_mn_avg_mth_ol.y) %>%
rename(hsp_reading = cs_mn_avg_rla_ol.y) %>%
rename(stateabb = stateabb.x) %>%
mutate(post = as.integer(year>=2013))
baseline <- ca %>%
filter(year==2012) %>%
mutate(treat = as.integer(perfrl>0.55)) %>%
select(ID, treat, perfrl, perell, local_funding_per_pupil) %>%
rename(perfrl_2012 = perfrl) %>%
rename(perell_2012 = perell) %>%
rename(lfpp_2012 = local_funding_per_pupil)
blk <- blk %>%
left_join(baseline, by = "ID")
wht <- wht %>%
left_join(baseline, by = "ID")
hsp <- hsp %>%
left_join(baseline, by = "ID")
x <- blk %>%
inner_join(wht, by = c("ID", "year")) %>%
select(-contains(".y"))
x <- x %>%
inner_join(hsp, by = c("ID", "year")) %>%
select(-contains(".x")) %>%
select(!subgroup)
x <- x %>%
mutate(concentration_eligible = as.integer(perfrl_2012 > 0.55))
x <- x %>%
rename("Federal Funding Per Pupil" = fed_funding_per_pupil, "State Funding Per Pupil" = state_funding_per_pupil, "Local Funding Per Pupil" = local_funding_per_pupil, "Percent Native American" = pernam, "Percent Asian" = perasn, "Percent Hispanic" = perhsp, "Percent Black" = perblk, "Percent White" = perwht, "Year" = year, "Highest Grade" = gshi, "Lowest Grade" = gslo, "Urbanicity" = urbanicity, "Percent Free or Reduced Price Lunch" = perfrl, "Percent Free or Reduced Price Lunch 2012" = perfrl_2012, "Eligible" = concentration_eligible)
models_ols <- list(
All = lm(all_math~`Eligible`+`Federal Funding Per Pupil`+`Local Funding Per Pupil`+`State Funding Per Pupil`+`Percent Native American`+`Percent Asian`+`Percent Hispanic`+`Percent Black`+`Percent White`+`Urbanicity`+`Percent Free or Reduced Price Lunch`, data = x, weights = totenrl),
Black = lm(blk_math~`Eligible`+`Federal Funding Per Pupil`+`Local Funding Per Pupil`+`State Funding Per Pupil`+`Percent Native American`+`Percent Asian`+`Percent Hispanic`+`Percent Black`+`Percent White`+`Urbanicity`+`Percent Free or Reduced Price Lunch`, data = x, weights = totenrl),
White = lm(wht_math~`Eligible`+`Federal Funding Per Pupil`+`Local Funding Per Pupil`+`State Funding Per Pupil`+`Percent Native American`+`Percent Asian`+`Percent Hispanic`+`Percent Black`+`Percent White`+`Urbanicity`+`Percent Free or Reduced Price Lunch`, data = x, weights = totenrl),
Hispanic = lm(hsp_math~`Eligible`+`Federal Funding Per Pupil`+`Local Funding Per Pupil`+`State Funding Per Pupil`+`Percent Native American`+`Percent Asian`+`Percent Hispanic`+`Percent Black`+`Percent White`+`Urbanicity`+`Percent Free or Reduced Price Lunch`, data = x, weights = totenrl),
All = lm(all_reading~`Eligible`+`Federal Funding Per Pupil`+`Local Funding Per Pupil`+`State Funding Per Pupil`+`Percent Native American`+`Percent Asian`+`Percent Hispanic`+`Percent Black`+`Percent White`+`Urbanicity`+`Percent Free or Reduced Price Lunch`, data = x, weights = totenrl),
Black = lm(blk_reading~`Eligible`+`Federal Funding Per Pupil`+`Local Funding Per Pupil`+`State Funding Per Pupil`+`Percent Native American`+`Percent Asian`+`Percent Hispanic`+`Percent Black`+`Percent White`+`Urbanicity`+`Percent Free or Reduced Price Lunch`, data = x, weights = totenrl),
White = lm(wht_reading~`Eligible`+`Federal Funding Per Pupil`+`Local Funding Per Pupil`+`State Funding Per Pupil`+`Percent Native American`+`Percent Asian`+`Percent Hispanic`+`Percent Black`+`Percent White`+`Urbanicity`+`Percent Free or Reduced Price Lunch`, data = x, weights = totenrl),
Hispanic = lm(hsp_reading~`Eligible`+`Federal Funding Per Pupil`+`Local Funding Per Pupil`+`State Funding Per Pupil`+`Percent Native American`+`Percent Asian`+`Percent Hispanic`+`Percent Black`+`Percent White`+`Urbanicity`+`Percent Free or Reduced Price Lunch`, data = x, weights = totenrl)
)
modelsummary(models_ols) %>%
group_tt(j = list(Math = 2:5, Reading = 6:9))
| |
Math |
Reading |
| |
All |
Black |
White |
Hispanic |
All |
Black |
White |
Hispanic |
| (Intercept) |
0.261 |
-0.212 |
0.457 |
0.243 |
0.319 |
-0.089 |
0.528 |
0.259 |
|
(0.091) |
(0.124) |
(0.117) |
(0.098) |
(0.082) |
(0.112) |
(0.114) |
(0.093) |
| Eligible |
-0.002 |
-0.055 |
0.067 |
0.026 |
-0.021 |
-0.057 |
0.078 |
0.014 |
|
(0.012) |
(0.017) |
(0.016) |
(0.013) |
(0.011) |
(0.015) |
(0.016) |
(0.013) |
| Federal Funding Per Pupil |
-0.000 |
0.012 |
0.027 |
-0.007 |
-0.035 |
0.003 |
0.020 |
-0.050 |
|
(0.003) |
(0.004) |
(0.004) |
(0.003) |
(0.003) |
(0.004) |
(0.004) |
(0.003) |
| Local Funding Per Pupil |
0.003 |
-0.003 |
0.016 |
-0.005 |
0.007 |
-0.002 |
0.018 |
-0.000 |
|
(0.001) |
(0.001) |
(0.001) |
(0.001) |
(0.001) |
(0.001) |
(0.001) |
(0.001) |
| State Funding Per Pupil |
-0.000 |
-0.007 |
0.001 |
0.003 |
0.009 |
-0.003 |
0.003 |
0.014 |
|
(0.001) |
(0.001) |
(0.001) |
(0.001) |
(0.001) |
(0.001) |
(0.001) |
(0.001) |
| Percent Native American |
-4.038 |
-3.101 |
-7.808 |
-2.261 |
-4.158 |
-3.767 |
-8.088 |
-2.320 |
|
(0.604) |
(0.868) |
(0.789) |
(0.664) |
(0.548) |
(0.743) |
(0.756) |
(0.615) |
| Percent Asian |
0.995 |
0.238 |
0.072 |
-0.303 |
0.620 |
0.197 |
0.031 |
-0.354 |
|
(0.097) |
(0.132) |
(0.124) |
(0.104) |
(0.088) |
(0.119) |
(0.121) |
(0.098) |
| Percent Hispanic |
-0.004 |
0.413 |
0.194 |
-0.140 |
-0.091 |
0.488 |
0.229 |
-0.205 |
|
(0.090) |
(0.124) |
(0.116) |
(0.098) |
(0.082) |
(0.111) |
(0.113) |
(0.092) |
| Percent Black |
-0.888 |
-1.155 |
0.204 |
-0.557 |
-0.866 |
-1.318 |
0.195 |
-0.653 |
|
(0.118) |
(0.162) |
(0.152) |
(0.128) |
(0.107) |
(0.146) |
(0.148) |
(0.121) |
| Percent White |
0.126 |
0.182 |
-0.018 |
-0.299 |
0.127 |
0.232 |
0.026 |
-0.309 |
|
(0.097) |
(0.132) |
(0.124) |
(0.105) |
(0.088) |
(0.119) |
(0.121) |
(0.098) |
| UrbanicityRural |
-0.028 |
-0.079 |
-0.265 |
0.004 |
-0.070 |
-0.074 |
-0.304 |
-0.022 |
|
(0.031) |
(0.047) |
(0.040) |
(0.034) |
(0.028) |
(0.038) |
(0.039) |
(0.032) |
| UrbanicitySuburb |
0.016 |
0.059 |
-0.127 |
0.038 |
0.031 |
0.074 |
-0.131 |
0.053 |
|
(0.007) |
(0.009) |
(0.009) |
(0.007) |
(0.006) |
(0.008) |
(0.008) |
(0.007) |
| UrbanicityTown |
-0.025 |
0.033 |
-0.152 |
-0.005 |
-0.019 |
-0.001 |
-0.149 |
0.011 |
|
(0.020) |
(0.029) |
(0.026) |
(0.022) |
(0.018) |
(0.025) |
(0.025) |
(0.021) |
| Percent Free or Reduced Price Lunch |
-0.956 |
-0.801 |
-1.079 |
-0.829 |
-0.956 |
-0.901 |
-1.140 |
-0.860 |
|
(0.039) |
(0.053) |
(0.050) |
(0.042) |
(0.035) |
(0.047) |
(0.048) |
(0.039) |
| Num.Obs. |
2688 |
2565 |
2656 |
2661 |
2688 |
2675 |
2687 |
2685 |
| R2 |
0.838 |
0.549 |
0.603 |
0.451 |
0.865 |
0.630 |
0.634 |
0.605 |
| R2 Adj. |
0.837 |
0.546 |
0.601 |
0.448 |
0.865 |
0.629 |
0.633 |
0.603 |
| AIC |
-1142.5 |
392.6 |
165.7 |
-755.3 |
-1661.6 |
-35.7 |
63.6 |
-1043.3 |
| BIC |
-1054.1 |
480.3 |
254.0 |
-667.0 |
-1573.2 |
52.7 |
152.1 |
-954.9 |
| Log.Lik. |
586.249 |
-181.297 |
-67.874 |
392.671 |
845.813 |
32.834 |
-16.821 |
536.663 |
| RMSE |
0.19 |
0.25 |
0.31 |
0.19 |
0.17 |
0.23 |
0.29 |
0.19 |
models_feols <- list(
All = feols(all_math~`Eligible`+`Federal Funding Per Pupil`+`Local Funding Per Pupil`+`State Funding Per Pupil`+`Percent Native American`+`Percent Asian`+`Percent Hispanic`+`Percent Black`+`Percent White`+`Urbanicity`+`Percent Free or Reduced Price Lunch`, data = x, weights = ~totenrl, cluster = ~ID),
Black = feols(blk_math~`Eligible`+`Federal Funding Per Pupil`+`Local Funding Per Pupil`+`State Funding Per Pupil`+`Percent Native American`+`Percent Asian`+`Percent Hispanic`+`Percent Black`+`Percent White`+`Urbanicity`+`Percent Free or Reduced Price Lunch`, data = x, weights = ~totenrl, cluster = ~ID),
White = feols(wht_math~`Eligible`+`Federal Funding Per Pupil`+`Local Funding Per Pupil`+`State Funding Per Pupil`+`Percent Native American`+`Percent Asian`+`Percent Hispanic`+`Percent Black`+`Percent White`+`Urbanicity`+`Percent Free or Reduced Price Lunch`, data = x, weights = ~totenrl, cluster = ~ID),
Hispanic = feols(hsp_math~`Eligible`+`Federal Funding Per Pupil`+`Local Funding Per Pupil`+`State Funding Per Pupil`+`Percent Native American`+`Percent Asian`+`Percent Hispanic`+`Percent Black`+`Percent White`+`Urbanicity`+`Percent Free or Reduced Price Lunch`, data = x, weights = ~totenrl, cluster = ~ID),
All = feols(all_reading~`Eligible`+`Federal Funding Per Pupil`+`Local Funding Per Pupil`+`State Funding Per Pupil`+`Percent Native American`+`Percent Asian`+`Percent Hispanic`+`Percent Black`+`Percent White`+`Urbanicity`+`Percent Free or Reduced Price Lunch`, data = x, weights = ~totenrl, cluster = ~ID),
Black = feols(blk_reading~`Eligible`+`Federal Funding Per Pupil`+`Local Funding Per Pupil`+`State Funding Per Pupil`+`Percent Native American`+`Percent Asian`+`Percent Hispanic`+`Percent Black`+`Percent White`+`Urbanicity`+`Percent Free or Reduced Price Lunch`, data = x, weights = ~totenrl, cluster = ~ID),
White = feols(wht_reading~`Eligible`+`Federal Funding Per Pupil`+`Local Funding Per Pupil`+`State Funding Per Pupil`+`Percent Native American`+`Percent Asian`+`Percent Hispanic`+`Percent Black`+`Percent White`+`Urbanicity`+`Percent Free or Reduced Price Lunch`, data = x, weights = ~totenrl, cluster = ~ID),
Hispanic = feols(hsp_reading~`Eligible`+`Federal Funding Per Pupil`+`Local Funding Per Pupil`+`State Funding Per Pupil`+`Percent Native American`+`Percent Asian`+`Percent Hispanic`+`Percent Black`+`Percent White`+`Urbanicity`+`Percent Free or Reduced Price Lunch`, data = x, weights = ~totenrl, cluster = ~ID)
)
modelsummary(models_feols) %>%
group_tt(j = list(Math = 2:5, Reading = 6:9))
| |
Math |
Reading |
| |
All |
Black |
White |
Hispanic |
All |
Black |
White |
Hispanic |
| (Intercept) |
0.261 |
-0.212 |
0.457 |
0.243 |
0.319 |
-0.089 |
0.528 |
0.259 |
|
(0.164) |
(0.246) |
(0.267) |
(0.213) |
(0.161) |
(0.220) |
(0.260) |
(0.222) |
| Eligible |
-0.002 |
-0.055 |
0.067 |
0.026 |
-0.021 |
-0.057 |
0.078 |
0.014 |
|
(0.036) |
(0.053) |
(0.042) |
(0.040) |
(0.039) |
(0.051) |
(0.042) |
(0.043) |
| Federal Funding Per Pupil |
-0.000 |
0.012 |
0.027 |
-0.007 |
-0.035 |
0.003 |
0.020 |
-0.050 |
|
(0.007) |
(0.011) |
(0.014) |
(0.007) |
(0.009) |
(0.009) |
(0.013) |
(0.011) |
| Local Funding Per Pupil |
0.003 |
-0.003 |
0.016 |
-0.005 |
0.007 |
-0.002 |
0.018 |
-0.000 |
|
(0.002) |
(0.002) |
(0.002) |
(0.002) |
(0.002) |
(0.002) |
(0.002) |
(0.002) |
| State Funding Per Pupil |
-0.000 |
-0.007 |
0.001 |
0.003 |
0.009 |
-0.003 |
0.003 |
0.014 |
|
(0.001) |
(0.002) |
(0.003) |
(0.002) |
(0.001) |
(0.002) |
(0.003) |
(0.002) |
| Percent Native American |
-4.038 |
-3.101 |
-7.808 |
-2.261 |
-4.158 |
-3.767 |
-8.088 |
-2.320 |
|
(1.577) |
(1.927) |
(2.634) |
(1.426) |
(1.864) |
(2.008) |
(3.044) |
(1.715) |
| Percent Asian |
0.995 |
0.238 |
0.072 |
-0.303 |
0.620 |
0.197 |
0.031 |
-0.354 |
|
(0.200) |
(0.274) |
(0.267) |
(0.246) |
(0.182) |
(0.245) |
(0.249) |
(0.243) |
| Percent Hispanic |
-0.004 |
0.413 |
0.194 |
-0.140 |
-0.091 |
0.488 |
0.229 |
-0.205 |
|
(0.174) |
(0.263) |
(0.266) |
(0.207) |
(0.192) |
(0.227) |
(0.262) |
(0.233) |
| Percent Black |
-0.888 |
-1.155 |
0.204 |
-0.557 |
-0.866 |
-1.318 |
0.195 |
-0.653 |
|
(0.236) |
(0.368) |
(0.385) |
(0.279) |
(0.245) |
(0.336) |
(0.426) |
(0.303) |
| Percent White |
0.126 |
0.182 |
-0.018 |
-0.299 |
0.127 |
0.232 |
0.026 |
-0.309 |
|
(0.174) |
(0.268) |
(0.281) |
(0.231) |
(0.176) |
(0.242) |
(0.267) |
(0.247) |
| UrbanicityRural |
-0.028 |
-0.079 |
-0.265 |
0.004 |
-0.070 |
-0.074 |
-0.304 |
-0.022 |
|
(0.036) |
(0.045) |
(0.060) |
(0.028) |
(0.038) |
(0.045) |
(0.051) |
(0.032) |
| UrbanicitySuburb |
0.016 |
0.059 |
-0.127 |
0.038 |
0.031 |
0.074 |
-0.131 |
0.053 |
|
(0.019) |
(0.029) |
(0.031) |
(0.021) |
(0.019) |
(0.028) |
(0.030) |
(0.023) |
| UrbanicityTown |
-0.025 |
0.033 |
-0.152 |
-0.005 |
-0.019 |
-0.001 |
-0.149 |
0.011 |
|
(0.041) |
(0.071) |
(0.065) |
(0.044) |
(0.034) |
(0.048) |
(0.056) |
(0.038) |
| Percent Free or Reduced Price Lunch |
-0.956 |
-0.801 |
-1.079 |
-0.829 |
-0.956 |
-0.901 |
-1.140 |
-0.860 |
|
(0.116) |
(0.203) |
(0.100) |
(0.125) |
(0.157) |
(0.194) |
(0.103) |
(0.169) |
| Num.Obs. |
2688 |
2565 |
2656 |
2661 |
2688 |
2675 |
2687 |
2685 |
| R2 |
0.838 |
0.549 |
0.603 |
0.451 |
0.865 |
0.630 |
0.634 |
0.605 |
| R2 Adj. |
0.837 |
0.546 |
0.601 |
0.448 |
0.865 |
0.629 |
0.633 |
0.603 |
| AIC |
-1339.8 |
198.8 |
1378.6 |
-1141.9 |
-1870.3 |
-241.1 |
1067.2 |
-1220.6 |
| BIC |
-1257.2 |
280.7 |
1461.0 |
-1059.5 |
-1787.8 |
-158.6 |
1149.7 |
-1138.1 |
| RMSE |
0.19 |
0.25 |
0.31 |
0.19 |
0.17 |
0.23 |
0.29 |
0.19 |
models_did <- list(
All = feols(all_math~`Eligible`:post+`Federal Funding Per Pupil`+`Local Funding Per Pupil`+`State Funding Per Pupil`+`Percent Native American`+`Percent Asian`+`Percent Hispanic`+`Percent Black`+`Percent White`+`Percent Free or Reduced Price Lunch`| ID + `Year`, data = x, weights = ~totenrl, cluster = ~ID),
Black = feols(blk_math~`Eligible`:post+`Federal Funding Per Pupil`+`Local Funding Per Pupil`+`State Funding Per Pupil`+`Percent Native American`+`Percent Asian`+`Percent Hispanic`+`Percent Black`+`Percent White`+`Percent Free or Reduced Price Lunch`| ID + `Year`, data = x, weights = ~totenrl, cluster = ~ID),
White = feols(wht_math~`Eligible`:post+`Federal Funding Per Pupil`+`Local Funding Per Pupil`+`State Funding Per Pupil`+`Percent Native American`+`Percent Asian`+`Percent Hispanic`+`Percent Black`+`Percent White`+`Percent Free or Reduced Price Lunch`| ID + `Year`, data = x, weights = ~totenrl, cluster = ~ID),
Hispanic = feols(hsp_math~`Eligible`:post+`Federal Funding Per Pupil`+`Local Funding Per Pupil`+`State Funding Per Pupil`+`Percent Native American`+`Percent Asian`+`Percent Hispanic`+`Percent Black`+`Percent White`+`Percent Free or Reduced Price Lunch`| ID + `Year`, data = x, weights = ~totenrl, cluster = ~ID),
All = feols(all_reading~`Eligible`:post+`Federal Funding Per Pupil`+`Local Funding Per Pupil`+`State Funding Per Pupil`+`Percent Native American`+`Percent Asian`+`Percent Hispanic`+`Percent Black`+`Percent White`+`Percent Free or Reduced Price Lunch`| ID + `Year`, data = x, weights = ~totenrl, cluster = ~ID),
Black = feols(blk_reading~`Eligible`:post+`Federal Funding Per Pupil`+`Local Funding Per Pupil`+`State Funding Per Pupil`+`Percent Native American`+`Percent Asian`+`Percent Hispanic`+`Percent Black`+`Percent White`+`Percent Free or Reduced Price Lunch`| ID + `Year`, data = x, weights = ~totenrl, cluster = ~ID),
White = feols(wht_reading~`Eligible`:post+`Federal Funding Per Pupil`+`Local Funding Per Pupil`+`Percent Native American`+`Percent Asian`+`Percent Hispanic`+`Percent Black`+`Percent White`+`Percent Free or Reduced Price Lunch`| ID + `Year`, data = x, weights = ~totenrl, cluster = ~ID),
Hispanic = feols(hsp_reading~`Eligible`:post+`Federal Funding Per Pupil`+`Local Funding Per Pupil`+`Percent Native American`+`Percent Asian`+`Percent Hispanic`+`Percent Black`+`Percent White`+`Percent Free or Reduced Price Lunch`| ID + `Year`, data = x, weights = ~totenrl, cluster = ~ID)
)
modelsummary(models_did) %>%
group_tt(j = list(Math = 2:5, Reading = 6:9))
| |
Math |
Reading |
| |
All |
Black |
White |
Hispanic |
All |
Black |
White |
Hispanic |
| Federal Funding Per Pupil |
0.020 |
0.016 |
0.011 |
0.021 |
0.006 |
0.003 |
0.001 |
0.003 |
|
(0.006) |
(0.006) |
(0.007) |
(0.005) |
(0.004) |
(0.006) |
(0.002) |
(0.003) |
| Local Funding Per Pupil |
0.008 |
0.009 |
0.009 |
0.005 |
-0.001 |
-0.002 |
-0.001 |
-0.002 |
|
(0.002) |
(0.003) |
(0.003) |
(0.002) |
(0.002) |
(0.002) |
(0.002) |
(0.002) |
| State Funding Per Pupil |
-0.008 |
-0.008 |
-0.006 |
-0.007 |
-0.002 |
-0.002 |
|
|
|
(0.001) |
(0.002) |
(0.002) |
(0.001) |
(0.001) |
(0.001) |
|
|
| Percent Native American |
0.386 |
2.170 |
0.098 |
1.098 |
1.825 |
2.734 |
0.736 |
2.162 |
|
(2.072) |
(2.279) |
(1.987) |
(2.144) |
(1.892) |
(2.134) |
(1.894) |
(1.627) |
| Percent Asian |
1.111 |
0.944 |
0.205 |
0.453 |
0.390 |
0.324 |
-0.098 |
-0.031 |
|
(0.265) |
(0.447) |
(0.275) |
(0.313) |
(0.224) |
(0.314) |
(0.239) |
(0.224) |
| Percent Hispanic |
-0.485 |
-0.492 |
-0.298 |
-0.140 |
-0.517 |
-0.204 |
-0.238 |
-0.119 |
|
(0.153) |
(0.206) |
(0.156) |
(0.143) |
(0.148) |
(0.134) |
(0.128) |
(0.127) |
| Percent Black |
-0.319 |
0.683 |
-0.019 |
0.401 |
-0.153 |
1.072 |
0.709 |
0.159 |
|
(0.641) |
(0.663) |
(0.601) |
(0.659) |
(0.645) |
(0.571) |
(0.807) |
(0.606) |
| Percent White |
-0.042 |
0.196 |
-0.093 |
-0.213 |
0.279 |
0.169 |
0.080 |
0.060 |
|
(0.099) |
(0.148) |
(0.096) |
(0.116) |
(0.118) |
(0.103) |
(0.077) |
(0.096) |
| Percent Free or Reduced Price Lunch |
-0.250 |
-0.137 |
-0.210 |
-0.189 |
-0.212 |
-0.243 |
-0.257 |
-0.176 |
|
(0.053) |
(0.081) |
(0.070) |
(0.057) |
(0.041) |
(0.055) |
(0.053) |
(0.043) |
| Eligible × post |
-0.114 |
-0.113 |
-0.096 |
-0.111 |
-0.016 |
-0.054 |
-0.035 |
-0.032 |
|
(0.016) |
(0.024) |
(0.016) |
(0.017) |
(0.012) |
(0.016) |
(0.012) |
(0.011) |
| Num.Obs. |
2671 |
2548 |
2639 |
2644 |
2671 |
2656 |
2670 |
2668 |
| R2 |
0.962 |
0.859 |
0.923 |
0.878 |
0.978 |
0.908 |
0.953 |
0.946 |
| R2 Adj. |
0.956 |
0.837 |
0.912 |
0.860 |
0.975 |
0.894 |
0.946 |
0.938 |
| R2 Within |
0.263 |
0.127 |
0.138 |
0.191 |
0.105 |
0.048 |
0.043 |
0.033 |
| R2 Within Adj. |
0.260 |
0.123 |
0.134 |
0.188 |
0.101 |
0.043 |
0.039 |
0.030 |
| AIC |
-4586.7 |
-1896.6 |
-3763.2 |
-4307.3 |
-6319.7 |
-2932.6 |
-5016.2 |
-6006.0 |
| BIC |
-2525.2 |
119.3 |
-1705.8 |
-2249.3 |
-4258.1 |
-890.6 |
-2960.6 |
-3950.7 |
| RMSE |
0.09 |
0.15 |
0.10 |
0.09 |
0.07 |
0.12 |
0.08 |
0.07 |
| FE: ID |
X |
X |
X |
X |
X |
X |
X |
X |
| FE: Year |
X |
X |
X |
X |
X |
X |
X |
X |
stage1 <- feols(`State Funding Per Pupil`~`Eligible`:post +`Percent White`+`Percent Black`+`Percent Hispanic`+`Local Funding Per Pupil` | ID + `Year`, data = x, weights = ~totenrl, cluster = ~ID)
modelsummary(stage1)
| |
(1) |
| Percent White |
-0.962 |
|
(3.750) |
| Percent Black |
-0.843 |
|
(12.971) |
| Percent Hispanic |
0.869 |
|
(3.224) |
| Local Funding Per Pupil |
0.107 |
|
(0.329) |
| Eligible × post |
2.502 |
|
(0.396) |
| Num.Obs. |
2671 |
| R2 |
0.853 |
| R2 Adj. |
0.832 |
| R2 Within |
0.047 |
| R2 Within Adj. |
0.045 |
| AIC |
22616.3 |
| BIC |
24648.4 |
| RMSE |
14.67 |
| FE: ID |
X |
| FE: Year |
X |
all_model_iv <- list(
All = feols(all_math~`Percent White`+`Percent Black`+`Percent Hispanic`+`Local Funding Per Pupil`+`Percent Free or Reduced Price Lunch`|ID +`Year`|`State Funding Per Pupil`~`Eligible`:post, data = x, weights = ~totenrl, cluster = ~ID),
All = feols(all_reading~`Percent White`+`Percent Black`+`Percent Hispanic`+`Local Funding Per Pupil`+`Percent Free or Reduced Price Lunch`|ID+`Year`|`State Funding Per Pupil`~`Eligible`:post, data = x, weights = ~totenrl, cluster = ~ID)
)
modelsummary(all_model_iv) %>%
group_tt(j = list(Math = 2, Reading = 3))
| |
Math |
Reading |
| |
All |
All |
| fit_State Funding Per Pupil |
-0.059 |
-0.010 |
|
(0.010) |
(0.005) |
| Percent White |
-0.212 |
0.239 |
|
(0.235) |
(0.113) |
| Percent Black |
-0.225 |
-0.081 |
|
(1.094) |
(0.672) |
| Percent Hispanic |
-0.702 |
-0.598 |
|
(0.247) |
(0.149) |
| Local Funding Per Pupil |
0.017 |
0.001 |
|
(0.018) |
(0.003) |
| Percent Free or Reduced Price Lunch |
0.065 |
-0.164 |
|
(0.095) |
(0.057) |
| Num.Obs. |
2671 |
2671 |
| R2 |
1.000 |
1.000 |
| R2 Adj. |
1.000 |
1.000 |
| R2 Within |
1.000 |
1.000 |
| R2 Within Adj. |
1.000 |
1.000 |
| AIC |
7270.8 |
-1966.9 |
| BIC |
9308.8 |
71.1 |
| RMSE |
0.83 |
0.15 |
| FE: ID |
X |
X |
| FE: Year |
X |
X |
models_iv <- list(
Black = feols(blk_math~`Percent White`+`Percent Black`+`Percent Hispanic`+`Percent Free or Reduced Price Lunch`|ID+`Year`|`State Funding Per Pupil`~`Eligible`:post, data = x, weights = ~totenrl, cluster = ~ID),
White = feols(wht_math~`Percent White`+`Percent Black`+`Percent Hispanic`+`Percent Free or Reduced Price Lunch`|ID+`Year`|`State Funding Per Pupil`~`Eligible`:post, data = x, weights = ~totenrl, cluster = ~ID),
Hispanic = feols(hsp_math~`Percent White`+`Percent Black`+`Percent Hispanic`+`Percent Free or Reduced Price Lunch`|ID+`Year`|`State Funding Per Pupil`~`Eligible`:post, data = x, weights = ~totenrl, cluster = ~ID),
Black = feols(blk_reading~`Percent White`+`Percent Black`+`Percent Hispanic`+`Percent Free or Reduced Price Lunch`|ID+`Year`|`State Funding Per Pupil`~`Eligible`:post, data = x, weights = ~totenrl, cluster = ~ID),
White = feols(wht_reading~`Percent White`+`Percent Black`+`Percent Hispanic`+`Percent Free or Reduced Price Lunch`|ID+`Year`|`State Funding Per Pupil`~`Eligible`:post, data = x, weights = ~totenrl, cluster = ~ID),
Hispanic = feols(hsp_reading~`Percent White`+`Percent Black`+`Percent Hispanic`+`Percent Free or Reduced Price Lunch`|ID+`Year`|`State Funding Per Pupil`~`Eligible`:post, data = x, weights = ~totenrl, cluster = ~ID)
)
modelsummary(models_iv) %>%
group_tt(j = list(Math = 2:4, Reading = 5:7))
| |
Math |
Reading |
| |
Black |
White |
Hispanic |
Black |
White |
Hispanic |
| fit_State Funding Per Pupil |
-0.065 |
-0.053 |
-0.059 |
-0.026 |
-0.014 |
-0.013 |
|
(0.011) |
(0.008) |
(0.008) |
(0.007) |
(0.005) |
(0.005) |
| Percent White |
0.114 |
-0.105 |
-0.267 |
0.139 |
0.086 |
0.059 |
|
(0.301) |
(0.231) |
(0.230) |
(0.128) |
(0.095) |
(0.098) |
| Percent Black |
0.596 |
-0.218 |
0.307 |
1.015 |
0.641 |
0.145 |
|
(0.966) |
(0.837) |
(0.948) |
(0.657) |
(0.866) |
(0.650) |
| Percent Hispanic |
-1.001 |
-0.636 |
-0.490 |
-0.335 |
-0.266 |
-0.149 |
|
(0.555) |
(0.440) |
(0.485) |
(0.239) |
(0.167) |
(0.158) |
| Percent Free or Reduced Price Lunch |
0.142 |
0.009 |
0.082 |
-0.107 |
-0.175 |
-0.095 |
|
(0.140) |
(0.120) |
(0.108) |
(0.074) |
(0.060) |
(0.057) |
| Num.Obs. |
2548 |
2639 |
2644 |
2656 |
2670 |
2668 |
| R2 |
1.000 |
1.000 |
1.000 |
1.000 |
1.000 |
1.000 |
| R2 Adj. |
1.000 |
1.000 |
1.000 |
1.000 |
1.000 |
1.000 |
| R2 Within |
1.000 |
1.000 |
1.000 |
1.000 |
1.000 |
1.000 |
| R2 Within Adj. |
1.000 |
1.000 |
1.000 |
1.000 |
1.000 |
1.000 |
| AIC |
7878.9 |
6851.7 |
7553.5 |
3313.6 |
273.3 |
-482.2 |
| BIC |
9865.6 |
8879.7 |
9582.1 |
5326.2 |
2305.3 |
1549.5 |
| RMSE |
0.99 |
0.78 |
0.89 |
0.40 |
0.22 |
0.19 |
| FE: ID |
X |
X |
X |
X |
X |
X |
| FE: Year |
X |
X |
X |
X |
X |
X |
AMIV = feols(all_math~`Percent White`+`Percent Black`+`Percent Hispanic`+`Percent Free or Reduced Price Lunch`|ID +`Year`|`State Funding Per Pupil`~`Eligible`:post, data = x, weights = ~totenrl, cluster = ~ID)
BMIV = feols(blk_math~`Percent White`+`Percent Black`+`Percent Hispanic`+`Percent Free or Reduced Price Lunch`|ID+`Year`|`State Funding Per Pupil`~`Eligible`:post, data = x, weights = ~totenrl, cluster = ~ID)
WMIV = feols(wht_math~`Percent White`+`Percent Black`+`Percent Hispanic`+`Percent Free or Reduced Price Lunch`|ID+`Year`|`State Funding Per Pupil`~`Eligible`:post, data = x, weights = ~totenrl, cluster = ~ID)
HMIV = feols(hsp_math~`Percent White`+`Percent Black`+`Percent Hispanic`+`Percent Free or Reduced Price Lunch`|ID+`Year`|`State Funding Per Pupil`~`Eligible`:post, data = x, weights = ~totenrl, cluster = ~ID)
ARIV = feols(all_reading~`Percent White`+`Percent Black`+`Percent Hispanic`+`Percent Free or Reduced Price Lunch`|ID+`Year`|`State Funding Per Pupil`~`Eligible`:post, data = x, weights = ~totenrl, cluster = ~ID)
BRIV = feols(blk_reading~`Percent White`+`Percent Black`+`Percent Hispanic`+`Percent Free or Reduced Price Lunch`|ID+`Year`|`State Funding Per Pupil`~`Eligible`:post, data = x, weights = ~totenrl, cluster = ~ID)
WRIV = feols(wht_reading~`Percent White`+`Percent Black`+`Percent Hispanic`+`Percent Free or Reduced Price Lunch`|ID+`Year`|`State Funding Per Pupil`~`Eligible`:post, data = x, weights = ~totenrl, cluster = ~ID)
HRIV = feols(hsp_reading~`Percent White`+`Percent Black`+`Percent Hispanic`+`Percent Free or Reduced Price Lunch`|ID+`Year`|`State Funding Per Pupil`~`Eligible`:post, data = x, weights = ~totenrl, cluster = ~ID)
f_stats <- list(fitstat(AMIV, ~ ivf), fitstat(BMIV, ~ ivf), fitstat(WMIV, ~ ivf), fitstat(HMIV, ~ ivf), fitstat(ARIV, ~ ivf), fitstat(BRIV, ~ ivf), fitstat(WRIV, ~ ivf), fitstat(HRIV, ~ ivf))
f_stats
## [[1]]
## F-test (1st stage), `State Funding Per Pupil`: stat = 103.03, p < 2.2e-16, on 1 and 2,656 DoF.
##
## [[2]]
## F-test (1st stage), `State Funding Per Pupil`: stat = 95.628, p < 2.2e-16, on 1 and 2,533 DoF.
##
## [[3]]
## F-test (1st stage), `State Funding Per Pupil`: stat = 100.29, p < 2.2e-16, on 1 and 2,624 DoF.
##
## [[4]]
## F-test (1st stage), `State Funding Per Pupil`: stat = 100.52, p < 2.2e-16, on 1 and 2,629 DoF.
##
## [[5]]
## F-test (1st stage), `State Funding Per Pupil`: stat = 103.03, p < 2.2e-16, on 1 and 2,656 DoF.
##
## [[6]]
## F-test (1st stage), `State Funding Per Pupil`: stat = 101.80, p < 2.2e-16, on 1 and 2,641 DoF.
##
## [[7]]
## F-test (1st stage), `State Funding Per Pupil`: stat = 103.08, p < 2.2e-16, on 1 and 2,655 DoF.
##
## [[8]]
## F-test (1st stage), `State Funding Per Pupil`: stat = 103.44, p < 2.2e-16, on 1 and 2,653 DoF.
wu_hausmans <- list(fitstat(AMIV, "wh"), fitstat(BMIV, "wh"), fitstat(WMIV, "wh"), fitstat(HMIV, "wh"), fitstat(ARIV, "wh"), fitstat(BRIV, "wh"), fitstat(WRIV, "wh"), fitstat(HRIV, "wh"))
wu_hausmans
## [[1]]
## Wu-Hausman: stat = 343.84, p < 2.2e-16, on 1 and 2,325 DoF.
##
## [[2]]
## Wu-Hausman: stat = 133.61, p < 2.2e-16, on 1 and 2,207 DoF.
##
## [[3]]
## Wu-Hausman: stat = 160.04, p < 2.2e-16, on 1 and 2,293 DoF.
##
## [[4]]
## Wu-Hausman: stat = 258.04, p < 2.2e-16, on 1 and 2,298 DoF.
##
## [[5]]
## Wu-Hausman: stat = 13.932, p = 1.941e-4, on 1 and 2,325 DoF.
##
## [[6]]
## Wu-Hausman: stat = 35.471, p = 2.984e-9, on 1 and 2,313 DoF.
##
## [[7]]
## Wu-Hausman: stat = 21.528, p = 3.682e-6, on 1 and 2,324 DoF.
##
## [[8]]
## Wu-Hausman: stat = 22.903, p = 1.811e-6, on 1 and 2,322 DoF.
models_all <- list(
OLS = lm(all_math~`Federal Funding Per Pupil`+`Local Funding Per Pupil`+`State Funding Per Pupil`+`Percent Native American`+`Percent Asian`+`Percent Hispanic`+`Percent Black`+`Percent White`+`Urbanicity`+`Percent Free or Reduced Price Lunch`, data = x),
FE = feols(all_math~`Federal Funding Per Pupil`+`Local Funding Per Pupil`+`State Funding Per Pupil`+`Percent Native American`+`Percent Asian`+`Percent Hispanic`+`Percent Black`+`Percent White`+`Urbanicity`+`Percent Free or Reduced Price Lunch`, data = x, cluster = ~ID),
DiD = feols(all_math~`Eligible`:post+`Federal Funding Per Pupil`+`Local Funding Per Pupil`+`State Funding Per Pupil`+`Percent Native American`+`Percent Asian`+`Percent Hispanic`+`Percent Black`+`Percent White`+`Urbanicity`+`Percent Free or Reduced Price Lunch`, data = x, cluster = ~ID),
IV = feols(all_math~`Percent White`+`Percent Black`+`Percent Hispanic`+`Local Funding Per Pupil`+`Percent Free or Reduced Price Lunch`|ID +`Year`|`State Funding Per Pupil`~`Eligible`:post, data = x, cluster = ~ID),
OLS = lm(all_reading~`Federal Funding Per Pupil`+`Local Funding Per Pupil`+`State Funding Per Pupil`+`Percent Native American`+`Percent Asian`+`Percent Hispanic`+`Percent Black`+`Percent White`+`Urbanicity`+`Percent Free or Reduced Price Lunch`, data = x),
FE = feols(all_reading~`Federal Funding Per Pupil`+`Local Funding Per Pupil`+`State Funding Per Pupil`+`Percent Native American`+`Percent Asian`+`Percent Hispanic`+`Percent Black`+`Percent White`+`Urbanicity`+`Percent Free or Reduced Price Lunch`, data = x, cluster = ~ID),
DiD = feols(all_reading~`Eligible`:post+`Federal Funding Per Pupil`+`Local Funding Per Pupil`+`State Funding Per Pupil`+`Percent Native American`+`Percent Asian`+`Percent Hispanic`+`Percent Black`+`Percent White`+`Urbanicity`+`Percent Free or Reduced Price Lunch`, data = x, cluster = ~ID),
IV = feols(all_reading~`Percent White`+`Percent Black`+`Percent Hispanic`+`Local Funding Per Pupil`+`Percent Free or Reduced Price Lunch`|ID+`Year`|`State Funding Per Pupil`~`Eligible`:post, data = x, cluster = ~ID)
)
modelsummary(models_all) %>%
group_tt(j = list(Math = 2:5, Reading = 6:9))
| |
Math |
Reading |
| |
OLS |
FE |
DiD |
IV |
OLS |
FE |
DiD |
IV |
| (Intercept) |
0.358 |
0.358 |
0.351 |
|
0.388 |
0.388 |
0.410 |
|
|
(0.081) |
(0.114) |
(0.115) |
|
(0.072) |
(0.107) |
(0.103) |
|
| Federal Funding Per Pupil |
-0.009 |
-0.009 |
-0.011 |
|
-0.022 |
-0.022 |
-0.016 |
|
|
(0.002) |
(0.005) |
(0.005) |
|
(0.002) |
(0.005) |
(0.005) |
|
| Local Funding Per Pupil |
0.003 |
0.003 |
0.003 |
0.097 |
0.004 |
0.004 |
0.004 |
0.017 |
|
(0.001) |
(0.002) |
(0.002) |
(0.024) |
(0.001) |
(0.001) |
(0.001) |
(0.007) |
| State Funding Per Pupil |
0.001 |
0.001 |
0.002 |
|
0.004 |
0.004 |
0.003 |
|
|
(0.001) |
(0.001) |
(0.001) |
|
(0.001) |
(0.001) |
(0.001) |
|
| Percent Native American |
-0.710 |
-0.710 |
-0.738 |
|
-0.526 |
-0.526 |
-0.437 |
|
|
(0.414) |
(1.226) |
(1.252) |
|
(0.365) |
(1.390) |
(1.302) |
|
| Percent Asian |
0.827 |
0.827 |
0.822 |
|
0.603 |
0.603 |
0.618 |
|
|
(0.089) |
(0.148) |
(0.149) |
|
(0.078) |
(0.121) |
(0.118) |
|
| Percent Hispanic |
0.036 |
0.036 |
0.026 |
-2.384 |
0.075 |
0.075 |
0.107 |
-0.655 |
|
(0.083) |
(0.119) |
(0.120) |
(1.071) |
(0.074) |
(0.107) |
(0.104) |
(0.264) |
| Percent Black |
-0.856 |
-0.856 |
-0.870 |
0.755 |
-0.665 |
-0.665 |
-0.621 |
-0.302 |
|
(0.114) |
(0.193) |
(0.193) |
(1.468) |
(0.100) |
(0.172) |
(0.172) |
(0.498) |
| Percent White |
-0.007 |
-0.007 |
-0.016 |
0.368 |
0.085 |
0.085 |
0.113 |
0.277 |
|
(0.087) |
(0.125) |
(0.126) |
(0.395) |
(0.077) |
(0.117) |
(0.114) |
(0.113) |
| UrbanicityRural |
-0.077 |
-0.077 |
-0.076 |
|
-0.089 |
-0.089 |
-0.093 |
|
|
(0.021) |
(0.054) |
(0.053) |
|
(0.019) |
(0.040) |
(0.042) |
|
| UrbanicitySuburb |
0.011 |
0.011 |
0.011 |
|
0.020 |
0.020 |
0.020 |
|
|
(0.008) |
(0.018) |
(0.018) |
|
(0.007) |
(0.016) |
(0.016) |
|
| UrbanicityTown |
-0.076 |
-0.076 |
-0.076 |
|
-0.081 |
-0.081 |
-0.080 |
|
|
(0.015) |
(0.033) |
(0.033) |
|
(0.013) |
(0.030) |
(0.030) |
|
| Percent Free or Reduced Price Lunch |
-1.103 |
-1.103 |
-1.066 |
-0.492 |
-1.168 |
-1.168 |
-1.285 |
-0.268 |
|
(0.034) |
(0.077) |
(0.081) |
(0.306) |
(0.030) |
(0.077) |
(0.077) |
(0.084) |
| Eligible × post |
|
|
-0.027 |
|
|
|
0.086 |
|
|
|
|
(0.016) |
|
|
|
(0.014) |
|
| fit_State Funding Per Pupil |
|
|
|
-0.029 |
|
|
|
-0.005 |
|
|
|
|
(0.009) |
|
|
|
(0.002) |
| Num.Obs. |
2688 |
2688 |
2688 |
2671 |
2688 |
2688 |
2688 |
2671 |
| R2 |
0.791 |
0.791 |
0.792 |
0.949 |
0.831 |
0.831 |
0.837 |
0.973 |
| R2 Adj. |
0.790 |
0.790 |
0.791 |
0.942 |
0.830 |
0.830 |
0.836 |
0.969 |
| R2 Within |
|
|
|
0.182 |
|
|
|
0.057 |
| R2 Within Adj. |
|
|
|
0.179 |
|
|
|
0.055 |
| AIC |
-1450.5 |
-1452.5 |
-1458.1 |
913.6 |
-2123.9 |
-2125.9 |
-2223.4 |
-5457.8 |
| BIC |
-1368.0 |
-1375.9 |
-1375.5 |
2951.6 |
-2041.3 |
-2049.2 |
-2140.9 |
-3419.7 |
| Log.Lik. |
739.266 |
|
|
|
1075.946 |
|
|
|
| RMSE |
0.18 |
0.18 |
0.18 |
0.25 |
0.16 |
0.16 |
0.16 |
0.08 |
| FE: ID |
|
|
|
X |
|
|
|
X |
| FE: Year |
|
|
|
X |
|
|
|
X |
math_models <- list(
OLS = lm(all_math~`Eligible`+`Federal Funding Per Pupil`+`Local Funding Per Pupil`+`State Funding Per Pupil`+`Percent Native American`+`Percent Asian`+`Percent Hispanic`+`Percent Black`+`Percent White`+`Urbanicity`+`Percent Free or Reduced Price Lunch`, data = x, weights = totenrl),
FE = feols(all_math~`Eligible`+`Federal Funding Per Pupil`+`Local Funding Per Pupil`+`State Funding Per Pupil`+`Percent Native American`+`Percent Asian`+`Percent Hispanic`+`Percent Black`+`Percent White`+`Urbanicity`+`Percent Free or Reduced Price Lunch`, data = x, weights = ~totenrl, cluster = ~ID),
DiD = feols(all_math~`Eligible`:post+`Federal Funding Per Pupil`+`Local Funding Per Pupil`+`State Funding Per Pupil`+`Percent Native American`+`Percent Asian`+`Percent Hispanic`+`Percent Black`+`Percent White`+`Percent Free or Reduced Price Lunch`| ID + `Year`, data = x, weights = ~totenrl, cluster = ~ID),
IV = feols(all_math~`Percent White`+`Percent Black`+`Percent Hispanic`+`Local Funding Per Pupil`+`Percent Free or Reduced Price Lunch`|ID +`Year`|`State Funding Per Pupil`~`Eligible`:post, data = x, cluster = ~ID),
OLS = lm(blk_math~`Eligible`+`Federal Funding Per Pupil`+`Local Funding Per Pupil`+`State Funding Per Pupil`+`Percent Native American`+`Percent Asian`+`Percent Hispanic`+`Percent Black`+`Percent White`+`Urbanicity`+`Percent Free or Reduced Price Lunch`, data = x, weights = totenrl),
FE = feols(blk_math~`Eligible`+`Federal Funding Per Pupil`+`Local Funding Per Pupil`+`State Funding Per Pupil`+`Percent Native American`+`Percent Asian`+`Percent Hispanic`+`Percent Black`+`Percent White`+`Urbanicity`+`Percent Free or Reduced Price Lunch`, data = x, weights = ~totenrl, cluster = ~ID),
DiD = feols(blk_math~`Eligible`:post+`Federal Funding Per Pupil`+`Local Funding Per Pupil`+`State Funding Per Pupil`+`Percent Native American`+`Percent Asian`+`Percent Hispanic`+`Percent Black`+`Percent White`+`Percent Free or Reduced Price Lunch`| ID + `Year`, data = x, weights = ~totenrl, cluster = ~ID),
IV = feols(blk_math~`Percent White`+`Percent Black`+`Percent Hispanic`+`Percent Free or Reduced Price Lunch`|ID+`Year`|`State Funding Per Pupil`~`Eligible`:post, data = x, weights = ~totenrl, cluster = ~ID),
OLS = lm(wht_math~`Eligible`+`Federal Funding Per Pupil`+`Local Funding Per Pupil`+`State Funding Per Pupil`+`Percent Native American`+`Percent Asian`+`Percent Hispanic`+`Percent Black`+`Percent White`+`Urbanicity`+`Percent Free or Reduced Price Lunch`, data = x, weights = totenrl),
FE = feols(wht_math~`Eligible`+`Federal Funding Per Pupil`+`Local Funding Per Pupil`+`State Funding Per Pupil`+`Percent Native American`+`Percent Asian`+`Percent Hispanic`+`Percent Black`+`Percent White`+`Urbanicity`+`Percent Free or Reduced Price Lunch`, data = x, weights = ~totenrl, cluster = ~ID),
DiD = feols(wht_math~`Eligible`:post+`Federal Funding Per Pupil`+`Local Funding Per Pupil`+`State Funding Per Pupil`+`Percent Native American`+`Percent Asian`+`Percent Hispanic`+`Percent Black`+`Percent White`+`Percent Free or Reduced Price Lunch`| ID + `Year`, data = x, weights = ~totenrl, cluster = ~ID),
IV = feols(wht_math~`Percent White`+`Percent Black`+`Percent Hispanic`+`Percent Free or Reduced Price Lunch`|ID+`Year`|`State Funding Per Pupil`~`Eligible`:post, data = x, weights = ~totenrl, cluster = ~ID),
OLS = lm(hsp_math~`Eligible`+`Federal Funding Per Pupil`+`Local Funding Per Pupil`+`State Funding Per Pupil`+`Percent Native American`+`Percent Asian`+`Percent Hispanic`+`Percent Black`+`Percent White`+`Urbanicity`+`Percent Free or Reduced Price Lunch`, data = x, weights = totenrl),
FE = feols(hsp_math~`Eligible`+`Federal Funding Per Pupil`+`Local Funding Per Pupil`+`State Funding Per Pupil`+`Percent Native American`+`Percent Asian`+`Percent Hispanic`+`Percent Black`+`Percent White`+`Urbanicity`+`Percent Free or Reduced Price Lunch`, data = x, weights = ~totenrl, cluster = ~ID),
DiD = feols(hsp_math~`Eligible`:post+`Federal Funding Per Pupil`+`Local Funding Per Pupil`+`State Funding Per Pupil`+`Percent Native American`+`Percent Asian`+`Percent Hispanic`+`Percent Black`+`Percent White`+`Percent Free or Reduced Price Lunch`| ID + `Year`, data = x, weights = ~totenrl, cluster = ~ID),
IV = feols(hsp_reading~`Percent White`+`Percent Black`+`Percent Hispanic`+`Percent Free or Reduced Price Lunch`|ID+`Year`|`State Funding Per Pupil`~`Eligible`:post, data = x, weights = ~totenrl, cluster = ~ID)
)
modelsummary(math_models) %>%
group_tt(j=list(All=2:5, Black=6:9, White=10:13, Hispanic=14:17))
| |
All |
Black |
White |
Hispanic |
| |
OLS |
FE |
DiD |
IV |
OLS |
FE |
DiD |
IV |
OLS |
FE |
DiD |
IV |
OLS |
FE |
DiD |
IV |
| (Intercept) |
0.261 |
0.261 |
|
|
-0.212 |
-0.212 |
|
|
0.457 |
0.457 |
|
|
0.243 |
0.243 |
|
|
|
(0.091) |
(0.164) |
|
|
(0.124) |
(0.246) |
|
|
(0.117) |
(0.267) |
|
|
(0.098) |
(0.213) |
|
|
| Eligible |
-0.002 |
-0.002 |
|
|
-0.055 |
-0.055 |
|
|
0.067 |
0.067 |
|
|
0.026 |
0.026 |
|
|
|
(0.012) |
(0.036) |
|
|
(0.017) |
(0.053) |
|
|
(0.016) |
(0.042) |
|
|
(0.013) |
(0.040) |
|
|
| Federal Funding Per Pupil |
-0.000 |
-0.000 |
0.020 |
|
0.012 |
0.012 |
0.016 |
|
0.027 |
0.027 |
0.011 |
|
-0.007 |
-0.007 |
0.021 |
|
|
(0.003) |
(0.007) |
(0.006) |
|
(0.004) |
(0.011) |
(0.006) |
|
(0.004) |
(0.014) |
(0.007) |
|
(0.003) |
(0.007) |
(0.005) |
|
| Local Funding Per Pupil |
0.003 |
0.003 |
0.008 |
0.097 |
-0.003 |
-0.003 |
0.009 |
|
0.016 |
0.016 |
0.009 |
|
-0.005 |
-0.005 |
0.005 |
|
|
(0.001) |
(0.002) |
(0.002) |
(0.024) |
(0.001) |
(0.002) |
(0.003) |
|
(0.001) |
(0.002) |
(0.003) |
|
(0.001) |
(0.002) |
(0.002) |
|
| State Funding Per Pupil |
-0.000 |
-0.000 |
-0.008 |
|
-0.007 |
-0.007 |
-0.008 |
|
0.001 |
0.001 |
-0.006 |
|
0.003 |
0.003 |
-0.007 |
|
|
(0.001) |
(0.001) |
(0.001) |
|
(0.001) |
(0.002) |
(0.002) |
|
(0.001) |
(0.003) |
(0.002) |
|
(0.001) |
(0.002) |
(0.001) |
|
| Percent Native American |
-4.038 |
-4.038 |
0.386 |
|
-3.101 |
-3.101 |
2.170 |
|
-7.808 |
-7.808 |
0.098 |
|
-2.261 |
-2.261 |
1.098 |
|
|
(0.604) |
(1.577) |
(2.072) |
|
(0.868) |
(1.927) |
(2.279) |
|
(0.789) |
(2.634) |
(1.987) |
|
(0.664) |
(1.426) |
(2.144) |
|
| Percent Asian |
0.995 |
0.995 |
1.111 |
|
0.238 |
0.238 |
0.944 |
|
0.072 |
0.072 |
0.205 |
|
-0.303 |
-0.303 |
0.453 |
|
|
(0.097) |
(0.200) |
(0.265) |
|
(0.132) |
(0.274) |
(0.447) |
|
(0.124) |
(0.267) |
(0.275) |
|
(0.104) |
(0.246) |
(0.313) |
|
| Percent Hispanic |
-0.004 |
-0.004 |
-0.485 |
-2.384 |
0.413 |
0.413 |
-0.492 |
-1.001 |
0.194 |
0.194 |
-0.298 |
-0.636 |
-0.140 |
-0.140 |
-0.140 |
-0.149 |
|
(0.090) |
(0.174) |
(0.153) |
(1.071) |
(0.124) |
(0.263) |
(0.206) |
(0.555) |
(0.116) |
(0.266) |
(0.156) |
(0.440) |
(0.098) |
(0.207) |
(0.143) |
(0.158) |
| Percent Black |
-0.888 |
-0.888 |
-0.319 |
0.755 |
-1.155 |
-1.155 |
0.683 |
0.596 |
0.204 |
0.204 |
-0.019 |
-0.218 |
-0.557 |
-0.557 |
0.401 |
0.145 |
|
(0.118) |
(0.236) |
(0.641) |
(1.468) |
(0.162) |
(0.368) |
(0.663) |
(0.966) |
(0.152) |
(0.385) |
(0.601) |
(0.837) |
(0.128) |
(0.279) |
(0.659) |
(0.650) |
| Percent White |
0.126 |
0.126 |
-0.042 |
0.368 |
0.182 |
0.182 |
0.196 |
0.114 |
-0.018 |
-0.018 |
-0.093 |
-0.105 |
-0.299 |
-0.299 |
-0.213 |
0.059 |
|
(0.097) |
(0.174) |
(0.099) |
(0.395) |
(0.132) |
(0.268) |
(0.148) |
(0.301) |
(0.124) |
(0.281) |
(0.096) |
(0.231) |
(0.105) |
(0.231) |
(0.116) |
(0.098) |
| UrbanicityRural |
-0.028 |
-0.028 |
|
|
-0.079 |
-0.079 |
|
|
-0.265 |
-0.265 |
|
|
0.004 |
0.004 |
|
|
|
(0.031) |
(0.036) |
|
|
(0.047) |
(0.045) |
|
|
(0.040) |
(0.060) |
|
|
(0.034) |
(0.028) |
|
|
| UrbanicitySuburb |
0.016 |
0.016 |
|
|
0.059 |
0.059 |
|
|
-0.127 |
-0.127 |
|
|
0.038 |
0.038 |
|
|
|
(0.007) |
(0.019) |
|
|
(0.009) |
(0.029) |
|
|
(0.009) |
(0.031) |
|
|
(0.007) |
(0.021) |
|
|
| UrbanicityTown |
-0.025 |
-0.025 |
|
|
0.033 |
0.033 |
|
|
-0.152 |
-0.152 |
|
|
-0.005 |
-0.005 |
|
|
|
(0.020) |
(0.041) |
|
|
(0.029) |
(0.071) |
|
|
(0.026) |
(0.065) |
|
|
(0.022) |
(0.044) |
|
|
| Percent Free or Reduced Price Lunch |
-0.956 |
-0.956 |
-0.250 |
-0.492 |
-0.801 |
-0.801 |
-0.137 |
0.142 |
-1.079 |
-1.079 |
-0.210 |
0.009 |
-0.829 |
-0.829 |
-0.189 |
-0.095 |
|
(0.039) |
(0.116) |
(0.053) |
(0.306) |
(0.053) |
(0.203) |
(0.081) |
(0.140) |
(0.050) |
(0.100) |
(0.070) |
(0.120) |
(0.042) |
(0.125) |
(0.057) |
(0.057) |
| Eligible × post |
|
|
-0.114 |
|
|
|
-0.113 |
|
|
|
-0.096 |
|
|
|
-0.111 |
|
|
|
|
(0.016) |
|
|
|
(0.024) |
|
|
|
(0.016) |
|
|
|
(0.017) |
|
| fit_State Funding Per Pupil |
|
|
|
-0.029 |
|
|
|
-0.065 |
|
|
|
-0.053 |
|
|
|
-0.013 |
|
|
|
|
(0.009) |
|
|
|
(0.011) |
|
|
|
(0.008) |
|
|
|
(0.005) |
| Num.Obs. |
2688 |
2688 |
2671 |
2671 |
2565 |
2565 |
2548 |
2548 |
2656 |
2656 |
2639 |
2639 |
2661 |
2661 |
2644 |
2668 |
| R2 |
0.838 |
0.838 |
0.962 |
0.949 |
0.549 |
0.549 |
0.859 |
1.000 |
0.603 |
0.603 |
0.923 |
1.000 |
0.451 |
0.451 |
0.878 |
1.000 |
| R2 Adj. |
0.837 |
0.837 |
0.956 |
0.942 |
0.546 |
0.546 |
0.837 |
1.000 |
0.601 |
0.601 |
0.912 |
1.000 |
0.448 |
0.448 |
0.860 |
1.000 |
| R2 Within |
|
|
0.263 |
0.182 |
|
|
0.127 |
1.000 |
|
|
0.138 |
1.000 |
|
|
0.191 |
1.000 |
| R2 Within Adj. |
|
|
0.260 |
0.179 |
|
|
0.123 |
1.000 |
|
|
0.134 |
1.000 |
|
|
0.188 |
1.000 |
| AIC |
-1142.5 |
-1339.8 |
-4586.7 |
913.6 |
392.6 |
198.8 |
-1896.6 |
7878.9 |
165.7 |
1378.6 |
-3763.2 |
6851.7 |
-755.3 |
-1141.9 |
-4307.3 |
-482.2 |
| BIC |
-1054.1 |
-1257.2 |
-2525.2 |
2951.6 |
480.3 |
280.7 |
119.3 |
9865.6 |
254.0 |
1461.0 |
-1705.8 |
8879.7 |
-667.0 |
-1059.5 |
-2249.3 |
1549.5 |
| Log.Lik. |
586.249 |
|
|
|
-181.297 |
|
|
|
-67.874 |
|
|
|
392.671 |
|
|
|
| RMSE |
0.19 |
0.19 |
0.09 |
0.25 |
0.25 |
0.25 |
0.15 |
0.99 |
0.31 |
0.31 |
0.10 |
0.78 |
0.19 |
0.19 |
0.09 |
0.19 |
| FE: ID |
|
|
X |
X |
|
|
X |
X |
|
|
X |
X |
|
|
X |
X |
| FE: Year |
|
|
X |
X |
|
|
X |
X |
|
|
X |
X |
|
|
X |
X |
library(kableExtra)
library(magick)
desc <- x %>%
mutate(
period = case_when(
Year == 2009 ~ "Pre (2009)",
Year == 2019 ~ "Post (2019)",
TRUE ~ NA_character_
)
) %>%
filter(!is.na(period))
fmt <- function(x) {
x <- x[!is.na(x)]
if (length(x) == 0) return("—")
sprintf("%.2f (%.2f)", mean(x), sd(x))
}
groups <- list(
"Ineligible — Pre" = desc %>% filter(`Eligible` == 0, period == "Pre (2009)"),
"Ineligible — Post" = desc %>% filter(`Eligible` == 0, period == "Post (2019)"),
"Eligible — Pre" = desc %>% filter(`Eligible` == 1, period == "Pre (2009)"),
"Eligible — Post" = desc %>% filter(`Eligible` == 1, period == "Post (2019)")
)
vars <- list(
"All Math" = "all_math",
"All Reading" = "all_reading",
"White Math" = "wht_math",
"White Reading" = "wht_reading",
"Hispanic Math" = "hsp_math",
"Hispanic Reading" = "hsp_reading",
"Black Math" = "blk_math",
"Black Reading" = "blk_reading",
"State $/Pupil" = "State Funding Per Pupil",
"Local $/Pupil" = "Local Funding Per Pupil"
)
rows <- lapply(vars, function(v) sapply(groups, function(g) fmt(g[[v]])))
tab <- do.call(rbind, rows)
rownames(tab) <- names(vars)
colnames(tab) <- names(groups)
kable(tab,
caption = "Mean (SD) by Eligibility Status and Period",
booktabs = TRUE,
align = "c") %>%
kable_styling(full_width = FALSE, font_size = 10) %>%
pack_rows("Test Scores", 1, 8) %>%
pack_rows("Funding", 9, 10) %>%
add_header_above(c(" " = 1,
"Ineligible (<55% FRL)" = 2,
"Eligible (≥55% FRL)" = 2)) %>%
footnote(general = "Test scores are standardized relative to the national mean (SEDA v6.0); negative values indicate below-average performance.",
general_title = "Note:",
footnote_as_chunk = TRUE) %>%
save_kable("desc_table.png")
# Test 1: Fiscal Substitution
# Does LCFF eligibility cause a reduction in local funding per pupil?
substitution_did <- feols(
`Local Funding Per Pupil` ~ `Eligible`:post +
`Percent White` + `Percent Black` + `Percent Hispanic` +
`Percent Free or Reduced Price Lunch` +
`Federal Funding Per Pupil` |
ID + Year,
data = x,
weights = ~totenrl,
cluster = ~ID
)
modelsummary(substitution_did)
| |
(1) |
| Percent White |
4.500 |
|
(2.680) |
| Percent Black |
-12.331 |
|
(12.134) |
| Percent Hispanic |
-15.115 |
|
(3.698) |
| Percent Free or Reduced Price Lunch |
-4.474 |
|
(1.271) |
| Federal Funding Per Pupil |
0.314 |
|
(0.167) |
| Eligible × post |
-1.143 |
|
(0.235) |
| Num.Obs. |
2671 |
| R2 |
0.945 |
| R2 Adj. |
0.937 |
| R2 Within |
0.129 |
| R2 Within Adj. |
0.127 |
| AIC |
12195.6 |
| BIC |
14233.6 |
| RMSE |
2.08 |
| FE: ID |
X |
| FE: Year |
X |
# Run all three models you want to show
first_stage <- feols(
`State Funding Per Pupil` ~ `Eligible`:post +
`Percent White` + `Percent Black` + `Percent Hispanic` +
`Local Funding Per Pupil` | ID + Year,
data = x, cluster = ~ID
)
substitution <- feols(
`Local Funding Per Pupil` ~ `Eligible`:post +
`Percent White` + `Percent Black` + `Percent Hispanic` +
`Percent Free or Reduced Price Lunch` +
`Federal Funding Per Pupil` | ID + Year,
data = x, cluster = ~ID
)
did_reading <- feols(
hsp_reading ~ `Eligible`:post +
`Percent White` + `Percent Black` + `Percent Hispanic` +
`Local Funding Per Pupil` + `Percent Free or Reduced Price Lunch` | ID + Year,
data = x, cluster = ~ID
)
# Build a clean summary table manually
results <- data.frame(
` ` = c(
"Effect of Eligibility × Post",
"Standard Error",
"",
"Observations",
"First-Stage F-Stat",
"District & Year FE"
),
`State Funding Per Pupil` = c("+$5.88", "(1.94)", "", "2,671", "62.4", "Yes"),
`Local Funding Per Pupil` = c("-$1.27", "(0.31)", "", "2,671", "—", "Yes"),
`Hispanic Reading Score` = c("+0.131 SD", "(0.013)", "", "2,685", "—", "Yes"),
check.names = FALSE
)
kable(results,
align = c("l", "c", "c", "c"),
caption = "Effects of LCFF Eligibility on Funding and Achievement") %>%
kable_styling(
bootstrap_options = c("striped", "condensed"),
full_width = FALSE,
font_size = 14
) %>%
add_header_above(c(
" " = 1,
"Funding Mechanisms" = 2,
"Achievement" = 1
)) %>%
row_spec(1, bold = TRUE) %>%
footnote(
general = "All models include district and year fixed effects with standard errors clustered at the district level. Eligible = district had >55% FRL share in 2012 (pre-LCFF baseline).",
general_title = "Note:",
footnote_as_chunk = TRUE
) %>%
save_kable("mechanisms_table1.png", zoom = 2)
# pre-trends check
est <- feols(
all_math ~ i(`Year`, treat, ref = 2012) + `Percent White`+`Percent Black`+`Percent Hispanic`+`Percent Free or Reduced Price Lunch`| ID + `Year`, weights = ~totenrl,
data = x
)
iplot(est)
