*! version 4.3 27Aug04 * Written by Jonah B. Gelbach, Dept of Economics, Univ of MD at College Park * Version 1.0 30Jul1999 * * Version 2.0 version 31Jan2001 (added weights) * * Version 3.0 * 1. fixes a bug that occurred when user lists same vars multiple times * 2. chgs to stat version 7 * * Version 4.0 (work started 8/15/03 and finished 8/18/03) * 1. allows user to request results for only a subset of observations * 2. adds baseline() option that tells margfx to set certain vars to * baseline values for calculating marginal effects for binary vars * * 09-22-03 -> fixed problem with long strings * (only occurs when report() option called with long arg) * * Version 4.1 (07-09-04) * * --Chgd code to drop obs from calculation of margfx if they * * 1. have zero weight * 2. were dropped from probit/logit model (eg b/c of collinearity) * * Version 4.2 (8-12-04) * * --Fixing problems in 4.1: * * 1. doesn't report all marg fx if report() option not used * 2. e(sample) condn doesn't work right when run margfx after running probit * * * Version 4.3 (08-27-04) * * --Fixing problems in 4.2: * * 1. didn't correctly handle case with only binary vars (a conditional on `contin' was wrongly "" instead of ".") * 2. didn't correctly handle case when margfx is called after running model (e(sample) conditional had to be fixed) * program define margfx version 7.0 di preserve /* preserving data so i can mess it up */ *checking to see whether this is a replay -- need to do manually (i.e. w/out replay fctn) bc want to be able to use if/in local varlist "optional" local if "optional" local in "optional" local weight "optional" local weight "aweight fweight" local options "BINary(string) CONTin(string) MODEL(string) QUIetly DONE ROBust CLUster(string) REPOrt(string) BASEline(string) AMEANLH AMEANLHIF(string) " parse "`*'" /* dealing with some options that need to be set if empty */ if "`report'"=="" { local report " `binary' `contin' " } else { local report " `report' " } /* this is done to ensure there is space-padding on either side of list */ if "`baseline'"=="" { local baseline "__NULL__" } /* note syntax of `baseline' option: var1=value1 var2=value2 ... varK=valueK */ /* done dealing with some options that need to be set if empty */ if "`model'" == "" & ("`robust'" ~= "" | "`cluster'" ~= "") { /* user wants robust variance but didn't specify a model */ if "$S_E_vce" == "" { /* existing estimates aren't robust */ di "You have specified the robust and/or cluster options, but" di "(1) You didn't specify a model to use, and" _new di "(2) Existing variance matrix estimate is not robust." _new di "-margfx- won't be part of your charade." exit } /* end of if */ else if "`cluster'" ~= "$S_E_cvn" { /* user declared a clustering var dif from existing */ di "You have not specified a model" di "You do specify the clustering variable `cluster'." di "But the existing covariance matrix was calculated using" di "the clustering variable $S_E_cvn" di "(if you don't see a variable name, that means there was no cluster." di "Try again without this error." _new exit } /* end of else if */ } /* end of if model */ *making unique---this will prevent conformability errors when user accidentally puts same var in list mult times if "`binary'" ~= "" { uniqify `binary' local binary " $uniqified " } /* end if */ if "`contin'" ~= "" { uniqify `contin' local contin " $uniqified " } /* end if */ tempname V vm m partial oldb oldv if "`model'" ~= "" & "`done'" ~= "" { di "You specified both that the model `model' should be used to generate" di "new estimates and that existing estimates should be used (the `done' option)." _new di "Make up your mind!" exit } /* crashing bc model and done both nonmissing */ *next line added for v4.3, 27aug04. need it outside of if block b/c is used even when `model' is specified explicitly tempvar esample if "`model'" == "" { if "$S_E_cmd" ~= "probit" & "$S_E_cmd" ~= "logit" { /* no existing estimates, or neither probit/logit */ di "According to global macro S_E_cmd (which is currently $S_E_cmd)," di "the last command to use matrix post was neither logit nor probit" di "or there is no last command on record" _new di "Either specify a varlist, binary/contin lists, and a valid model" di "or run a probit/logit and try again" exit } else { /* setting model and `esample' tempvar */ local model "$S_E_cmd" *next line added for v4.3 gen `esample' = e(sample) } /* end of setting model and `esample' tempvar */ } /* done with model test */ /* next block takes care of situation where either no arguments or neither binary nor contin macros are supplied */ if "`*'" == "" { local varleq = 0 } else if "`binary'" == "" & "`contin'" == "" { local varleq = 0 } else { /* if only one of binary/contin is specified, want to confirm that varlist is, too, which means it has to have dimension 1 */ local dummy : word count `varlist' capture assert `dummy' == 1 if _rc == 9 { di _new "You have specified either/both the binary/contin argument(s) but no varlist." _new if "$S_E_cmd" == "logit" | "$S_E_cmd" == "probit" { /* can use existing estimates */ di "-margfx- will use existing estimates from last command, $S_E_cmd" local varleq = 0 local binary local contin local varlist local model "$S_E_cmd" } /* end of if */ else { /* no existing estimates, or neither probit/logit */ di "According to global macro S_E_cmd (which is currently $S_E_cmd)," di "the last command to use matrix post was neither logit nor probit" di "or there is no last command on record" _new di "Either specify a varlist and binary/contin lists" di "or run a probit/logit and try again" exit } /* end of else statement */ } /* end of rc==9 code block */ } /* end of else statement */ /* need this to handle weights */ tempvar weightvar if "`weight'" ~= "" { local weight = "[`weight'`exp']" local sub = substr("`exp'",2,.) gen `weightvar' = `sub' } /* don't need anything when it's already empty */ else { /* setting `weightvar' to 1 */ gen `weightvar' = 1 } if "`done'" == "done" { /* user asked for existing estimates to be used */ if "$S_E_cmd" == "logit" | "$S_E_cmd" == "probit" { /* can use existing estimates */ local varleq = 0 local binary local contin } /* ok to proceed */ else { /* no existing estimates, or neither probit/logit */ di "According to global macro S_E_cmd (which is currently $S_E_cmd)," di "the last command to use matrix post was neither logit nor probit" di "or there is no last command on record" _new di "Either specify a varlist and binary/contin lists" di "or run a probit/logit and try again" exit } /* end of else statement */ } /* end of if done block */ if "`varleq'" == "0" { /* no varlist, so must be based on earlier estimates */ local model "$S_E_cmd" local done "done" matrix oldb = get(_b) local varlist : colnames(oldb) /* stripping _cons off of varlist */ local dummy "`varlist'" local dnum : word count `varlist' parse "`varlist'", parse(" ") local varlist local i 1 while `i' < `dnum' { local varlist "`varlist' `1'" macro shift local i = `i' + 1 } /* now have to figure out which variables are continuous */ parse "`varlist'", parse(" ") local i 1 /* this nifty code lifted from dprobit.ado */ while "``i''"!="" { capture assert ``i''==0 | ``i''==1 /*if `use'*/ if _rc==0 { /* this var is a dummy -- assertion is true */ global S_E_dum "$S_E_dum 1" local binary "`binary' ``i''" } else { global S_E_dum "$S_E_dum 0" local contin "`contin' ``i''" } local i = `i' + 1 } * global S_E_dum "$S_E_dum 0" local varlist = "$S_E_depv" *next line added in v4.3, 27aug04 local report " `binary' `contin' " } /* end of if "`varleq'" == "0" */ if "`done'" == "done" { /* for explanation of action to user before execution */ local message "Using results from" } else { local message "Running" } di _newline "`message' `model' of depvar" _column(37) "`varlist'" di "on rhs continuous variables" _column(37) "`contin'" di "and rhs binary variables" _column(37) "`binary'" _new local numbin : word count `binary' /* number of binary/contin vars */ local numcont: word count `contin' local numvars = `numbin' + `numcont' matrix m = J(1,`numvars',0) /* initializing margfx vector */ matrix vm = J(`numvars',`numvars',0) /* initializing cov matrix */ if "`done'" ~= "" { /* the model was estimated before invoking margfx command */ `quietly' di "Existing `model' estimates, ordered from binary to continuous, follow." if "$S_E_vce" == "Robust" { /* robust if */ local robust "robust" di "Note: robust variance estimates were used." if "$S_E_cvn" ~= "" { /* cluster if */ local cluster "$S_E_cvn" di "Note: clustering variable was $S_E_cvn." } /* end of cluster if */ } /* end of robust if */ di local S_E_ll = _result(2) local S_E_mdf = _result(3) local S_E_chi = _result(6) local S_E_cn "$S_E_cn" matrix oldb = get(_b) matrix oldv = get(VCE) local wconst = `numvars' + 1 matrix newb = J(1,`wconst',0) /* initializing coef vector with constant */ matrix newv = J(`wconst',`wconst',0) /* initializing cov matrix with constant */ local row 1 /* initializing row and column counters */ local col 1 local temp "`binary' `contin' _cons" parse "`temp'", parse(" ") while `col' <= `wconst' { /* loop for columns */ local row 1 while `row' <= `wconst' { /* loop for rows */ local rowvar "``row''" local colvar "``col''" matrix x = J(1,1,0) /* stupid but necessary -- stata glitch in names */ matrix x = oldv["`rowvar'","`colvar'"] matrix newv[`row',`col'] = x[1,1] /* doing covs */ if `row' == 1 { /* doing betas */ matrix x = oldb[1,"`colvar'"] matrix newb[1,`col'] = x[1,1] } local row = `row' + 1 /* increment row counter */ } /* end of row loop */ local col = `col' + 1 /* increment col counter */ } /* end of col loop */ matrix rownames newb = y1 matrix colnames newb = `binary' `contin' _cons matrix rownames newv = `binary' `contin' _cons matrix colnames newv = `binary' `contin' _cons matrix post newb newv /* posting coef and cov matrices */ `quietly' matrix mlout } /* done with `done' stuff */ /* dropping unused observations -- data is preserved above */ tempvar use quietly mark `use' `if' `in' /* marking out unusable observations */ quietly markout `use' `binary' `contin' `varlist' /* marking out unusable observations */ local backif "`if'" if "`if'" == "" { local if "if `use' == 1 & `weightvar'>0" } else { local if "`if' & `use' == 1 & `weightvar'>0" } quietly keep `if' `in' /* deleting unusables and user-defined nonusers no longer need to use if/in conditions */ local if "`backif'" /* done dropping unused observations */ if "`done'" == "" { /* we'll have to estimate the underlying model */ if "`robust'" ~= "" { /* robust if */ di "Note: robust variance estimates will be used." local robmac ", robust" if "`cluster'" ~= "" { local clusvar "cluster(`cluster')" di "Note: clustering variable is `cluster'." } /* end of cluster inside robust */ } /* end of robust if */ else if "`cluster'" ~= "" { local clusvar ", cluster(`cluster')" di "Note: robust variance estimates will be used." di "Note: clustering variable is `cluster'." } /* end of else if cluster */ di `quietly' `model' `varlist' `binary' `contin' `weight' `robmac' `clusvar' local S_E_ll = _result(2) local S_E_mdf = _result(3) local S_E_chi = _result(6) local S_E_cn "$S_E_cn" } /* next line added 9Jul04 to avoid including obs dropped from `model' */ di di "Dropping observations that were dropped from estimation..." if "`done'"=="" { /* we estimated the model ourself, so we need to make `esample' var now */ gen `esample'=e(sample) } /* end of we estimated the model ourself, so we need to make `esample' var now */ keep if `esample'==1 quietly count local numobs = _result(1) tempname var matrix `var' = get(VCE) /* getting coeff and covar matrices from last est command */ /* code to deal with dropped vars. NOTE: cannot use "foreach var" bc "`var'" is a matrix!! */ local included : rownames `var' *initializing local newrep local newbin local newcon /* note: __can't__ do this with index() or match(), as they truncate long strings */ foreach invar in `included' { /* looping over included vars */ foreach repvar in `report' { /* looping over report vars */ if "`invar'"=="`repvar'" { local newrep " `newrep' `repvar' " } } /* end of looping over report vars */ foreach binvar in `binary' { /* looping over binary vars */ if "`invar'"=="`binvar'" { local newbin " `newbin' `binvar' " continue } } /* end of looping over binary vars */ foreach convar in `contin' { /* looping over contin vars */ if "`invar'"=="`convar'" { local newcon " `newcon' `convar' " continue } } /* end of looping over contin vars */ } /* end of looping over included vars */ local binary "`newbin'" /* replacing with actually included vars */ local contin "`newcon'" /* replacing with actually included vars */ local report "`newrep'" /* replacing with actually included vars */ /* need to redo this bc of possibility of dropped vars */ local numbin : word count `binary' /* number of binary/contin vars */ local numcont: word count `contin' local numvars = `numbin' + `numcont' if `numbin' == 0 { local binary "." } if `numcont' == 0 { local contin "." } local donebin "." local c 0 /* creating counter for binary vars */ local v 0 /* overall counter */ while `c' < `numbin' { /* doing the margfx for binary vars */ local i 0 /* counter for donebin and bintodo */ local temp "`binary'" parse "`temp'", parse(" ") while `i' < `c' { /* creating donebin */ if "`donebin'" ~= "." {local donebin "`donebin' `1' "} macro shift local i = `i' + 1 } while `i' == `c' { /* dealing w/current trt var */ local i = `i' + 1 macro shift local bintodo "" } while `i' > `c' & `i' < `numbin' { /* creating bintodo */ if "`bintodo'" ~= "." {local bintodo "`bintodo' `1' "} macro shift local i = `i' + 1 } local c = `c' + 1 /* incrementing c counter */ local v = `v' + 1 /* incrementing v counter */ if `c' == `numbin' { /* we're on the last binary variable */ local bintodo "." } local treat : word `c' of `binary' local varnum = `v' /* note: __can't__ do this with index() or match(), as they truncate long strings */ /* this loop does equivalent by returning 1 in local macro `reported' if this var is to be reported and 0 otherwise */ local reported 0 /* initializing */ foreach repvar in `report' { /* test to see whether " `treat' " is in `report' string */ if "`repvar'"=="`treat'" { local reported = 1 } } /* end of test to see whether " `treat' " is in `report' string */ if (`reported'==1) { /* test to see whether " `treat' " is in `report' string */ bin `treat' `weight', donebin(`donebin') bintodo(`bintodo') contin(`contin') v(`v') model(`model') /* */ baseline(`baseline') matrix rownames part`varnum' = `treat' if `c'==1 { /* first var, so `partial' doesn't exist */ matrix `partial' = part`varnum' } else { /* not first var, so `partial' does exist */ matrix `partial' = `partial' \ part`varnum' } /* done updating `partial' vector */ } /* end of " `treat' " is in `report' string */ else { /* " `treat' " is not in `report' string */ local wconst = `numvars' + 1 if `c'==1 { /* first var, so `partial' doesn't exist */ matrix `partial' = J(1,`wconst',0) /* row vector of 0s as placeholder */ matrix rownames `partial' = `treat' } else { /* not first var, so `partial' does exist */ mat m[1,`varnum']=0 /* marginal effect is 0 if don't vary X */ mat part`varnum' = J(1,`wconst',0) /* row vector of 0s as placeholder */ matrix `partial' = `partial' \ part`varnum' } } /* end of " `treat' " is not in `report' string */ local donebin "" local bintodo "" } /* end of c loop for binary vars */ local c 0 /* reinitializing c counter -- note no reinit for v */ while `c' < `numcont' { /* doing the margfx for continuous vars */ local c = `c' + 1 /* incrementing c counter */ local v = `v' + 1 /* incrementing v counter */ local treat : word `c' of `contin' local varnum = `v' /* note: __can't__ do this with index() or match(), as they truncate long strings */ /* this loop does equivalent by returning 1 in local macro `reported' if this var is to be reported and 0 otherwise */ local reported 0 /* initializing */ foreach repvar in `report' { /* test to see whether " `treat' " is in `report' string */ if "`repvar'"=="`treat'" { local reported = 1 } } /* end of test to see whether " `treat' " is in `report' string */ if (`reported'==1) { /* this var is reported */ con `treat' `weight', contin(`contin') binary(`binary') v(`v') model(`model') matrix rownames part`varnum' = `treat' if (`c'==1 & `numbin' == 0) { /* first var, so `partial' doesn't exist */ matrix `partial' = part`varnum' } else { /* not first var, so `partial' does exist */ matrix `partial' = `partial' \ part`varnum' } /* done updating `partial' vector */ } /* end of " `treat' " is in `report' string */ else { /* " `treat' " is not in `report' string */ local wconst = `numvars' + 1 if (`c'==1 & `numbin' == 0) { /* first var, so `partial' doesn't exist */ matrix `partial' = J(1,`wconst',0) /* row vector of 0s as placeholder */ matrix rownames `partial' = `treat' } else { /* not first var, so `partial' does exist */ mat m[1,`varnum']=0 /* marginal effect is 0 if don't vary X */ mat part`varnum' = J(1,`wconst',0) /* row vector of 0s as placeholder */ matrix `partial' = `partial' \ part`varnum' } } /* end of " `treat' " is not in `report' string */ local donecon "" local contodo "" } /* end of c loop for continuous vars */ /* getting conformable colnames for `partial' matrix */ if "`binary'"~="." { *fixed next line in v4.3 (used to test "", now ".") if "`contin'"~="." { mat colnames `partial' = `binary' `contin' _cons } else { mat colnames `partial' = `binary' _cons } } /* done checking on binary */ else { if "`contin'"~="." { mat colnames `partial' = `contin' _cons } /* this really shouldn't ever happen */ else { mat colnames `partial' = `binary' _cons } } /* done getting conformable colnames for `partial' matrix */ matrix `V' = `partial'*`var'*`partial'' /* creating overall covar matrix */ if "`contin'" == "." {local contin} if "`binary'" == "." {local binary} matrix colnames `V' = `binary' `contin' matrix colnames m = `binary' `contin' tempname reportm reportV local numrep : word count `report' mat `reportm' = J(1,`numrep',0) mat colnames `reportm' = `report' mat `reportV' = J(`numrep',`numrep',0) mat colnames `reportV' = `report' mat rownames `reportV' = `report' local r 0 foreach rowvar in `report' { /* row vars in `report' from m and `V' */ local r = `r' + 1 mat `reportm'[1,`r'] = m[1,"`rowvar'"] /* getting estimated marginal effect */ local c 0 foreach colvar of varlist `report' { /* column vars in `report' from m and `V' */ local c = `c' + 1 mat `reportV'[`r',`c'] = `V'["`rowvar'","`colvar'"] /* getting cov term for row and col vars */ } /* end of row vars in `report' from m and `V' */ } /* end of column vars in `report' from m and `V' */ local length = length("`numobs'") while `length' < 8 { local numobs " `numobs'" /* adding a space at front */ local length = `length' + 1 } di _new _new "Mean of marginal effects," _skip(30) "Number of obs =`numobs'" di "observation-by-observation" _new _new di "Reporting coeficients for variables:" di ltrim("`report'") _new if "`baseline'"~="__NULL__" { di "Baseline conditions for binary variables are:" di "`baseline'" _new } matrix post `reportm' `reportV', depname(`varlist') obs(`numobs') matrix mlout restore /* putting the data back just the way it was */ macro drop s_mean /* doing saved results */ global S_E_nobs "`numobs'" global S_E_if "`if'" global S_E_in "`in'" global S_E_mod "`model'" global S_E_cmd "margfx" global S_E_depv "`varlist'" global S_E_bin "`binary'" global S_E_con "`contin'" global S_E_cvn "`cluster'" global S_E_vce "`robust'" global S_E_ll "`S_E_ll'" global S_E_mdf "`S_E_mdf'" global S_E_chi2 "`S_E_chi'" global S_E_cn "`S_E_cn'" if "`ameanlh'" ~= "" { /* user wants to report mean of lhs in same way ara does */ if "`ameanlhif'"~="" { if "`if'"=="" { local if "if `ameanlhif'" } else { local if "`if' & `ameanlhif'" } } qui sum `varlist' `if' `in' `weight' di _newline " __mean | " _result(3) " . " _newline } end program define bin local varlist "required existing max(1)" local options "DONEBIN(string) BINTODO(string) CONTIN(string) V(string) MODEL(string) BASELINE(string)" local weight "aweight fweight" parse "`*'" local varnum = `v' if "`donebin'" == "." { local donebin "" } if "`bintodo'" == "." { local bintodo "" } if "`contin'" == "." { local contin "" } if "`weight'" ~= "" { local weight = "[`weight'`exp']" } /* don't need anything when it's already empty */ tempvar backup treat hat0 hat1 effect index0 index1 phi0 phi1 delphi phirat tempname b v partial V quietly gen double `backup' = `varlist' /* doing each observation's treated value, including baseline stuff. note that the treated value for this var has to have baseline value of other vars. */ if "`baseline'"~="__NULL__" { /* dealing with manual baseline override */ local baselist /* initializing list of baseline vars and their backup values */ local t 0 /* counter for baseline vars */ foreach token in `baseline' { /* looping over tokens of `baseline' lmac */ local t = `t' + 1 parse "`token'", parse("=") local realvar "`1'" /* var involved in baseline override */ tempvar backup`t' qui gen `backup`t'' = `realvar' /* backing up this var */ local baselist "`baselist' `realvar'=`backup`t''" /* allows easy replacing with original values */ qui replace `token' /* this sets the current variable's value to the specified baseline */ } /* end of looping over tokens of `baseline' lmac */ } /* end of dealing with manual baseline override */ /* have to set this var to 1 for treated value, since presumably the baseline block above just set it to something else */ quietly replace `varlist' = 1 /* now we can predict the treated value */ quietly predict double `index1', index /* done doing each observation's treated value, including baseline stuff */ /* density if treated */ if "`model'" == "probit" { quietly gen double `hat1' = normprob(`index1') quietly gen double `phi1' = normd(`index1') /* density evaluated w/treat */ } else if "`model'" == "logit" { quietly gen double `hat1' = exp(`index1') / (1 + exp(`index1')) /* logit cdf value */ quietly gen double `phi1' = `hat1'*(1 - `hat1') /* logit pdf value */ } /* note: we do NOT yet want to replace the other vars with their baseline values. we do that AFTER finishing evthing here */ quietly replace `varlist' = 0 /* doing each observation's untreated value */ quietly predict double `index0', index /* density if not treated */ if "`model'" == "probit" { quietly gen double `hat0' = normprob(`index0') quietly gen double `phi0' = normd(`index0') /* density evaluated w/out treat */ } else if "`model'" == "logit" { quietly gen double `hat0' = exp(`index0') / (1 + exp(`index0')) /* logit cdf value */ quietly gen double `phi0' = `hat0'*(1 - `hat0') /* logit pdf value */ } quietly gen double `effect' = `hat1' - `hat0' /* each observation's treatment effect */ quietly gen double `delphi' = `phi1' - `phi0' /* each observation's dif in density by treatment */ quietly gen double `phirat' = `phi1'/`delphi' /* will be useful in mat vecaccum below */ quietly sum `effect' `weight' local mean = _result(3) matrix m[1,`varnum'] = `mean' matrix vecaccum part`varnum' = `delphi' `donebin' `phirat' `bintodo' `contin' `weight' /* creating the row vector of totals of first derivs of the trt effect wr2 the parameter vector `d' is "donebin" binary variables, `c' is continuous variables */ local numobs = 1/_result(1) /* inverse number of obs in vecaccum */ mat part`varnum' = part`varnum' * `numobs' /* partial vector for this var is now in mean form*/ if "`baseline'"~="__NULL__" { /* replacing manual baseline override values with actual values */ foreach token in `baselist' { /* looping over tokens of `baseline' lmac */ qui replace `token' /* this replaces the variable's value to the original one (see "foreach token..." above) */ } /* end of looping over tokens of `baseline' lmac */ } /* end of dealing with manual baseline override */ /* this is extraneous when "`baseline'" ~= "__NULL__" */ quietly replace `varlist' = `backup' end program define con local varlist "required existing max(1)" local options "CONTIN(string) BINARY(string) V(string) MODEL(string)" local weight "aweight fweight" parse "`*'" di "contin list is `contin'" local varnum = `v' if "`binary'" == "." {local binary} if "`weight'" ~= "" { local weight = "[`weight'`exp']" } /* don't need anything when it's already empty */ tempvar backup treat hat dense index product logder tempname b v partial V *===> doing the mean marginal effect local coef = _b[`varlist'] /* getting the coefficient for this variable */ quietly predict double `index', index /* predicting index */ /* doing stuff to create scalar part of partial vector, holding beta(k) constant */ if "`model'" == "probit" { quietly gen double `dense' = normd(`index') /* evaluating density at index */ quietly sum `dense' `weight' /* necessary to add back into partial vector for k */ local k = _result(3) quietly replace `dense' = `coef'*`dense' quietly sum `dense' `weight' matrix m[1,`varnum'] = _result(3) } else if "`model'" == "logit" { gen double `hat' = exp(`index') / (1 + exp(`index')) /* logit cdf value */ quietly gen double `logder' = (1-`hat')*`hat' /* need to add back into partl vector for k */ quietly sum `logder' `weight' local k = _result(3) /* this gets added later */ quietly replace `logder' = `coef'*`logder' /* now computing the mean marg effect */ quietly sum `logder' `weight' matrix m[1,`varnum'] = _result(3) } *===> doing the variance calculation if "`model'" == "probit" { /* making var needed for vecaccum below */ quietly gen double `product' = -`index'*`dense' /* product of index and its density */ } if "`model'" == "logit" { /* making var needed for vecaccum below */ quietly gen double `product' = (1 - 2*`hat')*`logder' /* logit deriv stuff */ } matrix vecaccum part`varnum' = `product' `binary' `contin' `weight' /* creating the row vector of totals of first derivs of the marg effect wr2 the parameter vector */ local numobs = 1/_result(1) /* inverse number of obs involved in vecaccum */ mat part`varnum' = part`varnum' * `numobs' /* partial vector is now in mean form */ mat part`varnum'[1,`varnum'] = `k' + part`varnum'[1,`varnum'] end *subroutine to get a unique token list *need this to avoid putting vars in multiple times when raw varlist *has same var listed more than once * *note that the multiple loops below are nec b/c stata's string functions *truncate all strings longer than 80 chars to 80 chars * *go figure. program define uniqify *`macname' is where we will put uniqified string syntax varlist unab string : `varlist' local n 0 /* counter for newstring macros */ foreach token of local string { if length("`newstring`n''") >= 57 { /* need to start a new string b/c of irritating stata limits on string length */ local n = `n' + 1 } /* end of need to start a new string b/c of irritating stata limits on string length */ local match = 0 foreach m of numlist 0/`n' { /* looping over newstring macros */ local match = `match' + match("`newstring`m''", "*`token'*" ) } /* end of looping over newstring macros */ *di "token is `token' and match=`match'" if `match'==0 { /*not already there */ local newstring`n' "`newstring`n'' `token'" } /* done with not already there */ } *di "n counter is now `n'. newstring macros are...." foreach m of numlist 0/`n' { /* looping over newstring macros */ local newstring "`newstring' `newstring`m''" } /* end of looping over newstring macros */ *di "done and newstring is " _new "`newstring'" global uniqified "`newstring'" end