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.
438 lines
13 KiB
Plaintext
438 lines
13 KiB
Plaintext
8 months ago
|
*! version 1.1.1 PR 28nov2005
|
||
|
/*
|
||
|
History
|
||
|
|
||
|
1.1.1 28nov2005 eform and eform() option styles now allowed.
|
||
|
nowarning option to suppress warning message about supported regression cmds.
|
||
|
1.1.0 30sep2005 Generalization of supported commands (cmdchk.ado also modified).
|
||
|
Version <=7 no longer supported.
|
||
|
1.0.9 18apr2005 Default rowid variable becomes _i.
|
||
|
If not found, take from char _dta[MI_obsid] then char _dta[mi_id].
|
||
|
Default impid variable is _j. If not found, take from _dta[MI_impid].
|
||
|
These changes are for future compatibility with MItools.
|
||
|
1.0.8 04mar2005 Fixed problem with eform on redisplay
|
||
|
1.0.7 28jan2005 Fixed problem with null model estimation
|
||
|
Fixed bug with noconstant option
|
||
|
1.0.6 25jan2005 e(sample) now correct for all imputations, via ereturn post.
|
||
|
Add d.f. quantities from Barnard & Rubin (1999) Biometrika 86:948-955 eq (3)-(5).
|
||
|
Minor additions to ereturn quantities for compatibility with misw.
|
||
|
Allow null model and model only with constant for benefit of misw.
|
||
|
1.0.5 16nov2004 Update calculations of quantities stored for Li et al (1991) F test.
|
||
|
1.0.4 13oct2004 Change e(cmd) to `cmd', make e(cmd2)="micombine" (for use after mfx).
|
||
|
Implementation of mean log likelihood and chisquare statistic saved
|
||
|
(note undocumented -noclear- but v. useful option to ereturn post/estimates post).
|
||
|
*/
|
||
|
program define micombine, eclass
|
||
|
|
||
|
if _caller()<=7 {
|
||
|
di as error "version 7 and earlier not supported"
|
||
|
exit 9
|
||
|
}
|
||
|
|
||
|
if replay() {
|
||
|
if `"`e(cmd2)'"'!="micombine" {
|
||
|
error 301
|
||
|
}
|
||
|
syntax[, EForm EForm2(string)]
|
||
|
if "`eform2'"!="" {
|
||
|
if "`eform'"!="" di as err "[eform ignored]"
|
||
|
local eform eform(`eform2')
|
||
|
}
|
||
|
else if "`eform'"!="" local eform eform("exp(b)")
|
||
|
di as text _n "Multiple imputation parameter estimates (" as res e(m) as text " imputations)"
|
||
|
capture ereturn display, `eform'
|
||
|
local rc=_rc
|
||
|
if `rc'>0 {
|
||
|
* Null model, or model with cc() only
|
||
|
if `"`e(cmd)'"'!="stcox" {
|
||
|
`e(cmd)' `0'
|
||
|
}
|
||
|
else di as text "[Null model - no estimates]"
|
||
|
}
|
||
|
else ereturn display, `eform'
|
||
|
di as result e(N) as text " observations."
|
||
|
exit
|
||
|
}
|
||
|
|
||
|
gettoken cmd 0 : 0
|
||
|
if "`cmd'"=="stpm" {
|
||
|
local dist 7
|
||
|
local bad 0
|
||
|
}
|
||
|
else {
|
||
|
cmdchk `cmd'
|
||
|
local cmdnotknown `s(bad)'
|
||
|
/*
|
||
|
dist=0 (normal), 1 (binomial), 2 (poisson), 3 (cox), 4 (glm),
|
||
|
5 (xtgee), 6(ereg/weibull).
|
||
|
*/
|
||
|
local dist `s(dist)'
|
||
|
}
|
||
|
syntax [anything] [if] [in] [aw fw pw iw] , [ IMPid(string) BR CC(varlist) noCONStant ///
|
||
|
DEAD(varname) DETail EForm EForm2(string) GENxb(string) LRR noWARning OBSid(string) * ]
|
||
|
|
||
|
if `cmdnotknown' & "`warning'"!="nowarning" {
|
||
|
di as err _n "Warning: " as inp "`cmd'" as err " is not a certified regression command for micombine."
|
||
|
di as err "micombine will continue mechanically, but correct results are not guaranteed."
|
||
|
di as err "You must take responsibility that Rubin's rules are appropriate here." _n
|
||
|
}
|
||
|
|
||
|
if "`eform2'"!="" {
|
||
|
if "`eform'"!="" di as err "[eform ignored]"
|
||
|
local eform eform(`eform2')
|
||
|
}
|
||
|
else if "`eform'"!="" local eform eform("exp(b)")
|
||
|
|
||
|
* Check for possible impid characteristic. If it does not exist use default _j
|
||
|
if "`impid'"=="" {
|
||
|
local impid: char _dta[MI_impid]
|
||
|
if "`impid'"=="" local impid _j
|
||
|
}
|
||
|
cap confirm var `impid'
|
||
|
if _rc {
|
||
|
di as err "imputation identifier `impid' not found"
|
||
|
exit 601
|
||
|
}
|
||
|
|
||
|
* Check for possible obsid chars. If none exist use default _i
|
||
|
if "`obsid'"=="" {
|
||
|
local I: char _dta[MI_obsid]
|
||
|
if "`I'"=="" local I: char _dta[mi_id]
|
||
|
if "`I'"=="" local I _i
|
||
|
}
|
||
|
else local I `obsid'
|
||
|
cap confirm var `I'
|
||
|
if _rc {
|
||
|
di as err "observation identifier `I' not found"
|
||
|
exit 601
|
||
|
}
|
||
|
|
||
|
if "`detail'"!="" {
|
||
|
local detail noisily
|
||
|
}
|
||
|
else local detail
|
||
|
|
||
|
*Change here 11/15/05, commenting out the line below !! PR DELETED XIAO CHEN'S EDIT, NOV 05
|
||
|
frac_cox "`dead'" `dist'
|
||
|
|
||
|
if "`constant'"=="noconstant" {
|
||
|
if "`cmd'"=="fit" | "`cmd'"=="stcox" | "`cmd'"=="cox" {
|
||
|
di as error "noconstant invalid with `cmd'"
|
||
|
exit 198
|
||
|
}
|
||
|
}
|
||
|
|
||
|
*Change here 11/15/05, `dist' could be null.... !! PR DELETED XIAO CHEN'S EDIT, NOV 05
|
||
|
*if "`dist'" =="7" { /* stcox, streg, stpm */
|
||
|
if `dist'==7 {
|
||
|
local y
|
||
|
local yname _t
|
||
|
local xvars `anything'
|
||
|
}
|
||
|
else {
|
||
|
gettoken y xvars : anything
|
||
|
gettoken xvars left: xvars, parse("(")
|
||
|
local yname `y'
|
||
|
}
|
||
|
|
||
|
tempvar touse
|
||
|
quietly {
|
||
|
marksample touse
|
||
|
markout `touse' `varlist' `dead' `cc'
|
||
|
if "`dead'"!="" {
|
||
|
local dead "dead(`dead')"
|
||
|
}
|
||
|
|
||
|
* Deal with weights.
|
||
|
frac_wgt `"`exp'"' `touse' `"`weight'"'
|
||
|
local wgt `r(wgt)'
|
||
|
|
||
|
tempvar J
|
||
|
* Important (compatibility with mitools): ignore rows for which impid=0
|
||
|
egen int `J'=group(`impid') if `touse'==1 & `impid'>0 & !missing(`impid')
|
||
|
sum `J', meanonly
|
||
|
local m=r(max)
|
||
|
if `m'<2 {
|
||
|
di as error "there must be at least 2 imputations"
|
||
|
exit 198
|
||
|
}
|
||
|
|
||
|
local nxvar: word count `xvars'
|
||
|
/*
|
||
|
if `nxvar'<1 {
|
||
|
di as err "there must be at least one covariate"
|
||
|
exit 198
|
||
|
}
|
||
|
*/
|
||
|
local ncc: word count `cc' /* could legitimately be zero */
|
||
|
local nvar=`nxvar'+`ncc' /* number of covariates in model */
|
||
|
|
||
|
count if `touse'==1 & `J'==1
|
||
|
local nobs=r(N)
|
||
|
|
||
|
* Null Cox model (or model with only ccvars): fit on final imputation only, and quit
|
||
|
if "`xvars'"=="" & ("`cmd'"=="cox" | "`cmd'"=="stcox") {
|
||
|
if "`cmd'"=="stcox" & "`cc'"=="" {
|
||
|
local options `options' estimate
|
||
|
}
|
||
|
`detail' `cmd' `y' `cc' if `touse'==1 & `J'==`m' `wgt', `options' `dead' `constant'
|
||
|
noi `cmd'
|
||
|
di as result `nobs' as text " observations."
|
||
|
ereturn scalar m=`m'
|
||
|
ereturn local impid `impid'
|
||
|
ereturn local cmd `cmd'
|
||
|
ereturn local cmd2 micombine
|
||
|
exit
|
||
|
}
|
||
|
|
||
|
* Compute model over m imputations
|
||
|
tempname W Q B T QQ
|
||
|
if "`genxb'"!="" {
|
||
|
tempvar xb xbtmp
|
||
|
gen `xb'=.
|
||
|
}
|
||
|
* Estimate mean LR chisquare statistic (where possible)
|
||
|
tempname chi2 ell ell0 nucom
|
||
|
scalar `chi2'=0
|
||
|
scalar `ell'=0
|
||
|
scalar `ell0'=0
|
||
|
forvalues i=1/`m' {
|
||
|
tempname Q`i'
|
||
|
`detail' `cmd' `y' `xvars' `cc' `left' if `touse'==1 & `J'==`i' `wgt', ///
|
||
|
`options' `dead' `constant'
|
||
|
scalar `nucom'=e(df_r) // complete-data residual degrees of freedom
|
||
|
if `nucom'==. {
|
||
|
scalar `nucom'=100000
|
||
|
}
|
||
|
scalar `ell'=`ell'+e(ll)
|
||
|
scalar `ell0'=`ell0'+e(ll_0)
|
||
|
scalar `chi2'=`chi2'-2*(e(ll_0)-e(ll))
|
||
|
if "`genxb'"!="" {
|
||
|
predict `xbtmp' if `touse'==1 & `J'==`i', xb
|
||
|
replace `xb'=`xbtmp' if `touse'==1 & `J'==`i'
|
||
|
drop `xbtmp'
|
||
|
}
|
||
|
matrix `Q`i''=e(b)
|
||
|
if `i'==1 {
|
||
|
matrix `Q'=e(b)
|
||
|
matrix `W'=e(V)
|
||
|
}
|
||
|
else {
|
||
|
matrix `Q'=`Q'+e(b)
|
||
|
matrix `W'=`W'+e(V)
|
||
|
}
|
||
|
|
||
|
}
|
||
|
if "`genxb'"!="" {
|
||
|
sort `touse' `I' `J'
|
||
|
by `touse' `I': gen `genxb'=sum(`xb')/`m' if `touse'==1
|
||
|
by `touse' `I': replace `genxb'=`genxb'[_N] if _n<_N
|
||
|
lab var `genxb' "Mean Linear Predictor (`m' imputations)"
|
||
|
}
|
||
|
matrix `Q'=`Q'/`m' /* MI param estimates */
|
||
|
matrix `W'=`W'/`m'
|
||
|
scalar `chi2'=`chi2'/`m'
|
||
|
scalar `ell'=`ell'/`m'
|
||
|
scalar `ell0'=`ell0'/`m'
|
||
|
local k=colsof(`Q')
|
||
|
matrix `B'=J(`k',`k',0)
|
||
|
forvalues i=1/`m' {
|
||
|
matrix `QQ'=`Q`i''-`Q'
|
||
|
if `i'==1 {
|
||
|
matrix `B'=`QQ''*`QQ'
|
||
|
}
|
||
|
else matrix `B'=`B'+`QQ''*`QQ'
|
||
|
}
|
||
|
matrix `B'=`B'/(`m'-1)
|
||
|
matrix `T'=`W'+(1+1/`m')*`B' /* estimated VCE matrix */
|
||
|
/*
|
||
|
Relative increase in variance due to missing information (r) for
|
||
|
each variable, and df and lambda, the fraction of missing information.
|
||
|
All measures are unstable for low m. See Schafer (1997) p. 110.
|
||
|
|
||
|
Note that BIF = sqrt(T/W) = sqrt(1 + (B/W)*(1+1/m)) = sqrt(1+r)
|
||
|
is the between-imputation imprecision factor, i.e. the ratio
|
||
|
of the SE derived from T to the SE derived from W,
|
||
|
ignoring between-imputation variation in parameter estimates.
|
||
|
*/
|
||
|
tempname r t lambda nu BIF
|
||
|
matrix `r'=J(1,`k',0)
|
||
|
matrix `lambda'=J(1,`k',0)
|
||
|
matrix `nu'=J(1,`k',0)
|
||
|
matrix `BIF'=J(1,`k',0)
|
||
|
scalar `t'=`m'-1
|
||
|
* Next few lines assign quantities for tests of individual (1 df) components of Q (=beta)
|
||
|
forvalues j=1/`k' {
|
||
|
matrix `r'[1,`j']=(1+1/`m')*`B'[`j',`j']/`W'[`j',`j']
|
||
|
matrix `nu'[1,`j']=cond(`t'>4, 4+(`t'-4)*(1+(1-2/`t')/`r'[1,`j'])^2, `t'*(1+1/`r'[1,`j'])^2)
|
||
|
matrix `lambda'[1,`j']=(`r'[1,`j']+2/(`nu'[1,`j']+3))/(`r'[1,`j']+1)
|
||
|
matrix `BIF'[1,`j']=sqrt(1+`r'[1,`j']) /* = sqrt(`T'[`j',`j']/`W'[`j',`j']) */
|
||
|
}
|
||
|
* Next few lines assign quantities for d.f. from Barnard & Rubin 1999 B'ka 86(4): 948-955.
|
||
|
tempname nutilde num nuobs gamma
|
||
|
matrix `nutilde'=J(1,`k',0)
|
||
|
matrix `num'=J(1,`k',0)
|
||
|
matrix `nuobs'=J(1,`k',0)
|
||
|
matrix `gamma'=J(1,`k',0)
|
||
|
forvalues j=1/`k' {
|
||
|
matrix `gamma'[1,`j']=(1+1/`m')*`B'[`j',`j']/`T'[`j',`j']
|
||
|
matrix `nuobs'[1,`j']=((`nucom'+1)/(`nucom'+3))*`nucom'*(1-`gamma'[1,`j'])
|
||
|
matrix `num'[1,`j']=(`m'-1)*`gamma'[1,`j']^-2
|
||
|
matrix `nutilde'[1,`j']=1/((1/`num'[1,`j']+1/`nuobs'[1,`j']))
|
||
|
}
|
||
|
* use all varnames
|
||
|
local names: colnames(`Q1')
|
||
|
matrix colnames `r'=`names'
|
||
|
matrix colnames `nu'=`names'
|
||
|
matrix colnames `lambda'=`names'
|
||
|
matrix colnames `BIF'=`names'
|
||
|
|
||
|
matrix colnames `gamma'=`names'
|
||
|
matrix colnames `nuobs'=`names'
|
||
|
matrix colnames `num'=`names'
|
||
|
matrix colnames `nutilde'=`names'
|
||
|
|
||
|
* Li, Raghunathan & Rubin (1991) estimates of T and nu1
|
||
|
* for F test of Q=0 on k,nu1 degrees of freedom
|
||
|
tempname r1 t1 BW TLRR
|
||
|
matrix `BW'=`B'*syminv(`W')
|
||
|
scalar `r1'=trace(`BW')*(1+1/`m')/`k'
|
||
|
matrix `TLRR'=`W'*(1+`r1')
|
||
|
scalar `t1'=`k'*(`m'-1)
|
||
|
matrix colnames `Q'=`names'
|
||
|
matrix rownames `T'=`names'
|
||
|
matrix colnames `T'=`names'
|
||
|
matrix rownames `B'=`names'
|
||
|
matrix colnames `B'=`names'
|
||
|
matrix rownames `TLRR'=`names'
|
||
|
matrix colnames `TLRR'=`names'
|
||
|
|
||
|
}
|
||
|
di as text _n "Multiple imputation parameter estimates (`m' imputations)"
|
||
|
if "`lrr'"!="" {
|
||
|
di as text "[Using Li-Raghunathan-Rubin (LRR) estimate of VCE matrix]"
|
||
|
ereturn post `Q' `TLRR', depname(`yname') obs(`nobs') esample(`touse') noclear
|
||
|
ereturn matrix T `T'
|
||
|
}
|
||
|
else {
|
||
|
ereturn post `Q' `T', depname(`yname') obs(`nobs') esample(`touse') noclear
|
||
|
ereturn matrix TLRR `TLRR'
|
||
|
}
|
||
|
if "`br'"=="" {
|
||
|
ereturn display, `eform'
|
||
|
di as result `nobs' as text " observations."
|
||
|
}
|
||
|
ereturn matrix B `B'
|
||
|
ereturn matrix W `W'
|
||
|
ereturn matrix r `r'
|
||
|
ereturn matrix nu `nu'
|
||
|
ereturn matrix lambda `lambda'
|
||
|
ereturn matrix BIF `BIF'
|
||
|
|
||
|
* Quantities for calculating df `nutilde' according to Barnard & Rubin (1999)
|
||
|
ereturn matrix gamma `gamma'
|
||
|
ereturn matrix nuobs `nuobs'
|
||
|
ereturn matrix num `num'
|
||
|
ereturn matrix nutilde `nutilde'
|
||
|
|
||
|
ereturn scalar r1=`r1'
|
||
|
ereturn scalar nu1=cond(`t1'>4, 4+(`t1'-4)*(1+(1-2/`t1')/`r1')^2, 0.5*`t1'*(1+1/`k')*(1+1/`r1')^2)
|
||
|
ereturn scalar m=`m'
|
||
|
ereturn scalar chi2=`chi2'
|
||
|
ereturn scalar ll=`ell'
|
||
|
ereturn scalar ll_0=`ell0'
|
||
|
ereturn local eform `eform'
|
||
|
ereturn local impid `impid'
|
||
|
ereturn local cmd `cmd'
|
||
|
ereturn local cmd2 micombine
|
||
|
if "`br'"!="" {
|
||
|
display_t
|
||
|
di as result `nobs' as text " observations."
|
||
|
}
|
||
|
end
|
||
|
|
||
|
program define display_t
|
||
|
* Display results with t-statistics estimated according to Barnard & Rubin (1999)
|
||
|
tempname V Q nu
|
||
|
matrix `V'=e(V)
|
||
|
matrix `Q'=e(b)
|
||
|
matrix `nu'=e(nutilde)
|
||
|
local yname `e(depvar)'
|
||
|
local xs: colnames `Q'
|
||
|
local k=colsof(`Q')
|
||
|
di as text _n "Intervals and inference based on d.f. from Barnard & Rubin (1999)"
|
||
|
di as txt "{hline 13}{c TT}{hline 64}"
|
||
|
local t0 = abbrev("`yname'",12)
|
||
|
if `"`e(eform)'"'!="" {
|
||
|
local tt "Odds Ratio"
|
||
|
}
|
||
|
else {
|
||
|
local tt " Coef."
|
||
|
}
|
||
|
|
||
|
#delimit ;
|
||
|
di as text
|
||
|
%12s "`t0'" _col(14)"{c |}`tt' Std. Err. t P>|t| [$S_level% Conf. Intvl] MI.df"
|
||
|
_n "{hline 13}{c +}{hline 64}" ;
|
||
|
#delimit cr
|
||
|
tempname df mn se t p invt l u
|
||
|
forvalues i=1/`k' {
|
||
|
local x: word `i' of `xs'
|
||
|
if "`x'"!="_cons" {
|
||
|
local fmt : format `x'
|
||
|
if substr("`fmt'",-1,1)=="f" {
|
||
|
local fmt="%8."+substr("`fmt'",-2,2)
|
||
|
}
|
||
|
else if substr("`fmt'",-2,2)=="fc" {
|
||
|
local fmt="%8."+substr("`fmt'",-3,3)
|
||
|
}
|
||
|
else local fmt "%8.0g"
|
||
|
local fmt`i' `fmt'
|
||
|
}
|
||
|
else local fmt "%8.0g"
|
||
|
scalar `df' =`nu'[1,`i']
|
||
|
scalar `mn' = `Q'[1,`i']
|
||
|
scalar `se' = sqrt(`V'[`i',`i'])
|
||
|
scalar `t' = `mn'/`se'
|
||
|
scalar `p' = 2* ttail(`df', abs(`t'))
|
||
|
scalar `invt' = invttail(`df', (1-$S_level/100)/2)
|
||
|
scalar `l' = `mn' - `invt'*`se'
|
||
|
scalar `u' = `mn' + `invt'*`se'
|
||
|
if `"`e(eform)'"'!="" {
|
||
|
scalar `mn' = exp(`mn')
|
||
|
scalar `se' = `mn'*`se'
|
||
|
scalar `l' = exp(`l')
|
||
|
scalar `u' = exp(`u')
|
||
|
}
|
||
|
if `df'>99999 {
|
||
|
local fmtdf %9.2e
|
||
|
}
|
||
|
else local fmtdf %9.2f
|
||
|
di as text /*
|
||
|
*/ %12s abbrev("`x'",12) _col(14) "{c |}" /*
|
||
|
*/ _col(17) as res `fmt' `mn' /*
|
||
|
*/ _col(27) `fmt' `se' /*
|
||
|
*/ _col(36) %7.2f `t' /*
|
||
|
*/ _col(42) %7.3f `p' /*
|
||
|
*/ _col(52) `fmt' `l' /*
|
||
|
*/ _col(61) `fmt' `u' /*
|
||
|
*/ _col(70) `fmtdf' `df'
|
||
|
}
|
||
|
di as text "{hline 13}{c BT}{hline 64}"
|
||
|
end
|
||
|
|
||
|
program define chkrowid, sclass
|
||
|
local I: char _dta[mi_id]
|
||
|
if "`I'"=="" {
|
||
|
di as error "no row-identifier variable found - data may have incorrect format"
|
||
|
exit 198
|
||
|
}
|
||
|
cap confirm var `I'
|
||
|
local rc=_rc
|
||
|
if `rc' {
|
||
|
di as error "row-identifier variable `I' not found"
|
||
|
exit `rc'
|
||
|
}
|
||
|
sret local I `I'
|
||
|
end
|