In his concise introduction to multilevel modeling,
Twisk (2006) has a chapter on multivariate multilevel modeling using
MLwiN (Rasbash et al. 2012). Multivariate models here refer to models that have more than one dependent variable. Indeed, MLwiN makes it easier than Stata 12 to fit models with more than one outcome; however, in many respects MLwiN is not the most user-friendly of all the statistical software packages. The command package
-runmlwin- (Leckie and Charlton 2013) allows to run MLwiN within the comfort of your Stata installation and, in my opinion, has the potential to make MLwiN useable for large-scale data analysis. (The user support for -runmlwin-, by the way, is also quick and competent.)
Here, I am presenting the Stata code necessary to fit the models in
Chapter 7 of Twisk (2006) using -runmlwin-. The data for the chapter are available
here.
// Define MLwiN path
global MLwiN_path C:\Program Files\MLwiN v2.27\i386\mlwin.exe
// Section 7.2: "Multivariate multilevel analysis: the MLwiM approach"
// (MLwiN approach = wide data format)
// Read in wide format data
insheet total_cholesterol systolic_blood_pressure medical_doctor age id ///
using "D:\twisk data sets\multivariate.dat", clear
// Table 7.1
// Table in book doesn't seem to be super-accurate
list id total_cholesterol systolic_blood_pressure medical_doctor age in 1/3
// Generate constant
gen cons = 1
// Output 7.2
// - Single-level multivariate HLM model
// - Random effects parameters are partitioned residual
// variance only, not random intercepts
runmlwin (total_cholesterol cons age, eq(1)) ///
(systolic_blood_pressure cons age, eq(2)), ///
level1(id: (cons, eq(1)) (cons, eq(2))) nopause
// Output 7.3
// - Single-level univariate model for one outcome
runmlwin total_cholesterol cons age, level1(id: cons) nopause
// Output 7.4
// - Single-level univariate model for other outcome
runmlwin systolic_blood_pressure cons age, level1(id: cons) nopause
// Output 7.5
// - Single-level MANCOVA
quietly manova total_cholesterol systolic_blood_pressure = c.age
mvreg
// Output 7.6
// - Single-level multivariate HLM model
// - age coefficients constrained to be equal
// Approach via externally defining a constraint
constraint def 1 [FP1]age = [FP2]age
runmlwin (total_cholesterol cons age, eq(1)) ///
(systolic_blood_pressure cons age, eq(2)), ///
level1(id: (cons, eq(1)) (cons, eq(2))) ///
constraints(1) ///
nopause
// Output 7.6
// - Single-level multivariate HLM model
// - age coefficients constrained to be equal
// Approach via constraining in runmlwin
runmlwin (total_cholesterol cons, equation(1)) ///
(systolic_blood_pressure cons, equation(2)) ///
(age, equation(1/2)) ///
, ///
level1(id: (cons, equation(1)) (cons, equation(2))) ///
nosort nopause
// Output 7.7
// - Multilevel multivariate HLM model
// - Age coefficients constrained to be equal
// - Random intercepts for different doctors
// Approach via constraining in runmlwin
runmlwin (total_cholesterol cons, eq(1)) ///
(systolic_blood_pressure cons, eq(2)) ///
(age, equation(1/2)) ///
, ///
level1(id: (cons, eq(1)) (cons, eq(2))) ///
level2(medical_doctor: (cons, eq(1)) (cons, eq(2))) ///
nosort nopause
// Output 7.8
// - Multilevel multivariate HLM model
// - Age coefficients constrained to be equal
// - Random intercepts for different doctors
// - Random slope for age coefficient
// Approach via constraining in runmlwin
runmlwin (total_cholesterol cons, eq(1)) ///
(systolic_blood_pressure cons, eq(2)) ///
(age, equation(1/2)) ///
, ///
level1(id: (cons, eq(1)) (cons, eq(2))) ///
level2(medical_doctor: (cons, eq(1)) (cons, eq(2)) (age, eq(1/2))) ///
nosort nopause
// Section 7.3: "Multivariate multilevel analysis: the general approach"
// (general approach = long data format)
// Read in long format data set
insheet z_outcome medical_doctor age variable id ///
using "D:\twisk data sets\multivariate_z.dat", clear
// Table 7.2
// Table in book doesn't seem to be super-accurate
list id z_outcome medical_doctor age variable in 1/4
// Generate constant
gen cons = 1
// Output 7.10
// - Random intercept at doctor level
runmlwin (z_outcome cons age), ///
level1(variable: cons) ///
level2(id: cons) nopause
// Output 7.11
// - Random intercept at doctor level
runmlwin (z_outcome cons age), ///
level1(variable: cons) ///
level2(id: cons) ///
level3(medical_doctor: cons) ///
nopause
// Output 7.12
// - Random intercept at doctor level
// - Random intercept at patient level
// - Random slope for age at patient level
runmlwin (z_outcome cons age), ///
level1(variable: cons) ///
level2(id: cons age) ///
level3(medical_doctor: cons) ///
nopause
// Output 7.13
// - Random intercept at doctor level
// - Random intercept at patient level
// - Random slope for age at doctor level
runmlwin (z_outcome cons age), ///
level1(variable: cons) ///
level2(id: cons) ///
level3(medical_doctor: cons age) ///
nopause
// Section 7.4 "Comments"
// Covert to wide format
reshape wide z_outcome, i(id) j(variable)
rename z_outcome1 total_cholesterol
rename z_outcome2 systolic_blood_pressure
// Output 7.14
// - Random intercept at doctor level
// - Random intercept at patient level
// - Random slope for age at doctor level
// Estimated via the "MLwiN approach"
runmlwin (total_cholesterol cons, eq(1)) ///
(systolic_blood_pressure cons, eq(2)) ///
(age, eq(1/2)) ///
, ///
level1(id: (cons, eq(1)) (cons, eq(2))) ///
level2(medical_doctor: (cons, eq(1)) (cons, eq(2)) (age, eq(1/2))) ///
nopause
References
Leckie, George, and Chris Charlton. 2013. "runmlwin. A Program to Run the MLwiN Multilevel Modeling Software from within Stata."
Journal of Statistical Software 52(11):1-40.
Rasbash, John, Fiona Steele, William J. Browne, and Harvey Goldstein. 2012.
A User's Guide to MLwiN Version 2.26. Center for Multilevel Modeling, University of Bristol.
Twisk, Jos W. R. 2006.
Applied Multilevel Analysis. A Practical Guide. Cambridge University Press. doi: 10.1017/CBO9780511610806