Mar 6, 2016

Shrinkage (partial pooling) in multilevel models

unzipfile "output7717034280080927434.zip", replace
use cntry essround happy using ESS1-6e01_0_F1, clear

// Drastically reduce sample size
bysort cntry essround: keep if _n < 5

// Encode country variable
encode cntry, gen(country)

// Fit random intercept model
mixed happy || country: 
predict u0, reffects
predict u0se, reses

// Calculate posterior intercept
generate eb_happy = u0 + _b[_cons]

// Plot posterior intercept
preserve
egen pickone = tag(country)
keep if pickone
   
egen order_ = rank(-u0), unique
labmask order_, value(country) decode

gen high = u0 + _b[_cons] + (1.96 * u0se)
gen low  = u0 + _b[_cons] - (1.96 * u0se)
local avg =  _b[_cons]

twoway (rcap eb_happy eb_happy order_, dsymbol(x)) ///
       (rspike high low order_) , ///
        yline(`avg') xlabel(1/32, val ang(v)) ///
        xtitle("") ///
        ylabel(4/10) ///
        ytitle("Country-level residuals + intercept") ///
        legend(off) ///
        title("Random intercept model") ///
        name(emp_bayes, replace) nodraw
restore

// Fit OLS models
regress happy
local avg =  _b[_cons]
regress happy i.country
predict avg_happy
predict se_happy, stdp

// Plot OLS estimates
preserve
egen pickone = tag(country)
keep if pickone
   
egen order_ = rank(-avg_happy), unique
labmask order_, value(country) decode

gen high = avg_happy + (1.96 * se_happy)
gen low  = avg_happy - (1.96 * se_happy)

twoway (rcap avg_happy avg_happy order_, dsymbol(x)) ///
       (rspike high low order_) , ///
        yline(`avg') xlabel(1/32, val ang(v)) ///
        xtitle("") ///
        ylabel(4/10) ///
        ytitle("Country-level means") ///
        legend(off) ///
        title("OLS regression model") ///
        name(plain, replace) nodraw
restore

graph combine emp_bayes plain, col(1) ysize(8) name(combo, replace)


// Plot EB and OLS means against one another to illustrate 
// shrinkage in multilevel modeling

preserve
egen pickone = tag(country)
keep if pickone
twoway (scatter eb_happy avg_happy) ///
       (function y = x, range(0 10)), ///
    legend(off) xtitle("OLS estimates") ytitle("Posterior intercept") ///
    title("Shrinkage")
restore