Load in packages

suppressPackageStartupMessages(library(tidyverse))
suppressPackageStartupMessages(library(lme4))

Load and explore data

stardata <- haven::read_dta("projectSTAR.dta")
glimpse(stardata)
## Rows: 6,325
## Columns: 27
## $ stdntid       <dbl> 10001, 10133, 10246, 10263, 10266, 10275, 10281, 10282, …
## $ race          <dbl+lbl> 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1…
## $ gender        <dbl+lbl> 1, 1, 2, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 2…
## $ FLAGSGK       <dbl+lbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1…
## $ flaggk        <dbl+lbl> 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1…
## $ gkclasstype   <dbl+lbl> 3, 3, 3, 1, 2, 3, 1, 3, 1, 2, 3, 3, 2, 3, 3, 3, 1, 2…
## $ gkschid       <dbl> 169229, 169280, 218562, 205492, 257899, 161176, 189382, …
## $ gksurban      <dbl+lbl> 2, 2, 4, 2, 3, 3, 2, 2, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3…
## $ gktchid       <dbl> 16922904, 16928003, 21856202, 20549204, 25789904, 161176…
## $ gktgen        <dbl+lbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2…
## $ gktrace       <dbl+lbl> 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1…
## $ gkthighdegree <dbl+lbl> 2, 2, 3, 2, 3, 2, 3, 3, 3, 3, 2, 2, 3, 2, 2, 2, 2, 2…
## $ gktcareer     <dbl+lbl>  4,  4,  4,  4,  4, NA,  4,  4,  4,  4,  4,  4,  4, …
## $ gktyears      <dbl> 5, 7, 8, 3, 12, 2, 7, 14, 4, 6, 11, 16, 12, 5, 17, 10, 6…
## $ gkclasssize   <dbl> 24, 22, 17, 17, 24, 24, 13, 24, 14, 23, 23, 22, 20, 24, …
## $ gkfreelunch   <dbl+lbl> 2, 2, 2, 1, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 2…
## $ gkrepeat      <dbl+lbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1…
## $ gkspeced      <dbl+lbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2…
## $ gkspecin      <dbl+lbl> 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2…
## $ gkpresent     <dbl> 161, 175, 132, 178, 170, 94, 160, 154, 172, 95, 163, 172…
## $ gkabsent      <dbl> 19, 5, 28, 2, 10, 3, 2, 7, 8, 2, 17, 8, 0, 31, 7, NA, 20…
## $ gktreadss     <dbl> NA, 427, 450, 483, 456, 411, 443, 448, 463, 472, 428, 54…
## $ gktmathss     <dbl> NA, 478, 494, 513, 513, 468, 473, 449, 520, 536, 484, 62…
## $ gktlistss     <dbl> NA, 509, 549, 554, 520, 571, 595, 540, 565, 595, NA, 622…
## $ gkwordskillss <dbl> NA, 418, 444, 431, 468, 396, 444, 444, 480, 486, 423, 52…
## $ gkmotivraw    <dbl> 23, 24, 28, 27, 25, 24, NA, NA, 26, 27, 24, 24, 23, 28, …
## $ gkselfconcraw <dbl> 52, 53, 56, 61, 54, 55, NA, NA, 52, 61, 55, 49, 49, 59, …
str(stardata)
## tibble [6,325 × 27] (S3: tbl_df/tbl/data.frame)
##  $ stdntid      : num [1:6325] 10001 10133 10246 10263 10266 ...
##   ..- attr(*, "label")= chr "STUDENT ID"
##   ..- attr(*, "format.stata")= chr "%10.0g"
##  $ race         : dbl+lbl [1:6325] 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1,...
##    ..@ label       : chr "STUDENT RACE/ETHNICITY"
##    ..@ format.stata: chr "%10.0g"
##    ..@ labels      : Named num [1:6] 1 2 3 4 5 6
##    .. ..- attr(*, "names")= chr [1:6] "WHITE" "BLACK" "ASIAN" "HISPANIC" ...
##  $ gender       : dbl+lbl [1:6325] 1, 1, 2, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 2,...
##    ..@ label       : chr "STUDENT GENDER"
##    ..@ format.stata: chr "%10.0g"
##    ..@ labels      : Named num [1:2] 1 2
##    .. ..- attr(*, "names")= chr [1:2] "MALE" "FEMALE"
##  $ FLAGSGK      : dbl+lbl [1:6325] 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,...
##    ..@ label       : chr "IN STAR IN KINDERGARTEN"
##    ..@ format.stata: chr "%10.0g"
##    ..@ labels      : Named num [1:2] 0 1
##    .. ..- attr(*, "names")= chr [1:2] "NO" "YES"
##  $ flaggk       : dbl+lbl [1:6325] 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1,...
##    ..@ label       : chr "ACHIEVEMENT DATA AVAILABLE GRADE K"
##    ..@ format.stata: chr "%10.0g"
##    ..@ labels      : Named num [1:2] 0 1
##    .. ..- attr(*, "names")= chr [1:2] "NO" "YES"
##  $ gkclasstype  : dbl+lbl [1:6325] 3, 3, 3, 1, 2, 3, 1, 3, 1, 2, 3, 3, 2, 3, 3, 3, 1, 2,...
##    ..@ label       : chr "CLASSROOM TYPE KINDERGARTEN"
##    ..@ format.stata: chr "%10.0g"
##    ..@ labels      : Named num [1:3] 1 2 3
##    .. ..- attr(*, "names")= chr [1:3] "SMALL CLASS" "REGULAR CLASS" "REGULAR + AIDE CLASS"
##  $ gkschid      : num [1:6325] 169229 169280 218562 205492 257899 ...
##   ..- attr(*, "label")= chr "KINDERGARTEN SCHOOL ID"
##   ..- attr(*, "format.stata")= chr "%10.0g"
##  $ gksurban     : dbl+lbl [1:6325] 2, 2, 4, 2, 3, 3, 2, 2, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3,...
##    ..@ label       : chr "SCHOOL URBANICITY KINDERGARTEN"
##    ..@ format.stata: chr "%10.0g"
##    ..@ labels      : Named num [1:4] 1 2 3 4
##    .. ..- attr(*, "names")= chr [1:4] "INNER CITY" "SUBURBAN" "RURAL" "URBAN"
##  $ gktchid      : num [1:6325] 16922904 16928003 21856202 20549204 25789904 ...
##   ..- attr(*, "label")= chr "KINDERGARTEN TEACHER ID"
##   ..- attr(*, "format.stata")= chr "%10.0g"
##  $ gktgen       : dbl+lbl [1:6325] 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,...
##    ..@ label       : chr "TEACHER GENDER KINDERGARTEN"
##    ..@ format.stata: chr "%10.0g"
##    ..@ labels      : Named num [1:2] 1 2
##    .. ..- attr(*, "names")= chr [1:2] "MALE" "FEMALE"
##  $ gktrace      : dbl+lbl [1:6325]  2,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  1,  ...
##    ..@ label       : chr "TEACHER RACE/ETHNICITY KINDERGARTEN"
##    ..@ format.stata: chr "%10.0g"
##    ..@ labels      : Named num [1:6] 1 2 3 4 5 6
##    .. ..- attr(*, "names")= chr [1:6] "WHITE" "BLACK" "ASIAN" "HISPANIC" ...
##  $ gkthighdegree: dbl+lbl [1:6325]  2,  2,  3,  2,  3,  2,  3,  3,  3,  3,  2,  2,  3,  ...
##    ..@ label       : chr "TEACHER HIGHEST DEGREE KINDERGARTEN"
##    ..@ format.stata: chr "%10.0g"
##    ..@ labels      : Named num [1:6] 1 2 3 4 5 6
##    .. ..- attr(*, "names")= chr [1:6] "ASSOCIATES" "BACHELORS" "MASTERS" "MASTERS +" ...
##  $ gktcareer    : dbl+lbl [1:6325]  4,  4,  4,  4,  4, NA,  4,  4,  4,  4,  4,  4,  4,  ...
##    ..@ label       : chr "TEACHER CAREER LADDER LEVEL KINDERGARTEN"
##    ..@ format.stata: chr "%10.0g"
##    ..@ labels      : Named num [1:7] 1 2 3 4 5 6 7
##    .. ..- attr(*, "names")= chr [1:7] "CHOSE NO TO BE ON CAREER LADDER" "APPRENTICE" "PROBATION" "LADDER LEVEL 1" ...
##  $ gktyears     : num [1:6325] 5 7 8 3 12 2 7 14 4 6 ...
##   ..- attr(*, "label")= chr "YEARS OF TOTAL TEACHING EXPERIENCE KINDERGARTEN"
##   ..- attr(*, "format.stata")= chr "%10.0g"
##  $ gkclasssize  : num [1:6325] 24 22 17 17 24 24 13 24 14 23 ...
##   ..- attr(*, "label")= chr "CLASS SIZE KINDERGARTEN"
##   ..- attr(*, "format.stata")= chr "%10.0g"
##  $ gkfreelunch  : dbl+lbl [1:6325] 2, 2, 2, 1, 2, 2, 2, 1, 1, 2, 2, 2, 2, 2, 2, 2, 1, 2,...
##    ..@ label       : chr "FREE/REDUCED LUNCH STATUS KINDERGARTEN"
##    ..@ format.stata: chr "%10.0g"
##    ..@ labels      : Named num [1:2] 1 2
##    .. ..- attr(*, "names")= chr [1:2] "FREE LUNCH" "NON-FREE LUNCH"
##  $ gkrepeat     : dbl+lbl [1:6325] 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,...
##    ..@ label       : chr "REPEATING KINDERGARTEN IN 1985-1986 SCHOOL YEAR"
##    ..@ format.stata: chr "%10.0g"
##    ..@ labels      : Named num [1:2] 1 2
##    .. ..- attr(*, "names")= chr [1:2] "YES, PROMOTION RECOMMENDED" "NO, PROMOTION NOT RECOMMENDED"
##  $ gkspeced     : dbl+lbl [1:6325] 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,...
##    ..@ label       : chr "SPECIAL EDUCATION STATUS KINDERGARTEN"
##    ..@ format.stata: chr "%10.0g"
##    ..@ labels      : Named num [1:2] 1 2
##    .. ..- attr(*, "names")= chr [1:2] "YES" "NO"
##  $ gkspecin     : dbl+lbl [1:6325] 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2,...
##    ..@ label       : chr "PULLED OUT FOR SPECIAL INSTRUCTION KINDERGARTEN"
##    ..@ format.stata: chr "%10.0g"
##    ..@ labels      : Named num [1:2] 1 2
##    .. ..- attr(*, "names")= chr [1:2] "YES" "NO"
##  $ gkpresent    : num [1:6325] 161 175 132 178 170 94 160 154 172 95 ...
##   ..- attr(*, "label")= chr "DAYS PRESENT AT SCHOOL KINDERGARTEN"
##   ..- attr(*, "format.stata")= chr "%10.0g"
##  $ gkabsent     : num [1:6325] 19 5 28 2 10 3 2 7 8 2 ...
##   ..- attr(*, "label")= chr "DAYS ABSENT FROM SCHOOL KINDERGARTEN"
##   ..- attr(*, "format.stata")= chr "%10.0g"
##  $ gktreadss    : num [1:6325] NA 427 450 483 456 411 443 448 463 472 ...
##   ..- attr(*, "label")= chr "TOTAL READING SCALE SCORE SAT KINDERGARTEN"
##   ..- attr(*, "format.stata")= chr "%10.0g"
##  $ gktmathss    : num [1:6325] NA 478 494 513 513 468 473 449 520 536 ...
##   ..- attr(*, "label")= chr "TOTAL MATH SCALE SCORE SAT KINDERGARTEN"
##   ..- attr(*, "format.stata")= chr "%10.0g"
##  $ gktlistss    : num [1:6325] NA 509 549 554 520 571 595 540 565 595 ...
##   ..- attr(*, "label")= chr "TOTAL LISTENING SCALE SCORE SAT KINDERGARTEN"
##   ..- attr(*, "format.stata")= chr "%10.0g"
##  $ gkwordskillss: num [1:6325] NA 418 444 431 468 396 444 444 480 486 ...
##   ..- attr(*, "label")= chr "WORD STUDY SKILLS SCALE SCORE SAT KINDERGARTEN"
##   ..- attr(*, "format.stata")= chr "%10.0g"
##  $ gkmotivraw   : num [1:6325] 23 24 28 27 25 24 NA NA 26 27 ...
##   ..- attr(*, "label")= chr "MOTIVATION RAW SCORE SCAMIN KINDERGARTEN"
##   ..- attr(*, "format.stata")= chr "%10.0g"
##  $ gkselfconcraw: num [1:6325] 52 53 56 61 54 55 NA NA 52 61 ...
##   ..- attr(*, "label")= chr "SELF-CONCEPT RAW SCORE SCAMIN KINDERGARTEN"
##   ..- attr(*, "format.stata")= chr "%10.0g"

Creating clean dataset / recoding variables

star.clean <- stardata %>% 
  mutate (.,
          school = gkschid, 
          class = gktchid, 
          math = gktmathss,
          class_type = as_factor(gkclasstype),
          degree = as_factor(gkthighdegree),
          self_concept = gkselfconcraw) %>%
  group_by(school) %>%
  mutate (.,
          math_school = mean(gktmathss, na.rm = TRUE)) %>% 
  ungroup() %>% 
  select (., 
          school,
          class,
          math,
          class_type,
          degree,
          gkthighdegree,
          math_school, 
          self_concept)
glimpse(star.clean)
## Rows: 6,325
## Columns: 8
## $ school        <dbl> 169229, 169280, 218562, 205492, 257899, 161176, 189382, …
## $ class         <dbl> 16922904, 16928003, 21856202, 20549204, 25789904, 161176…
## $ math          <dbl> NA, 478, 494, 513, 513, 468, 473, 449, 520, 536, 484, 62…
## $ class_type    <fct> REGULAR + AIDE CLASS, REGULAR + AIDE CLASS, REGULAR + AI…
## $ degree        <fct> BACHELORS, BACHELORS, MASTERS, BACHELORS, MASTERS, BACHE…
## $ gkthighdegree <dbl+lbl> 2, 2, 3, 2, 3, 2, 3, 3, 3, 3, 2, 2, 3, 2, 2, 2, 2, 2…
## $ math_school   <dbl> 498.8768, 486.9811, 501.1071, 502.6133, 476.2800, 476.78…
## $ self_concept  <dbl> 52, 53, 56, 61, 54, 55, NA, NA, 52, 61, 55, 49, 49, 59, …
summary(star.clean)
##      school           class               math      
##  Min.   :112038   Min.   :11203801   Min.   :288.0  
##  1st Qu.:176329   1st Qu.:17632904   1st Qu.:454.0  
##  Median :215533   Median :21553306   Median :484.0  
##  Mean   :211227   Mean   :21122678   Mean   :485.4  
##  3rd Qu.:244774   3rd Qu.:24477401   3rd Qu.:513.0  
##  Max.   :264945   Max.   :26494505   Max.   :626.0  
##                                      NA's   :454    
##                 class_type          degree     gkthighdegree    math_school   
##  SMALL CLASS         :1900   ASSOCIATES:   0   Min.   :2.000   Min.   :427.0  
##  REGULAR CLASS       :2194   BACHELORS :4119   1st Qu.:2.000   1st Qu.:474.0  
##  REGULAR + AIDE CLASS:2231   MASTERS   :1981   Median :2.000   Median :486.6  
##                              MASTERS + : 161   Mean   :2.386   Mean   :485.4  
##                              SPECIALIST:  43   3rd Qu.:3.000   3rd Qu.:502.5  
##                              DOCTORAL  :   0   Max.   :5.000   Max.   :549.6  
##                              NA's      :  21   NA's   :21                     
##   self_concept  
##  Min.   : 0.00  
##  1st Qu.:53.00  
##  Median :56.00  
##  Mean   :55.95  
##  3rd Qu.:59.00  
##  Max.   :72.00  
##  NA's   :1287

Null 3-level Model

model.0 <- lmer(math ~ (1|class) + (1|school), REML=FALSE, data=star.clean)
summary(model.0)
## Linear mixed model fit by maximum likelihood  ['lmerMod']
## Formula: math ~ (1 | class) + (1 | school)
##    Data: star.clean
## 
##      AIC      BIC   logLik deviance df.resid 
##  60618.8  60645.5 -30305.4  60610.8     5867 
## 
## Scaled residuals: 
##     Min      1Q  Median      3Q     Max 
## -6.2037 -0.6273 -0.0635  0.5846  3.9171 
## 
## Random effects:
##  Groups   Name        Variance Std.Dev.
##  class    (Intercept)  287.6   16.96   
##  school   (Intercept)  375.8   19.39   
##  Residual             1612.4   40.15   
## Number of obs: 5871, groups:  class, 325; school, 79
## 
## Fixed effects:
##             Estimate Std. Error t value
## (Intercept)   486.00       2.45   198.4

##Calculate ICCs

ICC.class = 287.6/(287.6+375.8+1612.4)
ICC.class
## [1] 0.1263731

12.64% of the variability in math scores is between classrooms/teachers within the same school.

ICC.school = 376.8/(287.6+375.8+1612.4)
ICC.school
## [1] 0.1655682

16.56% of the variability in math scores is between schools.

##% variability at student-level

1-(ICC.class+ICC.school)
## [1] 0.7080587

##Conditional Models##

#Adding L1 Predictor(s)

model.1 <- lmer(math ~ self_concept + (1|class) + (1|school), REML=FALSE, data=star.clean)
summary(model.1)
## Linear mixed model fit by maximum likelihood  ['lmerMod']
## Formula: math ~ self_concept + (1 | class) + (1 | school)
##    Data: star.clean
## 
##      AIC      BIC   logLik deviance df.resid 
##  48969.7  49002.0 -24479.9  48959.7     4751 
## 
## Scaled residuals: 
##     Min      1Q  Median      3Q     Max 
## -3.8498 -0.6473 -0.0640  0.5925  3.9068 
## 
## Random effects:
##  Groups   Name        Variance Std.Dev.
##  class    (Intercept)  283.8   16.85   
##  school   (Intercept)  395.7   19.89   
##  Residual             1551.1   39.38   
## Number of obs: 4756, groups:  class, 301; school, 73
## 
## Fixed effects:
##              Estimate Std. Error t value
## (Intercept)  461.8349     7.1431  64.655
## self_concept   0.4523     0.1188   3.807
## 
## Correlation of Fixed Effects:
##             (Intr)
## self_concpt -0.931

Estimated math scores for students w/ average self-concept scores = 461.83. Estimated math scores for students increase by 0.45 for each increase in self-concept score.

lmerTest::rand(model.1)
## ANOVA-like table for random-effects: Single term deletions
## 
## Model:
## math ~ self_concept + (1 | class) + (1 | school)
##              npar logLik   AIC     LRT Df Pr(>Chisq)    
## <none>          5 -24480 48970                          
## (1 | class)     4 -24622 49253 284.956  1  < 2.2e-16 ***
## (1 | school)    4 -24525 49059  90.916  1  < 2.2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

#Adding L2 Predictor(s)

model.2 <- lmer(math ~ self_concept + class_type + degree + (1|class) + (1|school), REML=FALSE, data=star.clean)
summary(model.2)
## Linear mixed model fit by maximum likelihood  ['lmerMod']
## Formula: math ~ self_concept + class_type + degree + (1 | class) + (1 |  
##     school)
##    Data: star.clean
## 
##      AIC      BIC   logLik deviance df.resid 
##  48961.2  49025.9 -24470.6  48941.2     4746 
## 
## Scaled residuals: 
##     Min      1Q  Median      3Q     Max 
## -3.8266 -0.6442 -0.0610  0.5904  3.9341 
## 
## Random effects:
##  Groups   Name        Variance Std.Dev.
##  class    (Intercept)  252.1   15.88   
##  school   (Intercept)  407.1   20.18   
##  Residual             1551.2   39.39   
## Number of obs: 4756, groups:  class, 301; school, 73
## 
## Fixed effects:
##                                Estimate Std. Error t value
## (Intercept)                    467.9764     7.3642  63.547
## self_concept                     0.4363     0.1187   3.675
## class_typeREGULAR CLASS         -8.1748     2.7014  -3.026
## class_typeREGULAR + AIDE CLASS  -8.8767     2.6938  -3.295
## degreeMASTERS                    0.1572     2.7666   0.057
## degreeMASTERS +                 -5.2330     7.5361  -0.694
## degreeSPECIALIST                22.2608    13.2338   1.682
## 
## Correlation of Fixed Effects:
##             (Intr) slf_cn c_REGC c_R+AC dMASTE dMAST+
## self_concpt -0.906                                   
## c_REGULARCL -0.190  0.030                            
## c_REGULA+AC -0.188  0.026  0.475                     
## degrMASTERS -0.090 -0.018 -0.079 -0.075              
## dgrMASTERS+ -0.026 -0.012 -0.032  0.001  0.131       
## dSPECIALIST -0.040 -0.019  0.119  0.118  0.099  0.015

Intercept = predicted math score for a student w/ average self-concept, in a small class, and whose teacher has a Bachelor’s degree. Self-Concept = predicted math score increases by 0.44 for each increase in self-concept Regular Class = predicted math scores for students in a regular class are expected to be about 8.17 points lower than students’ scores in a small class. Regular + Aide Class = predicted math scores for students in a regular/aide class are expected to be about 8.88 points lower than students’ scores in a small class. Degree - Masters = predicted math scores for students whose teacher has a Master’s degree is expected to be about 0.16 points higher compared to students whose teacher has a Bachelor’s degree. not statistically significant difference though. Degree - Masters Plus = predicted math scores for students whose teacher has a Master’s degree + is expected to be about 5.23 points lower than students whose teacher has a Bachelor’s degree. not statistically significant difference Degree - Specialist = predicted math scores for students whose teacher has a Specialist degree are expected to be about 22.26 points higher compared to students whose teacher has a Bachelor’s degree. not statistically significant difference.

anova(model.1, model.2)
## Data: star.clean
## Models:
## model.1: math ~ self_concept + (1 | class) + (1 | school)
## model.2: math ~ self_concept + class_type + degree + (1 | class) + (1 | school)
##         npar   AIC   BIC logLik deviance  Chisq Df Pr(>Chisq)   
## model.1    5 48970 49002 -24480    48960                        
## model.2   10 48961 49026 -24471    48941 18.484  5   0.002397 **
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1

#Adding L3 Predictor(s)

model.3 <- lmer(math ~ self_concept + class_type + degree + math_school + (1|class) + (1|school), REML=FALSE, data=star.clean)
## boundary (singular) fit: see help('isSingular')
summary(model.3)
## Linear mixed model fit by maximum likelihood  ['lmerMod']
## Formula: math ~ self_concept + class_type + degree + math_school + (1 |  
##     class) + (1 | school)
##    Data: star.clean
## 
##      AIC      BIC   logLik deviance df.resid 
##  48768.2  48839.3 -24373.1  48746.2     4745 
## 
## Scaled residuals: 
##     Min      1Q  Median      3Q     Max 
## -3.7976 -0.6435 -0.0603  0.5904  4.0060 
## 
## Random effects:
##  Groups   Name        Variance Std.Dev.
##  class    (Intercept)  174.4   13.21   
##  school   (Intercept)    0.0    0.00   
##  Residual             1552.8   39.41   
## Number of obs: 4756, groups:  class, 301; school, 73
## 
## Fixed effects:
##                                 Estimate Std. Error t value
## (Intercept)                    -14.15268   22.09078  -0.641
## self_concept                     0.43544    0.11725   3.714
## class_typeREGULAR CLASS         -8.20633    2.35152  -3.490
## class_typeREGULAR + AIDE CLASS  -8.69961    2.35099  -3.700
## degreeMASTERS                   -0.33621    2.10936  -0.159
## degreeMASTERS +                 -2.37697    5.96377  -0.399
## degreeSPECIALIST                19.25123   10.64910   1.808
## math_school                      0.99386    0.04374  22.724
## 
## Correlation of Fixed Effects:
##             (Intr) slf_cn c_REGC c_R+AC dMASTE dMAST+ dSPECI
## self_concpt -0.274                                          
## c_REGULARCL -0.039  0.030                                   
## c_REGULA+AC -0.059  0.027  0.479                            
## degrMASTERS  0.019 -0.011 -0.072 -0.064                     
## dgrMASTERS+  0.021 -0.007 -0.021  0.000  0.114              
## dSPECIALIST  0.003 -0.008  0.101  0.101  0.054  0.021       
## math_school -0.951 -0.025 -0.019  0.002 -0.043 -0.030 -0.014
## optimizer (nloptwrap) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
help('isSingular')
## starting httpd help server ... done
anova(model.2, model.3)
## Data: star.clean
## Models:
## model.2: math ~ self_concept + class_type + degree + (1 | class) + (1 | school)
## model.3: math ~ self_concept + class_type + degree + math_school + (1 | class) + (1 | school)
##         npar   AIC   BIC logLik deviance  Chisq Df Pr(>Chisq)    
## model.2   10 48961 49026 -24471    48941                         
## model.3   11 48768 48839 -24373    48746 195.05  1  < 2.2e-16 ***
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
model.3b <- lmer(math ~ self_concept + class_type + math_school + (1|class) + (1|school), REML=FALSE, data=star.clean)
## boundary (singular) fit: see help('isSingular')
summary(model.3b)
## Linear mixed model fit by maximum likelihood  ['lmerMod']
## Formula: math ~ self_concept + class_type + math_school + (1 | class) +  
##     (1 | school)
##    Data: star.clean
## 
##      AIC      BIC   logLik deviance df.resid 
##  48765.7  48817.4 -24374.8  48749.7     4748 
## 
## Scaled residuals: 
##     Min      1Q  Median      3Q     Max 
## -3.7976 -0.6432 -0.0614  0.5883  3.9996 
## 
## Random effects:
##  Groups   Name        Variance Std.Dev.
##  class    (Intercept)  177     13.31   
##  school   (Intercept)    0      0.00   
##  Residual             1553     39.41   
## Number of obs: 4756, groups:  class, 301; school, 73
## 
## Fixed effects:
##                                 Estimate Std. Error t value
## (Intercept)                    -14.00052   22.18399  -0.631
## self_concept                     0.43628    0.11728   3.720
## class_typeREGULAR CLASS         -8.69083    2.34328  -3.709
## class_typeREGULAR + AIDE CLASS  -9.16379    2.34436  -3.909
## math_school                      0.99406    0.04389  22.647
## 
## Correlation of Fixed Effects:
##             (Intr) slf_cn c_REGC c_R+AC
## self_concpt -0.273                     
## c_REGULARCL -0.038  0.030              
## c_REGULA+AC -0.058  0.027  0.471       
## math_school -0.952 -0.026 -0.022  0.001
## optimizer (nloptwrap) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
model.3c <- lmer(math ~ math_school + (1|class) + (1|school), REML=FALSE, data=star.clean)
## boundary (singular) fit: see help('isSingular')
summary(model.3c)
## Linear mixed model fit by maximum likelihood  ['lmerMod']
## Formula: math ~ math_school + (1 | class) + (1 | school)
##    Data: star.clean
## 
##      AIC      BIC   logLik deviance df.resid 
##  60405.4  60438.8 -30197.7  60395.4     5866 
## 
## Scaled residuals: 
##     Min      1Q  Median      3Q     Max 
## -6.0261 -0.6306 -0.0617  0.5793  3.9863 
## 
## Random effects:
##  Groups   Name        Variance Std.Dev.
##  class    (Intercept)  193.7   13.92   
##  school   (Intercept)    0.0    0.00   
##  Residual             1613.2   40.16   
## Number of obs: 5871, groups:  class, 325; school, 79
## 
## Fixed effects:
##             Estimate Std. Error t value
## (Intercept)  0.84334   21.16579    0.04
## math_school  0.99926    0.04356   22.94
## 
## Correlation of Fixed Effects:
##             (Intr)
## math_school -0.999
## optimizer (nloptwrap) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
library(modelsummary)
library(broom.mixed)

models <- list(model.0, model.1, model.2, model.3)
modelsummary(models, output = "default")
Model 1 Model 2 Model 3 Model 4
(Intercept) 486.000 461.835 467.976 −14.153
(2.450) (7.143) (7.364) (22.091)
self_concept 0.452 0.436 0.435
(0.119) (0.119) (0.117)
class_typeREGULAR CLASS −8.175 −8.206
(2.701) (2.352)
class_typeREGULAR + AIDE CLASS −8.877 −8.700
(2.694) (2.351)
degreeMASTERS 0.157 −0.336
(2.767) (2.109)
degreeMASTERS + −5.233 −2.377
(7.536) (5.964)
degreeSPECIALIST 22.261 19.251
(13.234) (10.649)
math_school 0.994
(0.044)
SD (Intercept class) 16.958 16.846 15.877 13.205
SD (Intercept school) 19.386 19.893 20.176 0.000
SD (Observations) 40.155 39.383 39.386 39.405
Num.Obs. 5871 4756 4756 4756
R2 Marg. 0.000 0.002 0.012 0.249
R2 Cond. 0.292 0.306 0.307
AIC 60615.1 48968.4 48935.8 48751.2
BIC 60641.9 49000.7 49000.5 48822.3
ICC 0.3 0.3 0.3
RMSE 39.25 38.39 38.42 38.61

##Adding random slope for self-concept at both teacher and school levels

model_s_slp <- lmer(math ~ self_concept + class_type + degree + math_school + (self_concept|class) + (1|school), REML = FALSE, data = star.clean)
## Warning in checkConv(attr(opt, "derivs"), opt$par, ctrl = control$checkConv, :
## Model failed to converge with max|grad| = 2.477 (tol = 0.002, component 1)
## Warning in checkConv(attr(opt, "derivs"), opt$par, ctrl = control$checkConv, : Model is nearly unidentifiable: very large eigenvalue
##  - Rescale variables?;Model is nearly unidentifiable: large eigenvalue ratio
##  - Rescale variables?
summary(model_s_slp)
## Linear mixed model fit by maximum likelihood  ['lmerMod']
## Formula: 
## math ~ self_concept + class_type + degree + math_school + (self_concept |  
##     class) + (1 | school)
##    Data: star.clean
## 
##      AIC      BIC   logLik deviance df.resid 
##  48765.4  48849.5 -24369.7  48739.4     4743 
## 
## Scaled residuals: 
##     Min      1Q  Median      3Q     Max 
## -3.7930 -0.6469 -0.0626  0.5848  4.0115 
## 
## Random effects:
##  Groups   Name         Variance  Std.Dev. Corr 
##  class    (Intercept)  1.342e+03 36.63578      
##           self_concept 3.791e-01  0.61574 -0.93
##  school   (Intercept)  8.481e-04  0.02912      
##  Residual              1.543e+03 39.28519      
## Number of obs: 4756, groups:  class, 301; school, 73
## 
## Fixed effects:
##                                 Estimate Std. Error t value
## (Intercept)                    -14.03258   22.06256  -0.636
## self_concept                     0.43401    0.12478   3.478
## class_typeREGULAR CLASS         -8.17998    2.33708  -3.500
## class_typeREGULAR + AIDE CLASS  -8.67689    2.33564  -3.715
## degreeMASTERS                   -0.34328    2.09511  -0.164
## degreeMASTERS +                 -2.21733    5.92967  -0.374
## degreeSPECIALIST                19.37670   10.60322   1.827
## math_school                      0.99382    0.04346  22.866
## 
## Correlation of Fixed Effects:
##             (Intr) slf_cn c_REGC c_R+AC dMASTE dMAST+ dSPECI
## self_concpt -0.291                                          
## c_REGULARCL -0.040  0.031                                   
## c_REGULA+AC -0.060  0.028  0.480                            
## degrMASTERS  0.019 -0.009 -0.072 -0.064                     
## dgrMASTERS+  0.020 -0.006 -0.022 -0.001  0.114              
## dSPECIALIST  0.003 -0.008  0.101  0.101  0.053  0.021       
## math_school -0.945 -0.029 -0.019  0.002 -0.044 -0.029 -0.014
## optimizer (nloptwrap) convergence code: 0 (OK)
## Model failed to converge with max|grad| = 2.477 (tol = 0.002, component 1)
## Model is nearly unidentifiable: very large eigenvalue
##  - Rescale variables?
## Model is nearly unidentifiable: large eigenvalue ratio
##  - Rescale variables?
lmerTest::rand(model_s_slp)
## boundary (singular) fit: see help('isSingular')
## Warning in checkConv(attr(opt, "derivs"), opt$par, ctrl = control$checkConv, :
## Model failed to converge with max|grad| = 9.72245 (tol = 0.002, component 1)
## Warning in checkConv(attr(opt, "derivs"), opt$par, ctrl = control$checkConv, : Model is nearly unidentifiable: very large eigenvalue
##  - Rescale variables?
## ANOVA-like table for random-effects: Single term deletions
## 
## Model:
## math ~ self_concept + class_type + degree + math_school + (self_concept | class) + (1 | school)
##                                        npar logLik   AIC     LRT Df Pr(>Chisq)
## <none>                                   13 -24370 48765                      
## self_concept in (self_concept | class)   11 -24373 48768  6.7463  2    0.03428
## (1 | school)                             12 -24369 48763 -0.6240  1    1.00000
##                                         
## <none>                                  
## self_concept in (self_concept | class) *
## (1 | school)                            
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
models2 <- list(model.3, model_s_slp)
modelsummary(models2, output = "default")
Model 1 Model 2
(Intercept) −14.153 −14.033
(22.091) (22.063)
self_concept 0.435 0.434
(0.117) (0.125)
class_typeREGULAR CLASS −8.206 −8.180
(2.352) (2.337)
class_typeREGULAR + AIDE CLASS −8.700 −8.677
(2.351) (2.336)
degreeMASTERS −0.336 −0.343
(2.109) (2.095)
degreeMASTERS + −2.377 −2.217
(5.964) (5.930)
degreeSPECIALIST 19.251 19.377
(10.649) (10.603)
math_school 0.994 0.994
(0.044) (0.043)
SD (Intercept class) 13.205 36.636
SD (self_concept class) 0.616
Cor (Intercept~self_concept class) −0.935
SD (Intercept school) 0.000 0.029
SD (Observations) 39.405 39.285
Num.Obs. 4756 4756
R2 Marg. 0.249 0.230
R2 Cond. 0.310
AIC 48751.2 48748.4
BIC 48822.3 48832.5
ICC 0.1
RMSE 38.61 38.38
model_t_slp <- lmer(math ~ self_concept + class_type + degree + math_school + (1|class) + (self_concept|school), REML = FALSE, data = star.clean)
## boundary (singular) fit: see help('isSingular')
summary(model_t_slp)
## Linear mixed model fit by maximum likelihood  ['lmerMod']
## Formula: math ~ self_concept + class_type + degree + math_school + (1 |  
##     class) + (self_concept | school)
##    Data: star.clean
## 
##      AIC      BIC   logLik deviance df.resid 
##  48763.3  48847.4 -24368.7  48737.3     4743 
## 
## Scaled residuals: 
##     Min      1Q  Median      3Q     Max 
## -3.7525 -0.6472 -0.0606  0.5866  4.0302 
## 
## Random effects:
##  Groups   Name         Variance  Std.Dev. Corr 
##  class    (Intercept)   174.7269 13.2184       
##  school   (Intercept)  1553.6793 39.4167       
##           self_concept    0.4985  0.7061  -1.00
##  Residual              1539.9019 39.2416       
## Number of obs: 4756, groups:  class, 301; school, 73
## 
## Fixed effects:
##                                 Estimate Std. Error t value
## (Intercept)                    -14.26371   22.62614  -0.630
## self_concept                     0.41592    0.14666   2.836
## class_typeREGULAR CLASS         -8.26948    2.35719  -3.508
## class_typeREGULAR + AIDE CLASS  -8.67333    2.35483  -3.683
## degreeMASTERS                   -0.57631    2.11236  -0.273
## degreeMASTERS +                 -2.53788    5.97827  -0.425
## degreeSPECIALIST                19.53815   10.67695   1.830
## math_school                      0.99664    0.04377  22.769
## 
## Correlation of Fixed Effects:
##             (Intr) slf_cn c_REGC c_R+AC dMASTE dMAST+ dSPECI
## self_concpt -0.342                                          
## c_REGULARCL -0.039  0.027                                   
## c_REGULA+AC -0.058  0.023  0.480                            
## degrMASTERS  0.019 -0.011 -0.072 -0.064                     
## dgrMASTERS+  0.020 -0.005 -0.021 -0.001  0.114              
## dSPECIALIST  0.004 -0.010  0.100  0.101  0.052  0.021       
## math_school -0.928 -0.023 -0.019  0.002 -0.043 -0.030 -0.014
## optimizer (nloptwrap) convergence code: 0 (OK)
## boundary (singular) fit: see help('isSingular')
lmerTest::rand(model_t_slp)
## boundary (singular) fit: see help('isSingular')
## boundary (singular) fit: see help('isSingular')
## ANOVA-like table for random-effects: Single term deletions
## 
## Model:
## math ~ self_concept + class_type + degree + math_school + (1 | class) + (self_concept | school)
##                                         npar logLik   AIC     LRT Df Pr(>Chisq)
## <none>                                    13 -24369 48763                      
## (1 | class)                               12 -24458 48940 179.122  1    < 2e-16
## self_concept in (self_concept | school)   11 -24373 48768   8.831  2    0.01209
##                                            
## <none>                                     
## (1 | class)                             ***
## self_concept in (self_concept | school) *  
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
models3 <- list(model.3, model_t_slp)
modelsummary(models3, output = "default")
Model 1 Model 2
(Intercept) −14.153 −14.264
(22.091) (22.626)
self_concept 0.435 0.416
(0.117) (0.147)
class_typeREGULAR CLASS −8.206 −8.269
(2.352) (2.357)
class_typeREGULAR + AIDE CLASS −8.700 −8.673
(2.351) (2.355)
degreeMASTERS −0.336 −0.576
(2.109) (2.112)
degreeMASTERS + −2.377 −2.538
(5.964) (5.978)
degreeSPECIALIST 19.251 19.538
(10.649) (10.677)
math_school 0.994 0.997
(0.044) (0.044)
SD (Intercept class) 13.205 13.218
SD (Intercept school) 0.000 39.417
SD (self_concept school) 0.706
Cor (Intercept~self_concept school) −1.000
SD (Observations) 39.405 39.242
Num.Obs. 4756 4756
R2 Marg. 0.249 0.251
R2 Cond.
AIC 48751.2 48745.9
BIC 48822.3 48829.9
RMSE 38.61 38.36