capture program drop margeff8 program define margeff8 *! Marginal effects for categorical dependent variable models *! This version: 10 February 2006 (3rd update for Stata Journal submission) *! Author: Tamas Bartus (Corvinus University, Budapest) version 8 ******************************************************************************* * * [1] SYNTAX CHECK * ******************************************************************************* if "`e(cmd)'"=="" exit 301 * Determining what to do * if no arguments, replay results, provided the -replace- option was used if `"`0'"'=="," | "`0'"=="" { if "`e(cmd)'"=="margeff" local doit = 0 else local doit = 1 } * if arguments found, estimate if replay subcmd not found else { gettoken cmd 0 : 0 , parse(" ,") local l = length("`cmd'") if substr("replay",1,`l')==`"`cmd'"' { local doit = 0 } else if substr("compute",1,`l')=="`cmd'" { local doit = 1 } else { local 0 `cmd' `0' local doit = 1 } } if `doit'==1 { if `e(df_m)'==0 { di as error "There are no independent variables; running -margeff- makes no sense" exit } if "`e(cmd)'"=="margeff" exit 301 syntax [if] [in] [ , Eform Model(string) * ] if "`eform'"!="" { local length : word count `e(depvar)' if `length'>1 { di as error "The eform option can only be used after single-equation commands" exit } } if "`model'"=="" local model = e(cmd) sret clear SetSMacros `model' `eform' if "`s(type)'"=="0" { di as error "-margeff- does not work with `s(error)'`model'; use -mfx- instead" exit } preserve Estimate `0' restore sret clear Replay new `0' } else Replay existing `0' end program define SetSMacros , sclass version 6 sret clear sret local model "`1'" sret local ncons 1 if "`2'"!="" { sret local type 9 sret local neq 1 sret local nout 1 sret local nap 0 exit } else if "`1'"=="logit" | "`1'"=="logistic" | "`1'"=="probit" | "`1'"=="cloglog" | /* */ "`1'"=="poisson" { sret local nout 1 sret local type 1 sret local neq 1 sret local nap 0 exit } else if "`1'"=="xtprobit" | "`1'"=="nbreg" | "`1'"=="heckprob" { sret local nout 1 sret local type 1 sret local neq 1 sret local nap 1 exit } else if "`1'"=="oprobit" | "`1'"=="ologit" { qui tab `e(depvar)' if e(sample) local ncons = e(k_cat)-1 local nout = r(r) sret local ncons `ncons' sret local neq 1 sret local nout `nout' sret local type 2 sret local nap `ncons' exit } else if "`1'"=="mlogit" | "`1'"=="gologit" { qui tab `e(depvar)' if e(sample) local neq = r(r)-1 local nout = r(r) sret local ncons 1 sret local neq `neq' sret local nout `nout' sret local type 2 sret local nap 0 exit } else if "`1'"=="biprobit" | "`1'"=="zip" | "`1'"=="zinb" { local neq = 2 local type = 3 local nout = 1 if "`1'"=="biprobit" { if substr(e(title),1,1)=="B" { //local type = 2 local nout = 4 } else { sret local type 0 sret local error "seemingly unrelated verson of " exit } } sret local neq `neq' sret local nout `nout' sret local type `type' if "`1'"=="zip" { sret local nap 0 } else sret local nap 1 exit } else sret local type 0 end ******************************************************************************* * * [2] ESTIMATION * ******************************************************************************* program define Estimate , rclass version 8 syntax [if] [in] /// [ , at(string) Count Dummies(string) Eform Model(string) NODiscrete NOOFFset Percent Replace OUTcome(numlist min=1 integer) ] if "`at'"!="" { capture _at "`at'" if _rc!=0 { di as error "Invalid at() option" exit } } if "`outcome'"!="" { local nout : word count `outcome' local max : word `nout' of `outcome' if `max'>`s(nout)' error 125 } else { local nout = `s(nout)' numlist "1/`nout'" local outcome = r(numlist) } if "`nodiscrete'"!="" local discrete off else local discrete on if "`count'"!="" local count on else local count off *======================================= * * [2/1]: PROCESSING ESTIMATION RESULTS * *======================================= tempname b vce coef pder partder me bm Vm tempvar touse local cmd = e(cmd) * local numobs = e(N) qui gen byte `touse' = e(sample) `if' `in' qui count if `touse'==1 local numobs = r(N) ProcEst`s(type)' `s(model)' mat `b' = r(b) mat `coef' = r(coef) mat `vce' = r(v) local Vdim = colsof(`vce') if "`dummies'"!="" { DumList `b' `dummies' } if "`s(error)'"!="" { di as error "`s(error)'" error 198 } *======================================= * * [2/1]: DATA MODIFICATION: CONSTANTS AND AT LIST * *======================================= * ADDING CONSTANTS / CUT-OFFS TO DATA local i = 1 while `i'<=`s(ncons)' { tempvar c`i' qui gen byte `c`i'' = 1 local clist `clist' `c`i'' local i = `i'+1 } PassToS `clist' VarTypes `touse' `count' AtOption `at' if "`at'"!="" { _at "`at'" "if `touse'==1" tempname atmat mat `atmat' = r(at) foreach var in `s(Tlist)' { local pos = colnumb(`atmat',"`var'") local value = `atmat'[1,`pos'] qui replace `var' = `value' if `touse'==1 } } *======================================= * * [2/3]: PREDICTING INDEX - DEFINING CDF and PDF * *======================================= if "`s(model)'"=="mlogit" { local denom 1 } local i = 1 while `i'<=`s(neq)' { if `s(neq)'>1 { local Popt "eq(#`i')" } tempvar xb`i' matrix score `xb`i'' = `b' if `touse' , `Popt' if `"`e(offset)'"'!="" { if "`nooffset'"=="" { qui replace `xb`i'' = `xb`i''+ `e(offset)' } } Mindex `i' `xb`i'' if "`s(model)'"=="mlogit" { local denom "`denom'+exp(`xb`i'')" } local i = `i'+1 } if "`s(model)'"=="mlogit" { local mopt `denom' } if `s(type)'==9 { local exe eform } else local exe `s(model)' GenFx_`exe' `s(depvar)' `mopt' if "`s(error)'"!="" { di as error "-margeff- cannot estimate the requested marginal effects" di as error "The problem: `s(error)'" exit } *======================================= * * [2/4]: DOING THE CALCULATIONS * *======================================= local dim = `s(Ntreat)'*`nout' local col = 0 local treatlist `s(Treat)' local Dvars `s(Dummyvars)' local Cvars `s(Countvars)' local j = 1 while `j'<=`nout' { local out : word `j' of `outcome' local eqname : word `out' of `s(eqname)' * Loop for variables local i = 1 while `i'<=`s(Ntreat)' { local col = `col'+1 local treat : word `i' of `s(Tlist)' local vtype Contin if "`discrete'"=="on" { local temp : subinstr local Dvars "`treat'" "" , count(local change) if `change'==1 local vtype Dummy } if "`count'"=="on" & "`vtype'"=="Contin" { local temp : subinstr local Cvars "`treat'" "" , count(local change) if `change'==1 local vtype Count } local delta = 1 if "`vtype'"=="Contin" { qui sum `treat' , detail if r(p95)==r(p5) { local delta = 10^(-6)*(r(max)-r(min)) } else local delta = 10^(-6)*(r(p95)-r(p5)) } qui GetMargEff_`vtype' `treat' `touse' `numobs' `i' `out' `coef' `Vdim' `delta' `atmat' mat `me' = r(me) mat `pder' = r(pder) mat colnames `me' = `treat' mat colnames `pder' = `treat' _cons mat rownames `pder' = `treat' if `s(nout)'>1 { mat coleq `me' = `eqname' mat coleq `pder' = `eqname' mat roweq `pder' = `eqname' } capture mat list `bm' if _rc==0 { mat `bm' = `bm' , `me' mat `partder' = `partder' \ `pder' } else { mat `bm' = `me' mat `partder' = `pder' } local i = `i'+1 } * End of loop for variables local j = `j'+1 } mat `Vm' = `partder'*`vce' mat `Vm' = `Vm'*`partder'' return mat margeff_b `bm' return mat margeff_V `Vm' return local margeff_at `s(at)' return local margeff_method `s(method)' return local margeff_discrete `discrete' return local margeff_count `count' return local margeff_cvars `s(Countvars)' return local margeff_dvars `s(Dummyvars)' return local margeff_def `s(medef)' return local margeff_cmd `cmd' return local esample `touse' return scalar margeff_N = `numobs' end ******************************************************************************* * * [3] COLLECTING AND DISPLAYING RESULTS * ******************************************************************************* program define Replay , eclass version 8 gettoken first 0 : 0 syntax [if] [in] [ , Percent Replace * ] tempname at b V bpost Vpost tab tempvar touse if "`first'"=="new" local Class r else local Class e if "`e(cmd)'"=="margeff" local Prefix else local Prefix margeff_ mat `b' = `Class'(`Prefix'b) mat `V' = `Class'(`Prefix'V) local depvar = e(depvar) local cmd = `Class'(`Prefix'cmd) qui gen `touse' = e(sample) foreach word in cvars dvars count discrete at method def { local `word' = `Class'(margeff_`word') } * Display form (avoiding double percentages) if "`first'"=="existing" { if "`percent'"!="" & `"`e(margeff_display)'"'=="percent" { local percent } } if "`percent'"!="" { mat `b' = 10^2 * `b' mat `V' = 10^4 * `V' local dispfrom percent } else local dispform asis mat `bpost' = `b' mat `Vpost' = `V' tempname ehold _est hold `ehold' if "`method'"=="average" local title Average marginal effects else local title Marginal effects at `method's di di as text "`title' on " as res "`def'" as text " after " as res "`cmd'" if "`method'"!="average" & "`at'"!="." { di as text "Variables set to specific values: " _col(40) as res "`at'" } if "`count'"=="on" di as text "Variables treated as counts: " _col(40) as res "`cvars'" if "`discrete'"=="off" di as text "Dummies treated as continuous vars: " _col(40) as res "`dvars'" di ereturn post `bpost' `Vpost' , depname("`depvar'") ereturn disp _est unhold `ehold' if "`replace'"!="" { * Saves scalars local scalars : e(scalars) foreach el in `scalars' { tempname s`el' scalar `s`el'' = e(`el') } * Posting results mat `bpost' = `b' mat `Vpost' = `V' ereturn post `bpost' `Vpost' , esample(`touse') ereturn local cmd margeff ereturn local depvar `depvar' * Restores scalars foreach el in `scalars' { eret scalar `el' = `s`el'' } } * Returns results ereturn mat margeff_V = `V' ereturn mat margeff_b = `b' foreach word in cvars dvars count discrete at method def { ereturn local margeff_`word' ``word'' } ereturn local margeff_display `dispform' ereturn local margeff_cmd `cmd' end *============================================================ * * [4] MARGINAL EFFECTS + STANDARD ERRORS * *============================================================ program define GetMargEff_Contin , rclass version 8 args treat touse numobs id out mat Vdim delta tempvar hat0 hat1 tempname row pder mat `pder' = J(1,`Vdim',0) nobreak { gen double `hat0' = 0 local dmin = 10^6 * CALCULATING THE CDF + DENSITIES * CORRECTION FOR SMALL CHANGE TERM forval q = 1 / `s(neq)' { local beta = `mat'[`id',`q'] if `beta'<`dmin' & `beta'!=0 { local dmin = `beta' } tempvar save`q' phi0`q' gen double `save`q'' = `s(xb`q')' if "`s(dens`out'`q')'"=="" { gen byte `phi0`q'' = 0 } else { replace `hat0' = `hat0' + `s(dens`out'`q')'*`beta' gen double `phi0`q'' = `s(dens`out'`q')' `s(`treat')' } } local delta = `delta'/abs(`dmin') * SETTING DUMMIES TO 1 / INCREASING VALUE OF CONTINUOUS VARS forval q = 1 / `s(neq)' { local beta = `mat'[`id',`q'] replace `s(xb`q')' = `s(xb`q')'+`beta'*`delta' } * CALCULATING DENSITIES forval q = 1 / `s(neq)' { tempvar phi1`q' if "`s(dens`out'`q')'"=="" { gen byte `phi1`q'' = 0 } else gen double `phi1`q'' = `s(dens`out'`q')' `s(`treat')' } * CALCULATING STANDARD ERRORS * RESTORING INDEX forval q = 1 / `s(neq)' { local beta = `mat'[`id',`q'] tempvar part`q' gen double `part`q'' = (`phi1`q''-`phi0`q'')/`delta' if "``s(`treat')'"!="" { replace `part`q'' = 0 if `part`q''==. & `touse'==1 } replace `s(xb`q')' = `save`q'' * The i-th row of the part. deriv. matrix su `phi1`q'' local add = r(mean) tempname row`q' mat vecaccum `row`q'' = `part`q'' `s(rhs)' if `touse' , noconstant mat list `row`q'' mat `row`q'' = `row`q'' / `numobs' mat `row`q''[1,`id'] = `row`q''[1,`id'] + `add' if `q'==1 { mat `pder' = `row`q'' } else mat `pder' = `pder' , `row`q'' } } /* end of nobreak */ * MARGINAL EFFECT / RETURNING RESULTS sum `hat0' `s(`treat')' return scalar me = r(mean) return scalar sd = r(sd) return scalar min = r(min) return scalar max = r(max) return matrix pder `pder' end program define GetMargEff_Dummy , rclass version 8 args treat touse numobs id out mat Vdim delta atmat tempvar hat0 hat1 tempname row pder mat `pder' = J(1,`Vdim',0) nobreak { * BACKUP FOR LINEAR PREDICTION * SETTING DUMMIES TO ZERO forval q = 1 / `s(neq)' { local beta = `mat'[`id',`q'] tempvar save`q' gen double `save`q'' = `s(xb`q')' if "`s(method)'"=="average" replace `s(xb`q')' = `s(xb`q')'-`beta'*(`treat'==1) else { local pos = colnumb(`atmat',"`treat'") local value = `atmat'[1,`pos'] replace `s(xb`q')' = `s(xb`q')'-`beta'*`value' } } * CALCULATING THE CDF + DENSITIES gen double `hat0' = `s(cumu`out'1)' forval q = 1 / `s(neq)' { tempvar phi0`q' if "`s(dens`out'`q')'"=="" { gen byte `phi0`q'' = 0 } else gen double `phi0`q'' = `s(dens`out'`q')' `s(`treat')' } * SETTING DUMMIES TO 1 forval q = 1 / `s(neq)' { local beta = `mat'[`id',`q'] replace `s(xb`q')' = `s(xb`q')'+`beta' } * CALCULATING THE CDF + DENSITIES gen double `hat1' = `s(cumu`out'1)' forval q = 1 / `s(neq)' { tempvar phi1`q' if "`s(dens`out'`q')'"=="" { gen byte `phi1`q'' = 0 } else gen double `phi1`q'' = `s(dens`out'`q')' `s(`treat')' } * CALCULATING STANDARD ERRORS * RESTORING INDEX forval q = 1 / `s(neq)' { local beta = `mat'[`id',`q'] tempvar part`q' gen double `part`q'' = (`phi1`q''-`phi0`q'') if "``s(`treat')'"!="" { replace `part`q'' = 0 if `part`q''==. & `touse'==1 } replace `s(xb`q')' = `save`q'' * The i-th row of the part. deriv. matrix su `phi1`q'' local add = r(mean) tempname row`q' mat vecaccum `row`q'' = `part`q'' `s(rhs)' if `touse' , noconstant mat list `row`q'' mat `row`q'' = `row`q'' / `numobs' mat `row`q''[1,`id'] = `add' if `q'==1 { mat `pder' = `row`q'' } else mat `pder' = `pder' , `row`q'' } } /* end of nobreak */ * MARGINAL EFFECT / RETURNING RESULTS replace `hat1' = (`hat1'-`hat0') sum `hat1' `s(`treat')' `weight' return scalar me = r(mean) return scalar sd = r(sd) return scalar min = r(min) return scalar max = r(max) return matrix pder `pder' end program define GetMargEff_Count , rclass version 8 args treat touse numobs id out mat Vdim delta atmat tempvar hat0 hat1 tempname row pder mat `pder' = J(1,`Vdim',0) nobreak { * BACKUP FOR LINEAR PREDICTION forval q = 1 / `s(neq)' { tempvar save`q' gen double `save`q'' = `s(xb`q')' } * CALCULATING THE CDF + DENSITIES gen double `hat0' = `s(cumu`out'1)' forval q = 1 / `s(neq)' { tempvar phi0`q' if "`s(dens`out'`q')'"=="" { gen byte `phi0`q'' = 0 } else gen double `phi0`q'' = `s(dens`out'`q')' `s(`treat')' } * INCREASING VALUE OF COUNT VARS forval q = 1 / `s(neq)' { local beta = `mat'[`id',`q'] replace `s(xb`q')' = `s(xb`q')'+`beta'*`delta' } * CALCULATING THE CDF + DENSITIES gen double `hat1' = `s(cumu`out'1)' forval q = 1 / `s(neq)' { tempvar phi1`q' if "`s(dens`out'`q')'"=="" { gen byte `phi1`q'' = 0 } else gen double `phi1`q'' = `s(dens`out'`q')' `s(`treat')' } * CALCULATING STANDARD ERRORS * RESTORING INDEX forval q = 1 / `s(neq)' { local beta = `mat'[`id',`q'] tempvar part`q' gen double `part`q'' = (`phi1`q''-`phi0`q'')/(`delta') if "``s(`treat')'"!="" { replace `part`q'' = 0 if `part`q''==. & `touse'==1 } replace `s(xb`q')' = `save`q'' * The i-th row of the part. deriv. matrix su `phi1`q'' `w' local add = r(mean) tempname row`q' mat vecaccum `row`q'' = `part`q'' `s(rhs)' if `touse' , noconstant mat list `row`q'' mat `row`q'' = `row`q'' / `numobs' mat `row`q''[1,`id'] = `row`q''[1,`id'] + `add' if `q'==1 { mat `pder' = `row`q'' } else mat `pder' = `pder' , `row`q'' } } /* end of nobreak */ * MARGINAL EFFECT / RETURNING RESULTS replace `hat1' = (`hat1'-`hat0')/(`delta') sum `hat1' `s(`treat')' return scalar me = r(mean) return scalar sd = r(sd) return scalar min = r(min) return scalar max = r(max) return matrix pder `pder' end *============================================================ * * [5] PROGRAMS PREDICTING CDF, DENSITY, AND DERIVATIVES * *============================================================ program define GenFx_eform , sclass EqLabel `1' sret local medef E(exp[xb]) sret local depname `s(depvar)' sret local eqname `1' sret local cumu11 exp(`s(xb1)') sret local dens11 exp(`s(xb1)') end program define GenFx_probit , sclass version 8 args depvar rho if "`rho'"=="" { local rho 1 } sret local cumu11 "normprob(`rho'*`s(xb1)')" sret local dens11 " `rho'*normd(`rho'*`s(xb1)') " EqLabel `depvar' sret local medef "Prob(`depvar'==`s(cat)')" sret local depname `depvar' sret local eqname `depvar' end program define GenFx_xtprobit , sclass if e(predict)=="xtbin_p" { local rho = sqrt(1-`e(rho)') GenFx_probit `*' `rho' } else { sret local error "the population-averaged version of xtprobit not supported" exit } end program define GenFx_heckprob , sclass version 8 local depvar : word 1 of `0' GenFx_probit `depvar' end program define GenFx_logit , sclass version 8 args depvar local cumu11 "1/(1+exp(-`s(xb1)'))" sret local cumu11 `cumu11' sret local dens11 "(`cumu11')*(1-`cumu11')" EqLabel `depvar' sret local medef Prob(`depvar'==`s(cat)') sret local depname `depvar' sret local eqname `depvar' end program define GenFx_logistic GenFx_logit `*' end program define GenFx_cloglog , sclass local depvar "`1'" local cumu11 " 1-exp(-exp(`s(xb1)')) " local dens11 " -(1-`cumu11')*exp(`s(xb1)') " sret local cumu11 `cumu11' sret local dens11 `dens11' EqLabel `s(depvar)' sret local medef "Prob(`s(depvar)'==`s(cat)')" sret local depname `depvar' sret local eqname `depvar' end program define GenFx_oprobit version 8 tempname b mat `b' = e(b) local check = colnumb(`b',"_cut1") if `check'!=. GenFx_oprobit8 `0' else GenFx_oprobit9 `0' end program define GenFx_oprobit8 , sclass version 8 args depvar tempname matcat mat `matcat' = e(cat) local kcat = e(k_cat) sret local cumu11 "(1-normprob(`s(xb1)'-_b[_cut1]))" sret local dens11 "-normd(`s(xb1)'-_b[_cut1])" local cat = `matcat'[1,1] EqLabel `s(depvar)' `cat' forval i = 2(1)`s(nout)' { local j = `i'-1 di _b[_cut`j'] sret local cumu`i'1 "(normprob(_b[_cut`i']-`s(xb1)')-normprob(_b[_cut`j']-`s(xb1)'))" sret local dens`i'1 "(normd(_b[_cut`j']-`s(xb1)')-normd(_b[_cut`i']-`s(xb1)'))" local cat = `matcat'[1,`i'] EqLabel `e(depvar)' `cat' } local j = `s(nout)'-1 sret local cumu`s(nout)'1 "normprob(`s(xb1)'-_b[_cut`j'])" sret local dens`s(nout)'1 "normd(`s(xb1)'-_b[_cut`j'])" local cat = `matcat'[1,`s(nout)'] EqLabel `depvar' `cat' sret local medef Prob(`depvar') sret local depname `depvar' end program define GenFx_ologit version 8 tempname b mat `b' = e(b) local check = colnumb(`b',"_cut1") if `check'!=. GenFx_ologit8 `0' else GenFx_ologit9 `0' end program define GenFx_ologit8 , sclass version 8 args depvar tempname matcat b mat `matcat' = e(cat) sret local cumu11 "1/(1+exp(-_b[_cut1]+`s(xb1)'))" sret local dens11 "-exp(_b[_cut1]-`s(xb1)')/((1+exp(_b[_cut1]-`s(xb1)'))^2)" local cat = `matcat'[1,1] EqLabel `depvar' `cat' forval i = 2(1)`s(nout)' { local j = `i'-1 sret local cumu`i'1 "(1/(1+exp(_b[_cut`i']+`s(xb1)'))-1/(1+exp(-_b[_cut`j']+`s(xb1)')))" sret local dens`i'1 "(exp(_b[_cut`j']-`s(xb1)')/((1+exp(_b[_cut`j']-`s(xb1)'))^2)-exp(_b[_cut`i']-`s(xb1)')/((1+exp(_b[_cut`i']-`s(xb1)'))^2))" local cat = `matcat'[1,`i'] EqLabel `depvar' `cat' } local j = `s(nout)'-1 sret local cumu`s(nout)'1 "1/(1+exp(_b[_cut`j']-`s(xb1)'))" sret local dens`s(nout)'1 "exp(`s(xb1)'-_b[_cut`j'])/((1+exp(`s(xb1)'-_b[_cut`j']))^2)" local cat = `matcat'[1,`s(nout)'] EqLabel `depvar' `cat' sret local medef Prob(`depvar') sret local depname `depvar' end program define GenFx_gologit , sclass version 8 args depvar tempvar group qui egen `group' = group(`s(depvar)') forval i = 1(1)`s(nout)' { local j = `i'-1 if `i'==1 { sret local cumu`i'1 " 1/(1+exp(`s(xb`i')')) " sret local dens`i'`i' " -exp(-`s(xb`i')')/((1+exp(-`s(xb`i')'))^2) " } if `i'>1 & `i'<`s(nout)' { sret local cumu`i'1 " 1/(1+exp(`s(xb`i')'))-1/(1+exp(`s(xb`j')'))" sret local dens`i'`j' " exp(-`s(xb`j')')/((1+exp(-`s(xb`j')'))^2)" sret local dens`i'`i' "-exp(-`s(xb`i')')/((1+exp(-`s(xb`i')'))^2)" } if `i'==`s(nout)' { sret local cumu`i'1 "1/(1+exp(-`s(xb`j')'))" sret local dens`i'`j' " exp(`s(xb`j')')/((1+exp(`s(xb`j')'))^2)" } qui sum `depvar' if `group'==`i' local cat = r(mean) EqLabel `depvar' `cat' } sret local medef Prob(`depvar') sret local depname `depvar' end program define GenFx_mlogit , sclass version 8 args depvar denom tempname matcat mat `matcat' = e(cat) local base = e(ibasecat) **** CDF ******** forval i = 1/`s(nout)' { local j = `i'-(`i'>`base') if `i'==`base' local prob`i' "(1/(`denom'))" else local prob`i' "(exp(`s(xb`j')')/(`denom'))" sret local cumu`i'1 "`prob`i''" } ******* Densities ******* forval i = 1/`s(nout)' { local j = `i'-(`i'>`base') forval q = 1/`s(neq)' { if `i'==`base' { sret local dens`i'`q' "(-exp(`s(xb`q')')/(`denom')^2)" } else { if `q'==`j' { * sret local dens`i'`q' "((`prob`j'')*(1-(`prob`j'')))" sret local dens`i'`q' "(exp(`s(xb`j')')/(`denom')-exp(`s(xb`j')')^2/(`denom')^2)" } else { * sret local dens`i'`q' "-((`prob`j'')*(`prob`q''))" sret local dens`i'`q' "(-exp(`s(xb`j')')*exp(`s(xb`q')')/(`denom')^2)" } } } local cat = `matcat'[1,`i'] EqLabel `depvar' `cat' } sret local medef Prob(`depvar') sret local depname `depvar' end program define GenFx_poisson , sclass version 8 GenFx_eform `*' sret local medef E(`s(depname)') end program define GenFx_nbreg , sclass version 8 GenFx_poisson `*' end program define GenFx_zip , sclass version 8 args depvar local mu "exp(`s(xb1)')" if "`e(inflate)'"=="logit" { local cuminf "1/(1+exp(-`s(xb2)'))" local deninf "(`cuminf')*(1-`cuminf')" } else { local cuminf "normprob(`s(xb2)')" local deninf "normd(`s(xb2)')" } sret local cumu11 "`mu'*(1-`cuminf')" sret local dens11 "`mu'*(1-`cuminf')" sret local dens12 "-`mu'*`deninf'" sret local depname `depvar' sret local medef Prob(`depvar') end program define GenFx_zinb, sclass version 8 GenFx_zip `*' end program define GenFx_biprobit , sclass version 8 args v1 v2 bit local rho = e(rho) local srh = sqrt(1-`rho'^2) forval k = 1/4 { local A local C local B if `k'<3 local A - if `k'==1 | `k'==3 local B - if `k'==2 | `k'==3 local C - sret local cumu`k'1 binorm(`A'`s(xb1)',`B'`s(xb2)',`C'`rho') sret local dens`k'1 (`A'normd(`A'`s(xb1)')*normprob((`B'`s(xb2)'-`C'`rho'*`A'`s(xb1)')/`srh')) sret local dens`k'2 (`B'normd(`B'`s(xb2)')*normprob((`A'`s(xb1)'-`C'`rho'*`B'`s(xb2)')/`srh')) } sret local eqname "p00 p01 p10 p11" sret local medef "Prob(`v1',`v2')" end *============================================================ * * [6] SUBROUTINES THAT PROCESS ESTIMATION RESULTS * *============================================================ program define PassToS , sclass version 8 local rhs `*' local Tlist `r(treat)' local ntreat : word count `Tlist' sret local depvar `r(depvar)' sret local rhs `Tlist' `rhs' sret local Tlist `r(treat)' sret local Ntreat `ntreat' end program define ProcEst1 , rclass version 8 tempname b v coef local depvar = e(depvar) mat `b' = e(b) mat `v' = e(V) if "`s(model)'"=="heckprob" { local dim = colnumb(`b',"_cons") } else local dim = colsof(`b')-`s(nap)' mat `v' = `v'[1..`dim',1..`dim'] mat `b' = `b'[1,1..`dim'] local dim = `dim'-1 /* -1 is the constant */ mat `coef' = `b'[1,1..`dim'] local treat : colnames(`coef') mat `coef' = `coef'' return local treat `treat' return local depvar `e(depvar)' return matrix b `b' return matrix coef `coef' return matrix v `v' end program define ProcEst2 , rclass version 8 tempname b v coef temp mat `b' = e(b) mat `v' = e(V) if substr("`s(model)'",1,1)=="o" { local dim = colsof(`b')-`s(ncons)' mat `b' = `b'[1,1..`dim'] } else if "`s(model)'"=="biprobit" { local dim = colsof(`b')-1 mat `b' = `b'[1,1..`dim'] mat `v' = `v'[1..`dim',1..`dim'] *local dim = `dim'-2 } else local dim = colsof(`b')/(`s(nout)'-1)-1 forval i = 1/`s(neq)' { local p = (`i'-1)*(`dim'+1)+1 local q = `p'+`dim'-1 mat `temp' = `b'[1,`p'..`q'] if `i'==1 { mat `coef' = `temp' local treat : colnames(`temp') } else mat `coef' = `coef' \ `temp' } mat `coef' = `coef'' return local depvar `e(depvar)' return local treat `treat' return matrix b `b' return matrix coef `coef' return matrix v `v' end program define ProcEst3 , rclass version 8 local depvar = e(depvar) local v1 : word 1 of `depvar' local v2 : word 2 of `depvar' if "`v2'"=="" { if "`s(model)'"=="zip" | "`s(model)'"=="zinb" { local v2 "inflate" } else local v2 "select" local depvar "`depvar' `v2'" } tempname b v b1 b2 b3 v11 v12 v21 v22 bnew vnew mat `b' = e(b) mat `v' = e(V) local dim = colnumb(`b',"_cons")-1 mat `b1' = `b'[1,1..`dim'] mat `b2' = `b'[1,"`v2':"] mat `b3' = `b1'*0 mat `v11' = `v'["`v1':","`v1':"] mat `v12' = `v'["`v1':","`v2':"] mat `v22' = `v'["`v2':","`v2':"] local e1 : colnames(`b1') local e2 : colnames(`b2') local n1 = colsof(`v11') local n2 = colsof(`v12') * RESHAPING THE VECTOR OF COEFFICIENTS local j = 1 while `j'<=`n2' { local x : word `j' of `e2' if "`x'"!="_cons" { * Does the first eq contains `x' from the second eq? capture display _b[`v1':`x'] if _rc==0 { local dest = colnumb("`v11'","`x'") mat subst `b3'[1,`dest'] = _b[`v2':`x'] } else { local addname `addname' `x' local beta = _b[`v2':`x'] local addbeta `addbeta' `beta' local dim = `dim'+1 } } local j = `j'+1 } local treat `e1' `addname' local ntreat : word count `treat' mat `bnew' = J(2,`dim',0) mat input `b2' = (`addbeta') local nadd = colsof(`b2') mat `b3' = `b3', `b2' mat subst `bnew'[1,1] = `b1' mat subst `bnew'[2,1] = `b3' mat `bnew' = `bnew'' * RESHAPING THE VARIANCE-COVARIANCE MATRIX * increasing dimension of Eq#2 parts & changing the ordering of cols therein local i = 1 local moves = 0 while `i'<=`ntreat' { local var : word `i' of `treat' local beta = `bnew'[`i',2] if `beta'==0 { local dest = (`i'-1)*(`moves'>0) /* dest=0 as long as var contained only in Eq#2 */ Ins0Vec `v22' `dest' `var' mat `v22' = `v22'' Ins0Vec `v22' `dest' `var' mat `v22' = `v22'' Ins0Vec `v12' `dest' `var' } else if `i'<`n1' { /* - no modification needed if var is only in Eq#2 */ local orig = colnumb(`v22',"`var'") MoveVec `v22' `orig' `i' mat `v22' = `v22'' MoveVec `v22' `orig' `i' mat `v22' = `v22'' MoveVec `v12' `orig' `i' local moves = `moves'+1 } local i = `i'+1 } * * Adding row zeros to matrices containing Eq#2 parts mat `v21' = `v12'' local i = `n1'-1 while `i'<`ntreat' { local var : word `i' of `treat' Ins0Vec `v21' `i' `var' Ins0Vec `v11' `i' `var' mat `v11' = `v11'' Ins0Vec `v11' `i' `var' mat `v11' = `v11'' local i = `i'+1 } * RETURNING RESULTS mat `v12' = `v21'' mat `vnew' = ( `v11' , `v12' ) \ ( `v21' , `v22' ) return local depvar `v1' `v2' return local treat `treat' return matrix b `b' return matrix coef `bnew' return matrix v `vnew' end program define ProcEst9 ProcEst1 `*' end program define MoveVec version 8 args touse orig dest sym if `orig'==`dest' { exit } tempname mat col m1 m2 m3 mat `mat' = `touse' local nrow = rowsof(`mat') local ncol = colsof(`mat') mat `col' = `mat'[1..`nrow',`orig'] local pc1 = `dest'-1 local pc2 = `orig'-1 local pc3 = `orig'+1 if `orig'<`dest' { local pc1 = `orig'-1 local pc2 = `orig'+1 local pc3 = `dest'+1 } if `orig'==`ncol' & `dest'==1 { mat `m1' = `mat'[1..`nrow',1..`pc2'] mat `mat' = `col', `m1' } else if `dest'==`ncol' & `orig'==1 { mat `m1' = `mat'[1..`nrow',2..`ncol'] mat `mat' = `m1' , `col' } else if `orig'<`ncol' & `dest'==1 { mat `m2' = `mat'[1..`nrow',`dest'..`pc2'] mat `m3' = `mat'[1..`nrow',`pc3'..`ncol'] mat `mat' = `col', `m2', `m3' } else if `dest'<`ncol' & `orig'==1 { mat `m2' = `mat'[1..`nrow',`pc2'..`dest'] mat `m3' = `mat'[1..`nrow',`pc3'..`ncol'] mat `mat' = `m2', `col',`m3' } else if `orig'==`ncol' & `dest'>1 { mat `m1' = `mat'[1..`nrow',1..`pc1'] mat `m2' = `mat'[1..`nrow',`dest'..`pc2'] mat `mat' = `m1', `col', `m2' } else if `dest'==`ncol' & `orig'>1 { mat `m1' = `mat'[1..`nrow',1..`pc1'] mat `m2' = `mat'[1..`nrow',`pc2'..`dest'] mat `mat' = `m1', `m2', `col' } else if `orig'>`dest' { mat `m1' = `mat'[1..`nrow',1..`pc1'] mat `m2' = `mat'[1..`nrow',`dest'..`pc2'] mat `m3' = `mat'[1..`nrow',`pc3'..`ncol'] mat `mat' = `m1' , `col' , `m2' , `m3' } else { mat `m1' = `mat'[1..`nrow',1..`pc1'] mat `m2' = `mat'[1..`nrow',`pc2'..`dest'] mat `m3' = `mat'[1..`nrow',`pc3'..`ncol'] mat `mat' = `m1' , `m2' , `col', `m3' } mat `touse' = `mat' end program define Ins0Vec version 8 args touse pos name sym tempname mat col m1 m2 mat `mat' = `touse' local nrow = rowsof(`mat') local ncol = colsof(`mat') local sym = ("`sym'"!="") local row = 1+`sym' mat `col' = `mat'[1..`nrow',1]*0 mat coln `col' = `name' if `pos'==0 { mat `mat' = `col', `mat' } else if `pos'==`ncol' { mat `mat' = `mat' , `col' } else { local pos2 = `pos'+1 mat `m1' = `mat'[1..`nrow',1..`pos'] mat `m2' = `mat'[1..`nrow',`pos2'..`ncol'] mat `mat' = `m1' , `col' , `m2' } mat `touse' = `mat' end *============================================================ * * [7] OTHER SUBROUTINES * *============================================================ program define VarTypes , sclass version 8 args touse count local cvars `s(Tlist)' foreach var in `cvars' { capture assert `var'==1 | `var'==0 if `touse' if _rc==0 { local cvars : subinstr local cvars "`var'" "" local dummies `dummies' `var' } } if "`count'"=="on" { foreach var in `cvars' { capture assert `var'==int(`var') if `touse' if _rc==0 local counts `counts' `var' } } sret local Countvars `counts' sret local Dummyvars `dummies' sret local Continvars `cvars' end program define AtOption , sclass version 8 if "`0'"=="" { sret local at sret local method average exit } local at `0' * Searching for occurences of mean, median, zero local count = 0 foreach word in mean median zero { local new : subinstr local at "`word'" " " , count(local flag) if `flag'==1 local method `word' local count = `count'+`flag' } if `count'==0 local method mean * List of variables set to other values than mean/median/zero local user local at : subinstr local at "=" " " , all while "`at'"!="" { gettoken name at : at capture confirm var `name' if _rc==0 local user `user' `name' } sret local at `user' sret local method `method' end program define Mrhs , sclass version 8 local id "`1'" mac shift sret local rhs`id' `*' end program define Mindex , sclass version 8 sret local xb`1' `2' end program define EqLabel , sclass args depvar cat if "`cat'"=="" { qui sum `depvar' if `depvar'!=0 local cat = r(mean) } local label : label (`depvar') `cat' if "`label'"=="" { local label "p`cat'" } else { local cat `label' local label = substr("`label'",1,8) } local eqlab "`s(eqname)' `label'" sret local eqname `eqlab' sret local cat `cat' end program define DumList , sclass version 8 * Saving existing s() macros foreach word in nout type neq ncons nap model { local `word' `s(`word')' } gettoken b 0 : 0 local xvars : colnames `b' * Step 1: Recognizing lists of dummies as tokens tokenize "`0'" , p(" \ ") local args `0' local N = 1 local doit = 1 while `doit'==1 { *local check : subinstr local `"`args'"' "\" , all if "`args'"=="" local doit=0 *if "`check'"=="" | "`args'"=="" local doit=0 else { local pos = index("`args'","\") if `pos'==0 local pos = length("`args'") local tokens`N' = substr("`args'",1,`pos') local tokens`N' : subinstr local tokens`N' "\" " " , all local args = substr("`args'",`pos'+1,length("`args'")) local N = `N'+1 } } local N = `N'-1 * Step 2: Unabbreviating lists of dummies & eliminating dropped vars forval i = 1/`N' { tsunab list`i' : `tokens`i'' local list`i' : list list`i' & xvars } * Step 3: Generating if conditions forval i = 1/`N' { local n : word count `list`i'' if `n'>1 { forval j = 1/`n' { local treat : word `j' of `list`i'' local newlist : subinstr local list`i' "`treat'" " " , all local newlist : subinstr local newlist " " "!=1 & " , all local newlist if `newlist'!=1 local newlist : subinstr local newlist "& !=1 & !=1" " " , all local newlist : subinstr local newlist "!=1 & !=1" " " , all local newlist : subinstr local newlist "if &" "if" , all sret local `treat' `newlist' } } } * Restores s() macros foreach word in nout type neq ncons nap model { sret local `word' ``word'' } end