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.

344 lines
10 KiB
Plaintext

*! version 1.1.0 05nov2008 Ben Jann
program define eststo, byable(onecall)
version 8.2
local caller : di _caller()
// --- eststo clear ---
if `"`1'"'=="clear" {
if `"`0'"'!="clear" {
di as err "invalid syntax"
exit 198
}
if "`_byvars'"!="" error 190
_eststo_clear
exit
}
// --- update globals ---
_eststo_cleanglobal
// --- eststo dir ---
if `"`1'"'=="dir" {
if `"`0'"'!="dir" {
di as err "invalid syntax"
exit 198
}
if "`_byvars'"!="" error 190
_eststo_dir
exit
}
// --- eststo drop ---
if `"`1'"'=="drop" {
if "`_byvars'"!="" error 190
_eststo_`0'
exit
}
// --- eststo store (no by) ---
if "`_byvars'"=="" {
version `caller': _eststo_store `0'
exit
}
// --- eststo store (by) ---
// - check sorting
local sortedby : sortedby
local i 0
foreach byvar of local _byvars {
local sortedbyi : word `++i' of `sortedby'
if "`byvar'"!="`sortedbyi'" error 5
}
// - parse command on if qualified
capt _on_colon_parse `0'
if _rc error 190
if `"`s(after)'"'=="" error 190
local estcom `"`s(after)'"'
local 0 `"`s(before)'"'
if substr(trim(`"`estcom'"'),1,3)=="svy" {
di as err "svy commands not allowed with by ...: eststo:"
exit 190
}
AddBygrpToIfqualifier `estcom'
// - parse syntax of _eststo_store call in order to determine
// whether title() or missing was specified (note that
// -estimates change- cannot be used to set the titles since
// it does not work with -noesample-)
TitleAndMissing `0'
// - generate byindex
tempname _byindex
qui egen long `_byindex' = group(`_byvars'), label `missing'
qui su `_byindex', meanonly
if r(N)==0 error 2000
local Nby = r(max)
// - loop over bygroups
forv i = 1/`Nby' {
local ibylab: label (`_byindex') `i'
di as txt _n "{hline}"
di as txt `"-> `ibylab'"' // could be improved
if `titleopt'==0 local ibytitle
else if `titleopt'==1 local ibytitle `" title(`ibylab')"'
else if `titleopt'==2 local ibytitle `", title(`ibylab')"'
capture noisily {
version `caller': _eststo_store `0'`ibytitle' : `estcmd'
}
if _rc {
if "`_byrc0'"=="" error _rc
}
}
end
prog TitleAndMissing
capt syntax [anything] , Title(string) [ MISsing * ]
if _rc==0 {
c_local titleopt 0
c_local missing "`missing'"
}
else {
syntax [anything] [ , MISsing * ]
if `"`missing'`options'"'!="" c_local titleopt 1
else c_local titleopt 2
c_local missing "`missing'"
}
end
program AddBygrpToIfqualifier
syntax anything(equalok) [if/] [in] [using] [fw aw pw iw] [, * ]
local estcom `"`macval(anything)' if (\`_byindex'==\`i')"'
if `"`macval(if)'"'!="" {
local estcom `"`macval(estcom)' & (`macval(if)')"'
}
if `"`macval(in)'"'!="" {
local estcom `"`macval(estcom)' `macval(in)'"'
}
if `"`macval(using)'"'!="" {
local estcom `"`macval(estcom)' `macval(using)'"'
}
if `"`macval(weight)'"'!="" {
local estcom `"`macval(estcom)' [`macval(weight)'`macval(exp)']"'
}
if `"`macval(options)'"'!="" {
local estcom `"`macval(estcom)', `macval(options)'"'
}
c_local estcmd `"`macval(estcom)'"'
end
program define _eststo_clear
local names $eststo
foreach name of local names {
capt estimates drop `name'
}
global eststo
global eststo_counter
end
program define _eststo_dir
if `"$eststo"'!="" {
estimates dir $eststo
}
end
program define _eststo_cleanglobal
local enames $eststo
if `"`enames'"'!="" {
tempname hcurrent
_return hold `hcurrent'
qui _estimates dir
local snames `r(names)'
_return restore `hcurrent'
}
local names: list enames & snames
global eststo `names'
if "`names'"=="" global eststo_counter
end
program define _eststo_drop
local droplist `0'
if `"`droplist'"'=="" {
di as error "someting required"
exit 198
}
local names $eststo
foreach item of local droplist {
capt confirm integer number `item'
if _rc {
local dropname `item'
}
else {
if `item'<1 {
di as error "`item' not allowed"
exit 198
}
local dropname est`item'
}
local found 0
foreach name in `names' {
if match("`name'",`"`dropname'"') {
local found 1
estimates drop `name'
local names: list names - name
di as txt "(" as res "`name'" as txt " dropped)"
}
}
if `found'==0 {
di as txt "(no matches found for " as res `"`dropname'"' as txt ")"
}
}
global eststo `names'
end
program define _eststo_store, eclass
local caller : di _caller()
capt _on_colon_parse `0'
if !_rc {
local command `"`s(after)'"'
local 0 `"`s(before)'"'
}
syntax [name] [, ///
Title(passthru) ///
Prefix(name) ///
Refresh Refresh2(numlist integer max=1 >0) ///
ADDscalars(string asis) ///
noEsample ///
noCopy ///
MISsing svy /// doesn't do anything
]
if `"`prefix'"'=="" local prefix "est"
// get previous eststo names and counter
local names $eststo
local counter $eststo_counter
if `"`counter'"'=="" local counter 0
// if name provided; set refresh on if name already in list
if "`namelist'"!="" {
if "`refresh2'"!="" {
di as error "refresh() not allowed"
exit 198
}
local name `namelist'
if `:list name in names' local refresh refresh
else {
if "`refresh'"!="" {
di as txt "(" as res "`name'" as txt " not found)"
}
local refresh
}
if "`refresh'"=="" local ++counter
}
// if no name provided
else {
if "`refresh2'"!="" local refresh refresh
if "`refresh'"!="" {
// refresh2 not provided => refresh last (if available)
if "`refresh2'"=="" {
if "`names'"=="" {
di as txt "(nothing to refresh)"
local refresh
}
else local name: word `:list sizeof names' of `names'
}
// refresh2 provided => check availability
else {
if `:list posof "`prefix'`refresh2'" in names' {
local name `prefix'`refresh2'
}
else {
di as txt "(" as res "`prefix'`refresh2'" as txt " not found)"
local refresh
}
}
}
if "`refresh'"=="" local ++counter
// set default name
if "`name'"=="" local name `prefix'`counter'
}
// run estimation command if provided
if `"`command'"'!="" {
version `caller': `command'
}
// add scalars to e()
if `"`addscalars'"'!="" {
capt ParseAddscalars `addscalars'
if _rc {
di as err `"addscalars() invalid"'
exit 198
}
if "`replace'"=="" {
local elist `: e(scalars)' `: e(macros)' `: e(matrices)' `: e(functions)'
}
local forbidden b V sample
while (1) {
gettoken lhs rest: rest
if `:list lhs in forbidden' {
di as err `"`lhs' not allowed in addscalars()"'
exit 198
}
if "`replace'"=="" {
if `:list lhs in elist' {
di as err `"e(`lhs') already defined"'
exit 110
}
}
gettoken rhs rest: rest, bind
capt eret scalar `lhs' = `rhs'
if _rc {
di as err `"addscalars() invalid"'
exit 198
}
capture local result = e(`lhs')
di as txt "(e(" as res `"`lhs'"' as txt ") = " ///
as res `result' as txt " added)"
if `"`rest'"'=="" continue, break
}
}
// add e(cmd) if missing
if `"`e(cmd)'"'=="" {
if `"`: e(scalars)'`: e(macros)'`: e(matrices)'`: e(functions)'"'!="" {
eret local cmd "."
}
}
// store estimates with e(sample)
estimates store `name' , `copy' `title'
// remove e(sample) if -noesample- specified
if "`esample'"!="" {
capt confirm new var _est_`name'
if _rc {
tempname hcurrent
_est hold `hcurrent', restore estsystem nullok
qui replace _est_`name' = . in 1
_est unhold `name'
capt confirm new var _est_`name'
if _rc qui drop _est_`name'
else {
di as error "somethings wrong; please contact author of -eststo- " ///
"(see e-mail in help {help eststo})"
exit 498
}
_est hold `name', estimates varname(_est_`name')
// varname() only needed so that _est hold does not return error
// if variable `name' exists
}
}
// report
if "`refresh'"=="" {
global eststo `names' `name'
global eststo_counter `counter'
if `"`namelist'"'=="" {
di as txt "(" as res "`name'" as txt " stored)"
}
}
else {
if `"`namelist'"'=="" {
di as txt "(" as res "`name'" as txt " refreshed)"
}
}
end
program ParseAddscalars
syntax anything [ , Replace ]
c_local rest `"`anything'"'
c_local replace `replace'
end