📄 hausman.ado
字号:
/* equation rename */
if "`neweq'" == "" {
local enames : coleq `b'
}
else {
local enames "`neweq'"
}
local cnames : colnames `b'
tokenize "`enames'"
local i 1
local j 0
while `i' <= colsof(`b') {
local col : word `i' of `cnames'
if "``i''" != "`old'" {
local ++j
local old "``i''"
}
local newname "`newname' comp`j':`col'"
local ++i
}
mat colnames `b' = `newname'
mat colnames `V' = `newname'
mat rownames `V' = `newname'
end
program define Rmcons /* matname */
args m
local names : colnames `m'
local ct : word count `names'
tokenize `names'
local i 1
local strkcol 1
while "``i''" != "" {
if "``i''" == "_cons" {
if `i' == `ct' & `strkcol' == 1 {
di as err "no common coefficients names (eq:coef)," /*
*/ " nothing to test"
exit 498
}
else {
matstrik `m' `strkcol'
local --strkcol
}
}
local ++i
local ++strkcol
}
end
/*! version 1.0.0 23 May 1998 */
program define MatConf /* b1 V1 b2 V2 */
version 6
args b1 V1 b2 V2
tempname e wrk map
local nam1 : colfullnames `b1'
local nam2 : colfullnames `b2'
/* make `e' = (1, 2, 3, ...) */
local n2 = colsof(`b2')
mat `e' = `b2'
forvalues i = 1/`n2' {
mat `e'[1,`i'] = `i'
}
local n1 = colsof(`b1')
local i 1
while `i' <= `n1' {
local name : word `i' of `nam1'
capture mat `wrk' = `e'[1,`"`name'"']
if _rc {
if _rc != 111 {
error _rc
}
if `n1'==1 {
mat drop `b1' `V1' `b2' `V2'
exit 111
}
* drop row/column i
matstrik `b1' `i'
matstrik `V1' `i'
local nam1 : colfullnames `b1'
local --n1
}
else {
mat `map' = nullmat(`map'), `wrk'
local ++i
}
}
/* we know `n1' >= 1 */
tempname newb2 newV2
mat `newb2' = `b1' /* just to dcl and obtain names */
mat `newV2' = `V1'
forvalues i = 1/`n1' {
local ip = `map'[1,`i']
mat `newb2'[1,`i'] = `b2'[1,`ip']
forvalues j = 1/`n1' {
mat `newV2'[`i',`j'] = `V2'[`ip',`map'[1,`j']]
mat `newV2'[`j',`i'] = `newV2'[`i',`j']
}
}
mat `b2' = `newb2'
mat `V2' = `newV2'
end
/*
MatGinv A
computes the Moore-Penrose inverse Ai of A, i.e., the unqiue
matrix that satisfies the 4 conditions
(1) Ai*A*Ai = Ai
(2) A*Ai*A = A
(3) Ai*Ai' is a projection on the null space of A
(4) Ai'*Ai is a projection on the image of A
if A is invertible, Ai = inverse(A)
if A is n by m, Ai = m by n
If A is a matrix of zeros, the MP-inverse is all-zeroes also.
The first two requirements, (1) and (2) above, have been checked
using tough matrices from ./sim/sim_mcfad7 and the requirements
are met to reasonable accuracy.
adapted from Jeroen Weesie/ICS STB-39 dm49
*/
program define MatGinv
args invmat /// matrix name to hold inverted matrix
rank /// scalar name to hold rank of matrix
colon /// ":"
A /// name of matrix to be inverted (mat be invmat)
syminv /// "" or "syminv" for use syminv
tol // tolerence or ""
tempname At U W V Wmax
if "`syminv'" != "" { // Just a syminv requested
matrix `invmat' = syminv(`A')
scalar `rank' = colsof(`A') - diag0cnt(`invmat')
if diag0cnt(`invmat') > 0 {
RankMsg `=`rank'' `=colsof(`A')'
}
exit
}
local nrA = rowsof(`A')
local ncA = colsof(`A')
// singular value decomposition
if `nrA' < `ncA' {
matrix `At' = `A''
matrix svd `V' `W' `U' = `At''
}
else {
matrix svd `U' `W' `V' = `A'
}
// tolerance for inverting the diagonal elements of W
local nc = colsof(`W')
if "`tol'" == "" {
// max of singular values
scalar `Wmax' = 0
forvalues i = 1/`nc' {
scalar `Wmax' = max(`Wmax', `W'[1,`i'])
}
tempname tol
scalar `tol' = `Wmax' * `nc' * 1.0e-9
}
// invert the elements of W
local rnk 0
forvalues i = 1/`nc' {
if `W'[1,`i'] > `tol' {
matrix `W'[1,`i'] = 1/(`W'[1,`i'])
local rnk = `rnk' + 1
}
else {
matrix `W'[1,`i'] = 0
}
}
// produce InvA
if `rnk' == 0 {
matrix `invmat' = J(`ncA',`nrA',0)
}
else {
matrix `invmat' = `V' * diag(`W') * `U''
}
if `rnk' != colsof(`A') {
RankMsg `rnk' `=colsof(`A')'
}
if "`rank'" != "" {
scalar `rank' = `rnk'
}
end
program RankMsg
args rank coefs
di ""
di as text in smcl "{p 0 8}Note: the rank of the differenced variance matrix ({result:`rank'}) does not equal the number of coefficients being tested ({result:`coefs'}); be sure this is what you expect, or there may be problems computing the test. Examine the output of your estimators for anything unexpected and possibly consider scaling your variables so that the coefficients are on a similar scale."
end
program SymPosDef, rclass
args W
tempname X V
capture matrix symeigen `X' `V' = `W'
if _rc == 505 {
// `W' (the diff between 2 cov. matrices wasn't symmetric,
// we force it to be symmetric
mat `W' = (`W' + `W'')*.5
matrix symeigen `X' `V' = `W'
}
return local posdef = `V'[1,colsof(`V')] > 0
end
/* Remove all coefficients with Var==0 */
program define Strik0
args b V
while diag0cnt(`V') {
if colsof(`V')==1 {
di as err "nothing to test"
exit 498
}
Find0 `V'
local i `r(i)'
* drop row/column i
matstrik `b' `i'
matstrik `V' `i'
}
end
/* Find0 V
returns in r(i) the first index for which V[i,i]=0
*/
program define Find0, rclass
args V
local i 1
while `V'[`i',`i'] != 0 {
local ++i
}
ret local i `i'
end
/* Abbrev abname : name
returns in abname the 12char abbreviation of name,
or . if this abbrevation is empty
*/
program define Abbrev
args abname colon name
local abn = abbrev("`name'",12)
if "`abn'" == "" {
local abn .
}
c_local `abname' `abn'
end
/* GetbV name b V
returns e(b) and e(V) with error messages if not found
*/
program define GetbV
args name b V
foreach n in b V {
capt confirm matrix e(`n')
if _rc {
di as err "e(`n') not found in `name'"
exit 198
}
matrix ``n'' = e(`n')
}
end
/* OldSyntax
Processes subcommands -save- and -clear- not dealt with by the
new syntax/command due to -estimates-.
return in r(newsyntax) the translation of version 7 syntax
into version 8 syntax.
*/
program define OldSyntax, rclass
syntax [, Alleqs CLEAR Constant CURrent(string) Less More ///
Prior(string) Save SIGMAMore SIGMALess SKipeqs(passthru) ///
SYMINV EQuations(passthru) ]
NewSyntaxMsg
if "`save'" != "" {
syntax, save
di as txt "(storing estimation results as _HAUSMAN)"
est store _HAUSMAN, title("estimation results saved by hausman")
exit 0
}
if "`clear'" != "" {
syntax, clear
capt est drop _HAUSMAN
exit 0
}
// get information about models to be compared: _HAUSMAN and . (last)
capt est_cfexist _HAUSMAN
if _rc {
di as err "no estimation results were previously stored by hausman"
exit 198
}
if "`e(cmd)'" == "" {
error 301
}
if "`e(_estimates_name)'" == "_HAUSMAN" {
di as err "the last estimation results were already " /*
*/ "saved by hausman"
di as err "thus, no test can be performed"
exit 301
}
if "`more'" != "" & "`less'" != "" {
di as err "more and less cannot be combined"
exit 198
}
if "`less'" != "" {
// . is the "less efficient" estimator
local spec1 .
local spec2 _HAUSMAN
local teff `"`current'"'
local tcon `"`prior'"'
local reveq reveq
}
else {
// . is the "more efficient" estimator
local spec1 _HAUSMAN
local spec2 .
local teff `"`prior'"'
local tcon `"`current'"'
}
if "`teff'" == "" {
local teff Efficient
}
if "`tcon'" == "" {
local tcon Consistent
}
// assemble new syntax line
return local newsyntax `spec1' `spec2' , `constant' `alleqs' /*
*/ `equations' `reveq' `skipeqs' `sigmamore' `sigmaless' /*
*/ teff(`teff') tcon(`tcon') `syminv'
end
program define NewSyntaxMsg
di as txt "{p}You used the old syntax of {cmd:hausman}. Click " ///
"{help hausman##|_new:here} to learn about the new syntax.{p_end}" _n
end
exit
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -