*! version 1.05 22apr2013 * author: Paulo Guimaraes * program define scoregrp, rclass version 11 ************************************************************ syntax [varlist(default=none)],group(varname) [nocons] * check if matdelrc installed capture matdelrc if _rc != 0 { di as err "Error - Please install the user-written command matdelrc" di "type -findit matdelrc-" exit 601 } tempvar groups score y one quietly { if "`varlist'"==""&"`cons'"!="" { noisily di "No variable to test" error 301 } if "`cons'"!="" { local xx0="`varlist'" } else { local addone "`one'" local xx0: list varlist|addone } ************************************************************ * Obtain information from last regression ************************************************************ local vcetype=e(vce) local command=e(cmd) if "`command'"=="poisson"|"`command'"=="logit"|"`command'"=="logistic"|"`command'"=="probit" { if "`vcetype'"!="oim" { noisily di as err "Not valid with vce(`vcetype')" error 111 } noisily di noisily di as text "Score test for `command' regression" } else if "`command'"=="regress" { if "`vcetype'"!="ols" { noisily di as err "Not valid with vce(`vcetype')" error 111 } noisily di noisily di as text "Score test for Linear regression" local mse=e(df_r)/e(N)*(e(rmse)^2) } else { noisily di "Only valid after Regress, Poisson, Probit, Logit or Logistic command" error 111 } local xx1 : rownames e(V) /*all variables in the regression*/ * Test if variables belong to varlist local dummy: list varlist in xx1 if `dummy'==0 { noisily di as err "Error: at least one of the variables in `varlist'" di as err "does not belong to list of predictors or is repeated" error 111 } local constant "_cons" local xx2: list xx1-constant local xx3: list xx2|one /*all vars with constant */ local xx4: list xx3-xx0 /*vars not tested*/ *********************************************************** * Do validity checks *********************************************************** qui sum `group' if `r(min)' == `r(max)' { noisily di as err "The group variable `group' must have at least two different values!" error 198 } ************************************************************ * Restrict the sample to valid observations *********************************************************** preserve keep `xx2' `e(depvar)' `group' qui keep if e(sample) *********************************************************** * Compute Preliminary variables/constants gen int `one'=1 matrix B=e(V) local maxg=`e(N)'-colsof(B) /*Maximum nb of degrees of freedom*/ ************************************************************ * Computing scores ************************************************************ tempname s_ if "`command'"=="poisson"|"`command'"=="logit"|"`command'"=="logistic"|"`command'"=="regress" { tempvar yhat qui predict double `yhat' } if "`command'"=="probit" { tempvar xbhat lami qui predict double `xbhat', xb gen double `lami'=(2*`e(depvar)'-1)*normalden((2*`e(depvar)'-1)*`xbhat')/normal((2*`e(depvar)'-1)*`xbhat') } foreach var in `xx0' { if "`command'"=="poisson"|"`command'"=="logit"|"`command'"=="logistic" { gen double `s_'`var'=(`e(depvar)'-`yhat')*`var' } if "`command'"=="probit" { gen double `s_'`var'=`lami'*`var' } if "`command'" == "regress" { gen double `s_'`var'=(`e(depvar)'-`yhat')/(`mse')*`var' } } ************************************************************* * Computing Crossed Derivatives ************************************************************* tempname haa_ local dum "`xx0'" foreach var1 in `xx0' { foreach var2 in `dum' { if "`command'" == "poisson" { gen double `haa_'`var1'_`var2'=`var1'*`var2'*`yhat' } if "`command'" == "logit"|"`command'"=="logistic" { gen double `haa_'`var1'_`var2'=`var1'*`var2'*`yhat'*(1-`yhat') } if "`command'" == "probit" { gen double `haa_'`var1'_`var2'=`var1'*`var2'*`lami'*(`lami'+`xbhat') } if "`command'" == "regress" { gen double `haa_'`var1'_`var2'=`var1'*`var2'/(`mse') } } local dum: list dum-var1 } tempname hab_ foreach var1 in `xx4' { foreach var2 in `xx0' { if "`command'" == "poisson" { gen double `hab_'`var1'_`var2'=`var1'*`var2'*`yhat' } if "`command'" == "logit"|"`command'"=="logistic" { gen double `hab_'`var1'_`var2'=`var1'*`var2'*`yhat'*(1-`yhat') } if "`command'" == "probit" { gen double `hab_'`var1'_`var2'=`var1'*`var2'*`lami'*(`lami'+`xbhat') } if "`command'" == "regress" { gen double `hab_'`var1'_`var2'=`var1'*`var2'/(`mse') } } } egen long `groups'=group(`group') /*Compute unique id for groups*/ ********************************************************** unab haa: `haa_'* unab sco: `s_'* if "`xx4'"!="" { unab hab: `hab_'* matrix H=invsym(e(V)) if "`command'"=="regress" { matrix V=H matrix H=(e(N)/e(df_r))*V } foreach var in `xx0' { local pos: list posof `"`var'"' in xx3 matdelrc H, row(`pos') col(`pos') local xx3: list xx3-var } } collapse (sum) `haa' `hab' `sco', by(`groups') local nbtvars: list sizeof xx0 local df=min((_N-1)*`nbtvars',`maxg') *************************************************************************** if "`xx4'"!="" { noisily mata: testever("`sco'","`haa'","`hab'") } else { noisily mata: testever("`sco'","`haa'") } } ************************************************************************** local xx5: list xx1-xx4 if "`cons'"!="" { local xx5: list xx5-constant } di as txt "Testing variables: `xx5'" di as txt "Group variable: `group'" di di as txt %6.0f "Test result is chi(`df') = " as res %-9.4f `r(test)' as txt /// " Pr = " as res %-9.4f chi2tail(`df',`r(test)') return scalar pval=chi2tail(`df',`r(test)') return scalar test=`r(test)' set trace off end mata: function testever(string scalar vars1, string scalar vars2 ,|string scalar vars3) { string rowvector scoresv scoresv=tokens(vars1) st_view(scores1=.,.,scoresv) string rowvector haav haav=tokens(vars2) st_view(haa1=.,.,haav) if (args()==3) { string rowvector habv habv=tokens(vars3) st_view(hab1=.,.,habv) mv=st_matrix("H") k2=cols(mv) } k1=cols(scoresv) g=rows(scoresv) if (k1==1) { saH=scores1:/haa1 s1=cross(saH,scores1) s2=0 if (args()==3) { habw=hab1:/haa1 d1=cross(hab1,habw) d2=invsym(mv-d1) d3=cross(scores1,habw) s2=d3*d2*d3' } } if (k1>1) { s1=crossblock(scores1,haa1,scores1) s2=0 if (args()==3) { P1=J(1,k2,0) P2=J(k2,k2,0) for (i=1;i<=k2;i++) { p12=hab1[.,(((i-1)*k1+1)::i*k1)] P1[1,i]=crossblock(scores1,haa1,p12) } for (i=1;i<=k2;i++) { p12=hab1[.,(((i-1)*k1+1)::i*k1)] for (j=i;j<=k2;j++) { p13=hab1[.,(((j-1)*k1+1)::j*k1)] P2[i,j]=crossblock(p13,haa1,p12) P2[j,i]=P2[i,j] } } P=mv-P2 s2=P1*invsym(P)*P1' } } lm=s1+s2 test=lm[1,1] st_numscalar("r(test)",test) } real scalar crossblock( numeric matrix L, numeric matrix B, numeric matrix R) { real scalar g, k1, k2, s1 real matrix temp1,ll,rr,bb,BB g=rows(B) k1=cols(L) k2=k1*(k1-1)/2+k1 temp1=J(g,1,0) ll=J(k1,1,0) rr=J(k1,1,0) bb=J(k2,1,0) for (i=1;i<=g;i++) { for (j=1;j<=k1;j++) { ll[j,.]=L[i,j] rr[j,.]=R[i,j] } for (j=1;j<=k2;j++) { bb[j,.]=B[i,j] } BB=invvech(bb) temp1[i,1]=ll'*invsym(BB)*rr } s1=sum(temp1) return(s1) } end