You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

698 lines
21 KiB
Plaintext

7 months ago
*! 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