*! 0.3.2 2009-03-14 | long freese | fix mean calculation ** predictions for asmprobit capture program drop asprvalue capture program drop _Prvasmp program define asprvalue, rclass version 9 if e(cmd) == "asmprobit" { _Prvasmp `0' // local program just for asmprobit -- see below return add exit } preserve syntax [, x(passthru) Cat(string) Base(string) Save Diff Rest(string) BRief Full] * need to sort to calculate means below so accurate for unbalanced panels local idvar "`e(group)'" tempname recordnum sort `idvar', stable by `idvar' : gen `recordnum' = _n tempname b mat `b' = e(b) local allnames : colnames `b' * check if there are any interactions, so that otherwise warning message can be specified local anyX "no" * make list of case-specific variables foreach var of local allnames { local i = index("`var'", "X") if `i' != 0 { local anyX "yes" * is it an alternativeXcase-specific-variable interaction? local temppreX = substr("`var'", 1, `i'-1) local temppostX = substr("`var'", `i'+1, .) * assume that preX are all cats -- TO DO: insert check? local catslist "`catslist' `temppreX'" local isAxA "no" foreach var2 of local allnames { if "`temppostX'"=="`var2'" | "`temppostX'"=="`base'" { local isAxA "yes" local aXalist "`aXalist' `var'" } } * is it an alternativeXalternative interaction? if "`isAxA'" == "no" { local aXclist "`aXclist' `var'" local csvlist "`csvlist' `temppostX'" } } } * if cat is specified, that is the list of categories if "`cat'"!= "" { local catslist = "`cat'" } * make sure either cat() or interactions specified if "`cat'"=="" & "`anyX'"=="no" { di as err "cat() must be specified if no interactions in model" error 999 } local catslist : list uniq catslist local ncatsmin1 : word count `catslist' local numcats = `ncatsmin1' + 1 local csvlist : list uniq csvlist local asvlist : list allnames - aXclist local asvlist : list asvlist - catslist local asvlist : list asvlist - aXalist /* di "altXasv interactions: `aXalist'" di "altXcase interactions: `aXclist'" di "alternatives: `catslist'" di "altspec vars: `asvlist'" di "casespec vars: `csvlist'" di "number of alternatives `ncatsmin1'" */ * decode x() values tokenize `x', parse("()") local x "`3'" local x : subinstr local x "=" " ", all tokenize `x', parse(" ") while "`1'" != "" & "`2'" != "" { capture confirm number `3' if _rc == 0 { * TO DO: check that `1' is alternative-specific variables forvalues i = 1(1)`numcats' { local iplus1 = `i' + 1 confirm number ``iplus1'' local V`1'V`i' = ``iplus1'' } macro shift `iplus1' } else { local V`1' = `2' macro shift 2 } } * HANDLE REST OPTION * rest() = mean by default if "`rest'" == "" { local rest "mean" } *check that rest option includes an allowable option if "`rest'" != "mean" & "`rest'" != "asmean" { di as err "rest(`rest') not allowed" error 999 } foreach var of local csvlist { if "`V`var''" == "" { if "`rest'" == "mean" | "`rest'" == "asmean" { * qui su `var' if e(sample) == 1 & `recordnum' == 1 qui su `var' if e(sample) == 1 // FIX TO MEAN CALCULATION 9/2012 local V`var' = r(mean) } } } foreach var of local asvlist { if "`V`var''" == "" & "`V`var'V1'" == "" { if "`rest'" == "mean" { * qui su `var' if e(sample) == 1 & `recordnum' == 1 qui su `var' if e(sample) == 1 // FIX TO MEAN CALCULATION 9/2012 forvalues i = 1(1)`numcats' { local V`var'V`i' = r(mean) } } if "`rest'" == "asmean" { tempname refdum * this variable will equal 1 for only those cases that indicate base qui gen `refdum' = 1 if e(sample) == 1 local i = 1 foreach catname of local catslist { qui su `var' if `catname' == 1 & e(sample) == 1 local V`var'V`i' = r(mean) * turn off refdum for variables indicating category qui replace `refdum' = 0 if `catname' == 1 & e(sample) == 1 local i = `i' + 1 } * use refdum to get mean for reference category qui su `var' if `refdum' == 1 & e(sample) == 1 local V`var'V`i' = r(mean) } } } * add observations to bottom of dataset local N = _N local firstobs = `N' + 1 // firstobs is the reference number of the first added obs local lastobs = `firstobs'+`ncatsmin1' qui set obs `lastobs' capture drop _addedobs qui gen _addedobs = 1 if _n >= `firstobs' * find unique value for new observations local unique "no" local i = 1234567 while "`unique'" == "no" { qui count if `idvar' == `i' if r(N) == 0 { local unique "yes" } local i = `i' + 1234567 } qui replace `idvar' = `i' in `firstobs'/`lastobs' qui replace `idvar' = `i' in `firstobs'/`lastobs' foreach cat of local catslist { local obs = `firstobs' foreach cat2 of local catslist { * set dummy variables indicating which row is which alternative qui replace `cat' = 1 in `obs' if "`cat'" == "`cat2'" qui replace `cat' = 0 in `obs' if "`cat'" != "`cat2'" * set values for aXc interactions foreach csvar of local csvlist { qui replace `cat'X`csvar' = `V`csvar'' in `obs' if "`cat'" == "`cat2'" qui replace `cat'X`csvar' = 0 in `obs' if "`cat'" != "`cat2'" } local obs = `obs' + 1 } * set all alternative dummies to zero for row indicating reference category qui replace `cat' = 0 in `obs' * set all aXc to zero for row corresponding to reference category foreach csvar of local csvlist { qui replace `cat'X`csvar' = 0 in `obs' } } * set values for alternative-specific variables foreach alt of local asvlist { if "`V`alt''" != "" { qui replace `alt' = `V`alt'' in `firstobs'/`lastobs' } else { forvalues i = 1(1)`numcats' { local obs = `firstobs' + `i' - 1 qui replace `alt' = `V`alt'V`i'' in `obs' } } } * set values for aXa interactions foreach var of local aXalist { local i = index("`var'", "X") local temppreX = substr("`var'", 1, `i'-1) local temppostX = substr("`var'", `i'+1, .) qui replace `var' = `temppreX'*`temppostX' if _addedobs == 1 } * generate predicted probabilities tempname prob * 5/26/06 WORKAROUND FOR STATA BUG (?!) WHERE PREDICT RESORTS DATA tempname order gen `order' = _n qui predict `prob' if _addedobs == 1 sort `order' * reference category name if "`base'" == "" { local base = "base" } * DISPLAY RESULTS * heading local ecmd "`e(cmd)'" local edepvar "`e(depvar)'" di _n as res "`ecmd'" as txt ": Predictions for " as res "`edepvar'" * display predicted probabilities local obs = `firstobs' capture mat drop asprvres tempname tmpprob foreach cat of local catslist { sca `tmpprob' = `prob'[`obs'] mat asprvres = (nullmat(asprvres) \ `tmpprob') local obs = `obs' + 1 } sca `tmpprob' = `prob'[`obs'] mat asprvres = (nullmat(asprvres) \ `tmpprob') mat rownames asprvres = `catslist' `base' mat colnames asprvres = prob if "`diff'" != "" { mat changesav = asprvres - _ASPRVsav tempname display mat `display' = (asprvres, _ASPRVsav, changesav) mat colnames `display' = Current Saved Diff mat list `display', noh } else { mat list asprvres, noh } * display base values for case-specific variables if "`csvlist'" != "" { capture mat drop csvals foreach var of local csvlist { mat csvals = (nullmat(csvals) , `V`var'') } mat colnames csvals = `csvlist' mat rownames csvals = x= if "`brief'" == "" { di _n as txt "case-specific variables" if "`diff'" != "" { mat changecsv = csvals - _ASPRVcsv tempname displaycsv mat `displaycsv' = (csvals \ _ASPRVcsv \ changecsv) mat rownames `displaycsv' = Current Saved Diff mat list `displaycsv', noh } else { mat list csvals, noh } } } * display base values for alternative-specific variables if "`asvlist'" != "" { capture mat drop asvals foreach alt of local asvlist { capture mat drop _tmp if "`V`alt''" != "" { mat _tmp = J(1, `numcats', `V`alt'') } else { forvalues i = 1(1)`numcats' { mat _tmp = (nullmat(_tmp) , `V`alt'V`i'') } } mat asvals = (nullmat(asvals) \ _tmp) } mat rownames asvals = `asvlist' mat colnames asvals = `catslist' `base' if "`brief'" == "" { di _n as txt "alternative-specific variables" if "`diff'" != "" { tempname curasv mat `curasv' = asvals tempname savedasv mat `savedasv' = _ASPRVasv mat changeasv = asvals - `savedasv' mat roweq `curasv' = Current mat roweq `savedasv' = Saved mat roweq changeasv = Dif tempname displayasv mat `displayasv' = (`curasv' \ `savedasv' \ changeasv) mat list `displayasv', noh } else { mat list asvals, noh } } } * display all added observations and values if desired if "`full'" != "" { list `allnames' if _addedobs == 1, noobs } if "`save'" != "" { mat _ASPRVsav = asprvres if "`csvlist'" != "" { mat _ASPRVcsv = csvals } if "`asvlist'" != "" { mat _ASPRVasv = asvals } } * return results if "`diff'" != "" { //! added bj 24jul2008 capture return matrix p = changesav, copy //! capture return matrix csv = changecsv, copy //! capture return matrix asv = changeasv, copy //! } //! else { //! capture return matrix p = asprvres, copy capture return matrix csv = csvals, copy capture return matrix asv = asvals, copy } //! restore end program define _Prvasmp, rclass version 9 preserve syntax [, x(passthru) Cat(string) Base(string) Save Diff Rest(string) BRief Full] if "`cat'" != "" { di as err "(note: cat() ignored when using asprvalue with asmprobit)" } if "`base'" != "" { di as err "(note: base() ignored when using asprvalue with asmprobit)" } local altvar = e(altvar) local numcats = e(k_alt) local asvlist "`e(indvars)'" local csvlist "`e(ind2vars)'" if "`csvlist'" == "" { local csvlist "`e(casevars)'" } local idvar "`e(casevar)'" if "`idvar'" == "" { local idvar "`e(case)'" } * need to sort to calculate means below so accurate for unbalanced panels tempname recordnum sort `idvar', stable by `idvar' : gen `recordnum' = _n * add values to bottom of dataset local N = _N local firstobs = `N' + 1 local lastobs = `firstobs' + `numcats' - 1 qui set obs `lastobs' capture drop _addedobs qui gen _addedobs = 1 if _n >= `firstobs' * find unique value for new observations local unique "no" local i = 1234567 while "`unique'" == "no" { qui count if `idvar' == `i' if r(N) == 0 { local unique "yes" } local i = `i' + 1234567 } qui replace `idvar' = `i' in `firstobs'/`lastobs' * write values for alternative variable with values of alternatives _pecats `altvar' if e(sample) local catvals "`r(catvals)'" forvalues i = 1(1)`numcats' { local cat`i' : word `i' of `catvals' local catslist "`catslist' `e(alt`i')'" local obsnum = `firstobs' + `i' - 1 qui replace `altvar' = `cat`i'' in `obsnum' } * decode x() values tokenize `x', parse("()") local x "`3'" local x : subinstr local x "=" " ", all tokenize `x', parse(" ") while "`1'" != "" & "`2'" != "" { * if `3' exists and is a number, alternative-specific variables being specified capture confirm number `3' if _rc == 0 { * TO DO: check that `1' is alternative-specific variable forvalues i = 1(1)`numcats' { local iplus1 = `i' + 1 confirm number ``iplus1'' local V`1'V`i' = ``iplus1'' } macro shift `iplus1' } else { local V`1' = `2' macro shift 2 } } * HANDLE REST OPTION * rest() = mean by default if "`rest'" == "" { local rest "mean" } *check that rest option includes an allowable option if "`rest'" != "mean" & "`rest'" != "asmean" { di as err "rest(`rest') not allowed" error 999 } foreach var of local csvlist { if "`V`var''" == "" { if "`rest'" == "mean" | "`rest'" == "asmean" { * qui su `var' if e(sample) == 1 & `recordnum' == 1 qui su `var' if e(sample) == 1 // FIX TO MEAN CALCULATION 9/2012 local V`var' = r(mean) } } } foreach var of local asvlist { if "`V`var''" == "" & "`V`var'V1'" == "" { if "`rest'" == "mean" { * qui su `var' if e(sample) == 1 & `recordnum' == 1 qui su `var' if e(sample) == 1 // FIX TO MEAN CALCULATION 9/2012 forvalues i = 1(1)`numcats' { local V`var'V`i' = r(mean) } } if "`rest'" == "asmean" { forvalues i = 1(1)`numcats' { qui su `var' if `altvar' == `cat`i'' & e(sample) == 1 local V`var'V`i' = r(mean) } } } } * set values for alternative-specific variables foreach alt of local asvlist { if "`V`alt''" != "" { qui replace `alt' = `V`alt'' in `firstobs'/`lastobs' } else { forvalues i = 1(1)`numcats' { local obs = `firstobs' + `i' - 1 qui replace `alt' = `V`alt'V`i'' in `obs' } } } * set values for case-specific variables foreach var of local csvlist { qui replace `var' = `V`var'' in `firstobs'/`lastobs' } * generate predicted probabilities tempname prob ** 5/26/06 WORKAROUND FOR STATA BUG (?!) WHERE PREDICT RESORTS DATA tempname order gen `order' = _n * 2008-06-15 list `order' if _addedobs == 1 qui predict `prob' if _addedobs == 1 sort `order' * DISPLAY RESULTS -- whole routine almost the same as asprvalue but not quite * heading local ecmd "`e(cmd)'" local edepvar "`e(depvar)'" di _n as res "`ecmd'" as txt ": Predictions for " as res "`edepvar'" * display predicted probabilities local obs = `firstobs' capture mat drop asprvres tempname tmpprob foreach cat of local catslist { sca `tmpprob' = `prob'[`obs'] mat asprvres = (nullmat(asprvres) \ `tmpprob') local obs = `obs' + 1 } mat rownames asprvres = `catslist' mat colnames asprvres = prob if "`diff'" != "" { mat changesav = asprvres - _ASPRVsav tempname display mat `display' = (asprvres, _ASPRVsav, changesav) mat colnames `display' = Current Saved Diff mat list `display', noh } else { mat list asprvres, noh } * display base values for case-specific variables if "`csvlist'" != "" { capture mat drop csvals foreach var of local csvlist { mat csvals = (nullmat(csvals) , `V`var'') } mat colnames csvals = `csvlist' mat rownames csvals = x= if "`brief'" == "" { di _n as txt "case-specific variables" if "`diff'" != "" { mat changecsv = csvals - _ASPRVcsv tempname displaycsv mat `displaycsv' = (csvals \ _ASPRVcsv \ changecsv) mat rownames `displaycsv' = Current Saved Diff mat list `displaycsv', noh } else { mat list csvals, noh } } } * display base values for alternative-specific variables if "`asvlist'" != "" { capture mat drop asvals foreach alt of local asvlist { capture mat drop _tmp if "`V`alt''" != "" { mat _tmp = J(1, `numcats', `V`alt'') } else { forvalues i = 1(1)`numcats' { mat _tmp = (nullmat(_tmp) , `V`alt'V`i'') } } mat asvals = (nullmat(asvals) \ _tmp) } mat rownames asvals = `asvlist' mat colnames asvals = `catslist' if "`brief'" == "" { di _n as txt "alternative-specific variables" if "`diff'" != "" { tempname curasv mat `curasv' = asvals tempname savedasv mat `savedasv' = _ASPRVasv mat changeasv = asvals - `savedasv' mat roweq `curasv' = Current mat roweq `savedasv' = Saved mat roweq changeasv = Dif tempname displayasv mat `displayasv' = (`curasv' \ `savedasv' \ changeasv) mat list `displayasv', noh } else { mat list asvals, noh } } } * display all added observations and values if desired if "`full'" != "" { list `allnames' if _addedobs == 1, noobs } if "`save'" != "" { mat _ASPRVsav = asprvres if "`csvlist'" != "" { mat _ASPRVcsv = csvals } if "`asvlist'" != "" { mat _ASPRVasv = asvals } } * return results capture return matrix p = asprvres, copy capture return matrix csv = csvals, copy capture return matrix asv = asvals, copy restore end exit * 0.2.0 - jf - 5/26/06 - workaround for bug in Stata where predict resorts * 0.1.9 - jf - 12/19/05 - add returns * 0.1.8 - jf - 9/8/05 - warning but not error with cat() or base() with asmprobit * 0.1.7 - jf - 7/24/05 - fix asmean for asmprobit bug * 0.1.6 - jf - 7/19/05 - add heading to output * 0.1.5 - jf - 7/18/05 - bug fix * 0.1.4 - jf - 7/15/05 - add asmprobit (kludgy) - jf * 0.1.3 - jf - 7/15/05 - fix to allow = in x() * 0.1.2 - jf - 7/11/05 - bug fix * 0.1.1 - jf - 6/15/05 - change refcat() to base() * 0.1.0 - jf - 6/11/05 * 0.2.1 - jf - 7/2/07 - fix for changes in stata 7 asmprobit routine * 0.3.0a - bj 24jul2008 for work with estout * 0.3.0 2008-06-15 jsl * 0.3.1 2009-03-14