Showing posts with label xtmixed. Show all posts
Showing posts with label xtmixed. Show all posts

Sep 1, 2015

Making -mixed- tables via -esttab-

// Fit a couple of models

// Model 1
eststo clear
eststo: xtmixed wellbeing || cluster: , ml var
qui estadd scalar dev = -2*e(ll) // Deviance
qui matrix foo = e(N_g)          // Number of level 2 units
qui estadd scalar nc  = foo[1,1] // Number of level 2 units
qui estadd scalar v1  = exp(2*[lns1_1_1]_b[_cons])     // Intercept variance
qui estadd scalar v_e = exp(2*[lnsig_e]_b[_cons])     // Residual variance

// Model 2
eststo: xtmixed wellbeing hourscgm || cluster: hourscgm, ml var cov(uns)
qui estadd scalar dev = -2*e(ll) // Deviance
qui matrix foo = e(N_g)          // Number of level 2 units
qui estadd scalar nc  = foo[1,1] // Number of level 2 units
qui estadd scalar v2  = exp(2*[lns1_1_1]_b[_cons])     // Slope variance
qui estadd scalar v1  = exp(2*[lns1_1_2]_b[_cons])     // Intercept variance
qui estadd scalar cov = tanh([atr1_1_1_2]_b[_cons]) * /// Slope-intercept covariance
                        exp([lns1_1_1]_b[_cons])  * ///
                        exp([lns1_1_2]_b[_cons])
qui estadd scalar v_e = exp(2*[lnsig_e]_b[_cons])     // Residual variance

// Model 3
eststo: xtmixed wellbeing hourscwc || cluster: hourscwc, ml var cov(uns)
qui estadd scalar dev = -2*e(ll) // Deviance
qui matrix foo = e(N_g)          // Number of level 2 units
qui estadd scalar nc  = foo[1,1] // Number of level 2 units
qui estadd scalar v2  = exp(2*[lns1_1_1]_b[_cons])     // Slope variance
qui estadd scalar v1  = exp(2*[lns1_1_2]_b[_cons])     // Intercept variance
qui estadd scalar cov = tanh([atr1_1_1_2]_b[_cons]) * /// Slope-intercept covariance
                        exp([lns1_1_1]_b[_cons])  * ///
                        exp([lns1_1_2]_b[_cons])
qui estadd scalar v_e = exp(2*[lnsig_e]_b[_cons])     // Residual variance

// Model 4
eststo: xtmixed wellbeing sizecgm hourscgm || cluster: hourscgm, ml var cov(uns)
qui estadd scalar dev = -2*e(ll) // Deviance
qui matrix foo = e(N_g)          // Number of level 2 units
qui estadd scalar nc  = foo[1,1] // Number of level 2 units
qui estadd scalar v2  = exp(2*[lns1_1_1]_b[_cons])     // Slope variance
qui estadd scalar v1  = exp(2*[lns1_1_2]_b[_cons])     // Intercept variance
qui estadd scalar cov = tanh([atr1_1_1_2]_b[_cons]) * /// Slope-intercept covariance
                        exp([lns1_1_1]_b[_cons])  * ///
                        exp([lns1_1_2]_b[_cons])
qui estadd scalar v_e = exp(2*[lnsig_e]_b[_cons])     // Residual variance

// Model 5
eststo: xtmixed wellbeing sizecgm hourscwc || cluster: hourscwc, ml var cov(uns)
qui estadd scalar dev = -2*e(ll) // Deviance
qui matrix foo = e(N_g)          // Number of level 2 units
qui estadd scalar nc  = foo[1,1] // Number of level 2 units
qui estadd scalar v2  = exp(2*[lns1_1_1]_b[_cons])     // Slope variance
qui estadd scalar v1  = exp(2*[lns1_1_2]_b[_cons])     // Intercept variance
qui estadd scalar cov = tanh([atr1_1_1_2]_b[_cons]) * /// Slope-intercept covariance
                        exp([lns1_1_1]_b[_cons])  * ///
                        exp([lns1_1_2]_b[_cons])
qui estadd scalar v_e = exp(2*[lnsig_e]_b[_cons])     // Residual variance

// Create table via -esttab-
esttab est1 est2 est3 est4 est5 ///
     , se ///
       stats(v1 v2 v_e cov dev nc N, ///     Add variance components to table
             labels("Var(Intercept)" ///
                    "Var(Slope)" ///
                    "Var(Residual)" ///
                    "Cov(Int., Slope)" ///
                    "Deviance" ///
                    "No. clusters" ///
                    "No. individuals")) ///
        label ///                             Use variable labels
        keep(wellbeing:)                  // Drop variance components in weird shapes


// Give it another go
esttab est1 est2 est4 est3 est5 ///
     , se ///
       stats(v1 v2 v_e cov dev nc N, ///
             labels("Var(Intercept)" ///
                    "Var(Slope)" ///
                    "Var(Residual)" ///
                    "Cov(Int., Slope)" ///
                    "Deviance" ///
                    "No. clusters" ///
                    "No. individuals")) ///
       rename(hourscwc hours hourscgm hours) ///  Match up both hour variables
       varlabels(hours "Work hours (CGM/CWC)" /// Relabel variables
                 sizecgm "Workgroup size (CGM)" ///
                 _cons "Constant") ///
       wrap ///                                   Wrap variable labels
       mgroups("Null model" ///
               "Work hours CGM" ///               Group models
               "Work hours CWC", pattern(1 1 0 1 0) span) ///
       eqlabels("") ///                           Suppress equation label
       nomtitle ///                               Suppress model titles
       keep(wellbeing:)  //                       Drop weird variance components


Aug 31, 2015

Modeling variance functions

version 12.1
set more off

// Open National Longitudinal Survey (Young women 14-26 years of age in 1968)
webuse nlswork, clear
// Level 1: annual measurement
// Level 2: young women

// Null model
xtmixed ln_w || id: , var
xtmrho // VPC in random intercept case w/out covariates equals ICC

// Prepare level-1 covariate
center tenure, replace
label var tenure "Job tenure (years)"

// Add level-1 covariate
xtmixed ln_w tenure || id: , var
xtmrho // VPC after adjusting for a covariate

// 1) Constant variance

// Create variables: constant variance function at level 2
gen lev2var = e(var_u1)
label var lev2var "Variance at level 2"

// Create variables: constant variance function at level 1
gen lev1var = e(var_e)
label var lev1var "Variance at level 1"

// Create variable: predicted values
predict fit, xb

// Create variables: constant bounds for between-neighborhood variation
gen lev2cbhi = fit + 1.96*(lev2var^.5)
gen lev2cblo = fit - 1.96*(lev2var^.5)
label var fit      "Fixed relationship"
label var lev2cbhi "Upper bound between-person variation"
label var lev2cblo "Lower bound between-person variation"

// Graphs: Heterogeneity as a constant function
qui twoway (line lev2var tenure, sort) ///
           (line lev1var tenure, sort) ///
           , legend(ring(0) pos(5)) ///
             ylabel(.085 (.01) .12,format(%6.3f)) ///
             ytitle("Variance") ///
             name(variancefunction1, replace)
  
qui twoway (line fit lev2cbhi lev2cblo tenure, sort) ///
           , legend(ring(0)) ///
             ylabel(1 (.5) 3,format(%6.1f)) ///
             ytitle("Predicted log wage") ///
             name(betweenperson1, replace)
    
graph combine variancefunction1 between1
            , col(1) ysize(8) xcommon ///
              title("Random intercept model") ///
              name(constantvariance, replace)

// Clean up
drop lev2var lev1var fit lev2cbhi lev2cblo

// Add random slope to model
xtmixed ln_w tenure || id: tenure, var cov(uns)
xtmrho // VPC after adjusting for a covariate and random slope

// 2) Quadratic variance
   // Getting at the covariance parameter 
   // and slope variation as
   // -xtmrho- hasn't stored it in a better format
local cov      = tanh([atr1_1_1_2]_b[_cons])* exp([lns1_1_1]_b[_cons])* exp([lns1_1_2]_b[_cons])
di `cov' 
local var_tenure = exp([lns1_1_1]_b[_cons])^2
   // In order to get the other variance components
   // without -xtmrho-, one needs:
   *local var_cons = exp([lns1_1_2]_b[_cons])^2    // Intercept variance
   *local var_res  = exp([lnsig_e]_b[_cons])^2     // Residual variance

// Create variables: quadratic variance function at level 2
gen lev2var = e(var_u1) ///
            + 2 * `cov' * tenure ///
   + `var_tenure' * tenure * tenure
label var lev2var "Variance function at level 2"

// Create variable: predicted values
predict fit, xb

// Create variables: quadratic bound bounds for between-neighborhood variation
gen lev2cbhi = fit + 1.96*(lev2var^.5)
gen lev2cblo = fit - 1.96*(lev2var^.5)
label var fit      "Fixed relationship"
label var lev2cbhi "Upper bound between-person variation"
label var lev2cblo "Lower bound between-person variation"

// Graphs: Heterogeneity as a quadratic function
qui twoway (line lev2var tenure, sort) ///
           , legend(ring(0)) ///
             ytitle("Variance") ///
             ylabel(, format(%6.3f)) ///
             legend(ring(0) pos(11)) ///
             name(variancefunction2, replace)
qui twoway (line fit lev2cbhi lev2cblo tenure, sort) ///
           , legend(ring(0) pos(11)) ///
             name(betweenperson2, replace)

qui graph combine variancefunction2 betweenperson2, ///
                  , col(1) xcommon name(quadraticvariance, replace) ///
                    title("Random coefficient model")
   
graph combine constantvariance quadraticvariance, row(1) xsize(12) ysize(8)

// Clean up
drop lev2var fit lev2cbhi lev2cblo


Jul 22, 2013

Random graphs (15): Caterpillar plots

use http://www.ats.ucla.edu/stat/examples/imm/imm23, clear
// Data from Kreft and De Leeuw (1998: 58)

xtmixed math || schid:, var

predict means1, reffects 
predict means1se, reses

egen pickone = tag(schid)

sort means1
egen means1rank = rank(means1) if pickone == 1

serrbar means1 means1se means1rank if pickone == 1, ///
        scale(1.96) yline(0) xlabel(none) ///
        xtitle("Schools") ytitle("School effects on math scores") ///
        title("Null model") ///
        name(means1, replace)

xtmixed math meanses public ratio || schid:, var

predict means2, reffects 
predict means2se, reses

serrbar means2 means2se means1rank if pickone == 1, ///
        scale(1.96) yline(0) xlabel(none) ///
        xtitle("Schools") ytitle("School effects on math scores") ///
 title("After controlling for average SES, school type, ///
        and student–teacher ratio") ///
        name(means2, replace)
  
graph combine means1 means2, ycommon xcommon col(1) 

 

Reference

Kreft, Ita, and Jan De Leeuw. 1998. Introducing Multilevel Modeling. Sage.

Aug 8, 2012

R-squared for linear multilevel models

Explained variance in multilevel modeling is an issue that strongly differs from explained variance in single-level OLS regression. Whereas OLS regression comes with the long-established coefficient of determination R2, matters are somewhat more complicated in multilevel modeling.

Hierarchical models partition the total variance into several components, thus matters become more complex. Several pseudo-R2 coefficients have been proposed, the most popular being probably A) one that builds on proportional reductions in variance and B) one that builds on proportional reductions in prediction error.

The straightforward approach that treats reductions in variance components (e.g. `sigma_(u0)^2` and `sigma_(e0)^2`) as increases in explained variance has been suggested by Raudenbush and Bryk (2002) or Singer and Willett (2003). The random intercept model without any explanatory variables (the "null model") provides two variance components which are then interpreted as unexplained variance at the individual (`sigma_(e0)^2`) and the higher-order (`sigma_(u0)^2`) level. Once explanatory variables are introduced to the model, the variance components change in value, thus a simple calculation along the lines of

`R^2 = ((sigma_(e0|b)^2 - sigma_(e0|m)^2)/ sigma_(e0|b)^2)`

`sigma_(e0|b)^2` refers to the lower-level residual variance of the baseline model, `sigma_(e0|m)^2` denotes the said parameter estimate in the model that includes explanatory variables. (This notation is taken from Hox 2010, p. 71.)

While this seems to be a straightforward approach, several complications and differences from OLS regression arise: Firstly, we obtain more than one single R2-value; instead we have one value per level/variance component. Secondly, adding predictor variables can lead to reductions in explained variance and even to negative R2-values. This is often observed when a null model is compared to a model that includes only group mean-centered predictor variables. Snijders and Bosker (1994) give a detailed account of situations when higher-level variance components go up in value when lower-level predictors are added to the equation. Thirdly, the situation gets even more complicated when random slopes are added to the model. Hox (2010, p.73) gives an example for this case and stresses the importance of centering in multilevel modeling.

Snijders and Bosker (1994) have suggested a way to calculate a pseudo-R2 via proportionate reductions in prediction error to overcome the second shortcoming: Explained variance should not increase when predictors are added to the model. In order to achieve this, they focus on the total estimated variance `sigma_(u0)^2 + sigma_(e0)^2` for calculating their pseudo-R2's. Snijders and Bosker calculate the level-1 coefficent as follows:

`R_1^2 = 1 - ((sigma_(u0|m)^2 + sigma_(e0|m)^2))/((sigma_(u0|b)^2 + sigma_(e0|b)^2))`
and the level-2 coefficient in the following fashion:
`R_2^2 = 1 - (((sigma_(u0|m)^2)/(n_j) + sigma_(e0|m)^2))/(((sigma_(u0|b)^2)/(n_j) + sigma_(e0|b)^2))`

Where `n_j` stands for average group size (Snijders and Boskers recommend using the harmonic mean).

Alexander Schmidt and Katja Möhring have released the mlt package comprising several multilevel tools, enabling users to calculate both the Bosker & Snijders (1994) and Raudenbush & Bryk pseudo-R2's after xtmixed using their command mltrsq. The package cannot be found on SSC, but needs to be downloaded here.

A brief test:

webuse pisa2000.dta, clear
xtmixed isei female high_school college one_for both_for test_lang pass_read ///
             || id_school:, var
mltrsq, full

gives the following results:

Level 2 variable is id_school 
 
Calculating R-squared for the parameters of
 female high_school college one_for both_for test_lang pass_read and _cons
   
Level 2 variable is id_school
   
Number of macro-units:   148
   
Harmonic mean of the level-2 group sizes:  8.29
   
Random-effects Parameters of complete model:  
   Residual-varianz level 1: 222.3588
   Residual-varianz level 2: 24.7574
   
Random-effects Parameters of Null-model:  
   Residual-varianz level 1: 259.0281
   Residual-varianz level 2: 51.7011
   
   
Snijders/Bosker R-squared Level 1:  0.2047
Snijders/Bosker R-squared Level 2:  0.3782
   
Bryk/Raudenbush R-squared Level 1:  0.1416
Bryk/Raudenbush R-squared Level 2:  0.5211

Differences between the two approaches seem sizable; however, given the fact that our example only draws on level-1 predictors, this is a rather extreme case. But in general I have a feeling that Kreft and De Leeuw (1998, p. 119) are correct in their suggestion not to use any pseudo-R2's in multilevel modeling.

Roberts et al. (2011) however suggest three new measures of explained variance in multilevel models which are not yet readily implemented in any Stata commands.

References


Kreft, Ita, and Jan de Leeuw. 1998. Introducing Multilevel Modeling. Sage.

Raudenbush, Stephen W., and Anthony S. Bryk. 2002. Hierarchical Linear Models. Applications and Data Analysis Methods, 2nd ed. Sage.

Roberts, J. Kyle, James P. Monaco, Holly Stovall, and Virginia Foster. 2011. "Explained Variance in Mulitlevel Models." Pp. 219-230 in Handbook of Advanced Multilevel Analysis, edited by Joop J. Hox and J. Kyle Roberts. Routledge.

Singer, Judith D., and John B. Willett. 2003. Applied Longitudinal Data Analysis. Modeling Change and Event Occurrence. Oxford University Press. doi: 10.1093/acprof:oso/9780195152968.001.0001

Snijders, Tom, and Roel Bosker. 1994. "Modeled Variance in Two-Level Models." Sociological Methods and Research 22(3):342-363. doi: 10.1177/0049124194022003004

Snijders, Tom, and Roel Boskers. 1999. Multilevel Analysis. An Introduction to Basic and Advanced Multilevel Modeling. Sage.