program define sregress, eclass * S-regression fit * By Vincenzo Verardi FNRS-FUNDP and Christophe Croux version 10.0 if replay()& "`e(cmd)'"=="sregress" { ereturn display exit } syntax varlist [if] [in] , [outlier replic(numlist max=1) NOConstant graph ] tempvar rand yres touse u u0 w rho psi weight tcand bestw res stdres ord continuous dv v ivs tempconst tempu tempmad tempname mad mad2 bestmad bestmrho mrho scale eps maxit err v B coefS nvar1 b c touse1 A local nvar: word count `varlist' local nvar1=`nvar'-1 if `nvar'==1 { local nvar=2 } local dv: word 1 of `varlist' local expl: list varlist -dv mark `touse' `if' `in' markout `touse' `varlist' qui count if `touse' local N=r(N) qui gen `ord'=_n qui gen `touse1'=1-`touse' qui sort `touse1' if "`replic'"!="" { local reps=`replic' } else { local reps=max(ceil((log(1-0.99))/(log(1-(1-0.2)^(`nvar')))),20) } if `reps'>500 { display in red "!!! The total number of p-subsets to check is " `reps' " it can take quite some time." } else { display in white "The total number of p-subsets to check is "`reps' } qui gen `rand'=0 scalar `bestmad'=10e+12 scalar `bestmrho'=10e+12 scalar `eps'=1e-5 scalar `maxit'=50 qui gen `tcand'=10e+12 qui gen `bestw'=1 capture qui { local i 1 while `i'<=`reps' { capture drop `rand' sort `touse1' `ord' qui gen `rand'=uniform() sort `touse1' `rand' scalar `err'=1 if "`noconstant'"!="" { qui reg `varlist' in 1/`nvar1', nocons } else { qui reg `varlist' in 1/`nvar' } capture drop `yres' capture drop `u0' predict `yres', res gen `u0'=`yres' qui replace `yres'=abs(`yres') summ `yres' if `touse', d scalar `mad'=_result(10)/0.6745 capture drop `u' gen `u'=`u0'/`mad' capture drop `w' gen `w'=1*(abs(`u')/1.5468906<=1) capture drop `rho' gen `rho'=(`u'^2/(2)*(1-(`u'^2/(1.5468906^2))+(`u'^4/(3*1.5468906^4))))*`w' +(1-`w')*(1.5468906^2/6) replace `rho'=`rho'*6/1.5468906^2 qui summ `rho' if `touse' scalar `mrho'=r(mean) capture drop `weight' gen `weight'=(1-(`u'/1.5468906)^2)^2*`w' sort `tcand' if `mad'<`tcand' in 5 { replace `tcand'=`mad' in 5 local j 1 while `j'<=`maxit'&`err'>`eps' { if "`noconstant'"!="" { qui reg `varlist' [aweight=`weight'] if `touse', nocons } else { qui reg `varlist' [aweight=`weight'] if `touse' } capture drop `u0' capture qui predict `u0',res capture drop `u' capture qui gen `u'=`u0'/`mad' capture drop `w' capture qui gen `w'=1*(abs(`u')/1.5468906<=1) replace `rho'=(`u'^2/(2)*(1-(`u'^2/(1.5468906^2))+(`u'^4/(3*1.5468906^4))))*`w' +(1-`w')*(1.5468906^2/6) replace `rho'=`rho'*6/1.5468906^2 qui summ `rho' if `touse' scalar `mrho'=r(mean) scalar `mad2' = sqrt(`mad'^2 * `mrho'/ 0.5) scalar `err'=abs(`mad2'/`mad' - 1) capture drop `weight' capture qui gen `weight'=(1-(`u'/1.5468906)^2)^2*`w' scalar `mad'=`mad2' local j=`j'+1 } } if `mad'<`bestmad' { scalar `bestmad'=`mad' replace `bestw'=`weight' } local i=`i'+1 } } sort `ord' if "`noconstant'"!="" { qui reg `varlist' [aweight=`bestw'] if `touse', nocons gen `tempconst'=. } else { qui reg `varlist' [aweight=`bestw'] if `touse' gen `tempconst'=1 } matrix `coefS'=e(b) capture drop `u' predict `u', res qui replace `u'=`u'/`bestmad' capture drop `stdres' qui gen `stdres'=`u' qui gen `tempu'=`stdres' qui gen `tempmad'=`bestmad' local tempconsti="`tempconst'" local tempui="`tempu'" local tempmadi="`tempmad'" mata: tstat("`varlist'","`tempconsti'","`tempui'","`tempmadi'","`touse'") matrix V=e(V) ereturn post `coefS' V, esample(`touse') depname(`dv') obs(`N') ereturn local depvar = "`depvar'" ereturn scalar scale=`bestmad' ereturn scalar N = `N' if "`noconstant'"!="" { ereturn scalar df_r= `N'-`nvar'+1 ereturn scalar df_m= `nvar'-1 } else { ereturn scalar df_r= `N'-`nvar' ereturn scalar df_m= `nvar' } ereturn local cmd="sregress" ereturn local title="S-regression" matrix repost V=COV qui sort `ord' ereturn display di in bl "Scale parameter= "%9.0g in y scalar(`bestmad') qui est store `A' global S_1=`bestmad' if "`outlier'"!="" { capture drop S_outlier capture qui gen S_outlier=(abs(`stdres')>2.25) if e(sample)&`stdres'!=. capture drop S_stdres capture qui gen S_stdres=`stdres' if e(sample)&`stdres'!=. qui est restore `A' } if "`graph'"!="" { local c=0 local dv: word 1 of `varlist' local ivs: list varlist-dv foreach v of local ivs { qui tab `v' if r(r)==2 { local c=`c' } else { local continuous "`continuous' `v'" local c=`c'+1 } } local cv: word 1 of `continuous' local continuous: list continuous-cv local b=sqrt(invchi2(`c'),0.975) capture qui mcd `continuous', outlier qui est restore `A' label var `stdres' "Robust standardized residuals" twoway (scatter `stdres' Robust_distance if abs(`stdres')<4&Robust_distance=4|Robust_distance>=2*`b', mlabel(`ord') msymbol(circle_hollow)), xline(`b') yline(2.25) yline(-2.25) legend(off) } end version 10.0 mata: void tstat(string scalar varlist, string scalar tempconsti, string scalar tempui, string scalar tempmadi, string scalar touse) { st_view(X=.,.,tokens(varlist),touse) st_view(ONE=.,.,tokens(tempconsti), touse) st_view(u=.,.,tokens(tempui),touse) st_view(sc=.,.,tokens(tempmadi), touse) s=sc[1,1] n=rows(X) ONE=ONE[1..n,1] X=(nonmissing(ONE)==0 ? X : (X,ONE) ) k0=cols(X) w=(abs(u):/1.5468906):<=1 psi=w:*u:*(1:-(u:/1.5468906):^2):^2 dpsi=w:*(1:-u:^2:*(6/1.5468906^2:-5:*u:^2:/1.5468906^4)) X=X[.,(2..k0)] k=cols(X) h1=dpsi*J(1,k,1) h1=h1:*X EdpsiXX=(1/n)*X'*h1 h2=psi*J(1,k,1) G=X:*h2 B=(1/n)*G'*G h3=invsym(EdpsiXX) cov1s=s^2*(1/n)*h3*B*h3 st_matrix("COV",cov1s) } end exit