*! Program to test for spatial autocorrelation in the residuals from OLS, IV, SAR, and IV-SAR models *! Author P. Wilner Jeanty *! Version 1.0 Born: Date October 17, 2008 *! Version 1.2 Updated January 2009 *! Version 1.3 January 2010: Test after spatial lag model estimated by ML added program define anketest, rclass version 9.2 if "`e(cmd)'"=="" { di di as err "The model has not been estimated. Please estimate a model" exit 301 } else if !inlist("`e(cmd)'", "ivregress", "ivreg29", "regress", "spmlreg") { di di as err "ANKETEST does not work after the `e(cmd)' command" exit 198 } if ("`e(cmd)'"=="spmlreg" & "`e(title)'"!="Spatial Lag Model") { di di as err "ANKETEST does not work after a `e(title)'" exit 198 } syntax, Wname(str) WFrom(str) model(str) [favor(str)] if !inlist("`wfrom'", "Stata", "Mata") { di di as err "Either Stata or Mata must specified with the {bf:wfrom()} option" exit 198 } if !inlist("`model'", "ols", "iv", "sar", "iv-sar") { // sar if for both ML-sar and IV-sar di di as err "One of {bf:ols}, {bf:iv}, {bf:sar}, and {bf:iv-sar} must be specified with the {bf:model()} option" exit 198 } if "`model'"=="ols" & "`e(cmd)'"!="regress" { di as err "An OLS model was not estimated" exit 301 } if inlist("`model'", "iv", "iv-sar") & !inlist("`e(cmd)'", "ivregress", "ivreg29") { di as err "An iv or iv-sar model was not estimated" exit 301 } if "`model'"=="sar" & !inlist("`e(cmd)'", "ivregress", "ivreg29", "spmlreg") { di as err "A SAR model was not estimated either by ML or spatial 2SLS" exit 301 } if "`favor'"!="" & inlist("`favor'", "space", "speed")==0 { di as err " Option {bf:favor(`favor')} not allowed" exit 198 } mata: anketest_lagml=0 local sarml=0 if "`e(cmd)'"== "spmlreg" & "`e(title)'"== "Spatial Lag Model" { local rho_cons=[rho]_cons local Vrho=([rho]_se[_cons])^2 local sigma_cons=[sigma]_cons mata: anketest_rho=`rho_cons'; anketest_Vrho=`Vrho'; anketest_sigma=`sigma_cons'; anketest_lagml=1; anketest_W1="`e(wname)'" local sarml=1 local wname1 `e(wname)' local wfrom1 `e(wfrom)' local depv "`e(depvar)'" } tempvar resreg if `sarml' { tempvar yhat wy qui predict `yhat' qui gen double `wy'=. mata: wm=Anketest_ReadWght("wfrom1", "wname1"); st_view(y=., ., st_local("depv")); ylag=wm*y; st_store(., st_local("wy"), ylag) qui replace `yhat'=`yhat'+ [rho]_b[_cons]*`wy' qui gen double `resreg'=`depv'-`yhat' } else predict `resreg', res if "`model'"!="ols" { local inst "`e(insts)'" local insted "`e(instd)'" } else if "`model'"=="ols" { tempname bmat bmatshort mat `bmat'=e(b) local col=colsof(`bmat') mat `bmatshort'=`bmat'[1,1..`col'-1] local xvs : colnames(`bmatshort') local depv "`e(depvar)'" } if "`favor'"=="" & c(matafavor)=="space" mata: mata set matafavor speed if "`favor'"=="speed" & c(matafavor)=="space" mata: mata set matafavor speed if "`favor'"=="space" & c(matafavor)=="speed" mata: mata set matafavor space mata: Anketest_CalcStat() matlist testres, nob row(Tests) title("`title'") cspec(| b %16s | %10.2f & %7.4f |) `rspec' if `sarml' di as txt "*: Test based on maximum likelihood estimation of Rho and Sigma" return matrix Diagmat=testres end version 9.2 mata: mata drop *() mata set matastrict on void Anketest_CalcStat() { external real scalar anketest_rho, anketest_Vrho, anketest_lagml, anketest_sigma external string scalar anketest_W1, anketest_wfrom external real colvector y st_view(e=., ., st_local("resreg")); n=rows(e) model=st_local("model") if (model=="ols") { st_view(y=., ., st_local("depv")) st_view(x=., ., tokens(st_local("xvs"))); x=x,J(n,1,1) } else if (anketest_lagml==0) { st_view(exog=., ., tokens(st_local("inst"))) st_view(endog=., ., tokens(st_local("insted"))) } w=Anketest_ReadWght("wfrom", "wname") // Mata learners: here I pass onto Mata the names of the macros rather than their contents t2= trace(w, w) + trace(w, w, 1) // =trace((w*w)+(w'*w)) if (anketest_lagml==1) { // SAR estimated by ML if (st_local("wname")==anketest_W1) W1=w else W1=Anketest_ReadWght("wfrom1", "wname1") // user specifies a weights matrix different from the one used for the spatial lag model InvA=luinv(I(n)-anketest_rho*W1) w2w1=w*W1; w1A=W1*InvA T21A=trace(w2w1, InvA) + trace(w, w1A, 1) // trace(w*w1*invA + w'*w1*invA) where w2=w TD=(t2 - T21A*T21A*anketest_Vrho) sigma2=anketest_sigma^2 // to save some computing time esigma=e'*w*y/sigma2 } else { ee=quadcross(e, e) // for ee=e'*e sigma2=ee/n // this is equal to sigma^2, where sigma is estimated directly by ML in the lag model ewe=e'*w*e esigma=ewe/sigma2 } if (model=="iv" | model=="sar" | model=="ols") { if (anketest_lagml==0) LM_err=(esigma^2)/t2 else LM_err=(esigma^2)/TD pLM_err=chi2tail(1,LM_err) } if (model=="ols") { // LM_lag test ewy=e'*w*y px=x*invsym(quadcross(x, x))*x' b=st_matrix(st_local("bmat")) wxb=w*x*b' D=(wxb'*(I(n)-px)*wxb)/sigma2 + t2 invD=1/D LM_lag=invD*(ewy/sigma2)^2 pLM_lag=chi2tail(1,LM_lag) // robust LM_err RLM_err=((esigma-t2*invD*ewy/sigma2)^2)/(t2-t2*t2*invD) pRLM_err=chi2tail(1,RLM_err) // Robust LM_lag RLM_lag=(((ewy/sigma2)-esigma)^2)/(D-t2) pRLM_lag=chi2tail(1,RLM_lag) // Moran's I for OLS MI=ewe/ee k=cols(x) m=I(n)-px s=sum(w) I=(n/s):*MI d=(n-k):*(n-k+2) M1=quadcross(m', w); M2=quadcross(m', w') // M1=m*w; M2=m*w' t1=trace(m, w) t3=trace(M1, M1) // trace(m*w*m*w) ex=(n/s)*t1/(n-k) vi=((n/s)^2)*(trace(M1, M2)+ t3+ t1*t1)/d vi=vi-ex*ex zi=(I-ex)/sqrt(vi) // Moran's I z-score pMI=(1-normal(abs(zi)))*2 // p-value for two-tailed test } if (model=="iv-sar" | (model=="sar" & !anketest_lagml) | model=="iv") { MI=ewe/ee // Moran's I for models with endogenous regressors and/or spatially lagged dependent variable if (model=="iv-sar") { z1=exog,endog x=exog,J(rows(z1), 1, 1) px=x*invsym(quadcross(x, x))*x' a1=(e'*w*z1)/n a2=n*invsym(z1'*px*z1) a3=(1/n)*(z1'*w'*e) A=a1*a2*a3 } if (model=="iv" | model=="sar") A=0 // According to Anselin and Kelejian (1997) s1=sum(w)/n; s2=t2/n phi2=s2/(2*s1^2) + A*(4/s1^2*sigma2); MI_z=(sqrt(n)*MI)/sqrt(phi2) pmiz=(1-normal(abs(MI_z)))*2 } // Now reporting if (model=="ols") { st_local("rspec", "rspec(--&&&&-)") st_local("title", "Tests for Spatial Autocorrelation in the OLS Model residuals") olsres=zi,pMI\LM_err, pLM_err\RLM_err, pRLM_err\LM_lag, pLM_lag\RLM_lag, pRLM_lag st_matrix("testres", olsres) st_matrixrowstripe("testres", ("", "Moran's_I"\"", "LM_Error"\"", "Robust_LM_Error"\"", "LM_Lag"\"", "Robust_LM_Lag")) st_matrixcolstripe("testres", ("", "Statistic"\"", "P-Value")) } if (model=="iv") { st_local("rspec", "rspec(--&-)") st_local("title", "Tests for Spatial Autocorrelation in the IV-Model Residuals") fsres=MI_z,pmiz\LM_err, pLM_err st_matrix("testres", fsres) st_matrixrowstripe("testres", ("", "IV_Moran's_I"\"", "IV_LM_Error")) st_matrixcolstripe("testres", ("", "Statistic"\"", "P-Value")) } if (model=="sar" & anketest_lagml==0) { st_local("rspec", "rspec(--&-)") st_local("title", "Tests for Spatial Autocorrelation in the SAR Model Residuals") sar_res=MI_z,pmiz\LM_err, pLM_err st_matrix("testres", sar_res) st_matrixrowstripe("testres", ("", "Moran's_I"\"", "LM_Error")) st_matrixcolstripe("testres", ("", "Statistic"\"", "P-Value")) } if (model=="sar" & anketest_lagml==1) { st_local("rspec", "rspec(---)") st_local("title", "Tests for Spatial Autocorrelation in the SAR (ML) Model Residuals") mlsar_res=LM_err,pLM_err st_matrix("testres", mlsar_res) st_matrixrowstripe("testres", ("","LM_Error*")) st_matrixcolstripe("testres", ("", "Statistic"\"", "P-Value")) } if (model=="iv-sar") { st_local("rspec", "rspec(---)") st_local("title", "Tests for Spatial Autocorrelation in the IV_SAR Model Residuals") endsar_res=MI_z,pmiz st_matrix("testres", endsar_res) st_matrixrowstripe("testres", ("","IV_Moran's_I")) st_matrixcolstripe("testres", ("", "Statistic"\"", "P-Value")) } "" stata(`"di as txt "{title:Diagnostic tests for Spatial Dependence}""'); "" } real matrix Anketest_ReadWght(string scalar A_from, string scalar A_wname) { if (st_local(A_from)=="Mata") { if (!fileexists(st_local(A_wname))) { "" errprintf("File %s not found\n", st_local(A_wname)) exit(601) } else { fh = fopen(st_local(A_wname), "r") // get the weights matrix from a Mata file wmat=fgetmatrix(fh) fclose(fh) } } else { // get the weights matrix from Stata wmat=st_matrix(st_local(A_wname)) if (cols(wmat)==0 | rows(wmat)==0) { "" errprintf("Matrix %s not found\n", st_local(A_wname)) exit(601) } } return(wmat) } end