*! version 2.2.0 07may2003 (SJ3-4: st0049, st0050, st0051) program define simex, eclass byable(onecall) version 8.0 if replay() { if _by() { error 190 } if "`e(cmd)'" != "simex" { error 301 } DispEst `"`0'"' exit } if _by() { local by "by `_byvars'`_byrc0':" } eret clear capture noisily `by' Estimate `0' exit _rc end program define Estimate, eclass byable(recall) sort _crcdeq `"`0'"' , weight(fweight iweight pweight) local 0 ",`opts'" #delimit ; syntax [, SCALE(string) MESSage(int 2) Family(string) Link(string) LTOLerance(real 1e-6) ITERate(int 100) SEED(int 0) BSTRAP BOOT BREP(int -1) LINear RATional MEDian THEta(string) SUUINIT(string) BTRIM(real .02) SAVing(str) REPLACE SREP(int 50) NLEPS(real 1) NLREP(int 100) noSCALEX ] ; #delimit cr if `"`saving'"'=="" { local filetmp "yes" if "`replace'"!="" { di in red "replace can only be specified when " /* */ "using saving() option" exit 198 } } else { capture qui describe using `saving' if _rc == 0 & "`replace'" == "" { error 602 } } if `neq' == 1 { di in red "no measurement error data" exit 198 } if "`boot'`bstrap'"!="" & `brep' < 0 { local brep 199 } if `brep' > 0 { local boot "boot" } MapFL "`family'" "`link'" local fam `"`r(fam)'"' local famarg `"`r(famarg)'"' local fcode `"`r(famcode)'"' local fstr `"`r(fstr)'"' local lnk `"`r(lnk)'"' local lnkarg `"`r(lnkarg)'"' local lcode `"`r(lnkcode)'"' local lstr `"`r(lstr)'"' local scale1 `"`r(scale1)'"' local method 0 if "`rational'" != "" { local method 1 } else if "`linear'" != "" { { local method 2 } if "`median'" == "" { local mean 0 } else { local mean 1 } local uutype 1 if "`suu'" == "" { tempname sumat local suu "`sumat'" } else { local suusave "yes" } if "`suuinit'" != "" { tempname bb confirm matrix `suuinit' capture mat `bb' = syminv(`suuinit') if _rc { di in red "suu() must name a symmetric matrix" exit 198 } tempname newname mat `newname' = `suuinit' local suu "`newname'" local uutype 0 } if "`theta'" == "" { tempname lamm lamm0 mat `lamm' = (0,.5,1,1.5,2) mat `lamm0' = `lamm' local theta "`lamm'" } else { tempname lamm lamm0 confirm matrix `theta' local nr = rowsof(`theta') local nc = colsof(`theta') if `nr' != 1 { di as err "Must supply a row vector in theta() option" exit 198 } mat `lamm' = `theta' local flag 0 local badv 0 tempname ss local i 1 while `i' <= `nc' { scalar `ss' = `lamm'[1,`i'] if `ss' == 0 { local flag = 1 } if `ss' < 0 { local badv = 1 } local i = `i'+1 } if `flag' == 0 { di as err "theta() vector must contain zero" exit 198 } if `badv' == 1 { di as err "theta() vector must be nonnegative" exit 198 } mat `lamm0' = `lamm' local theta "`lamm'" } qui { if "`scalex'" == "" { local scalex 0 } else { local scalex 1 } tempvar touse mark `touse' `ifx' `inx' `wgt' local totlst "`ind1'" local i 2 while `i' <= `neq' { global S_WL`i' "`ind`i''" local totlst "`totlst' `ind`i''" local i = `i'+1 } local ntot : word count `totlst' qui _rmcoll `totlst' local ctot : word count `r(varlist)' if `ntot' != `ctot' { di as err "varlists must contain unique variables" exit 198 } global S_WL1 = `neq'-1 noi ChkReps `touse' local i 2 while `i' <= `neq' { local ind`i' "${S_WL`i'}" local i = `i'+1 } local i 1 while `i' <= `neq' { SetSamp `touse' "`dep`i''" "`ind`i''" "`i'" "regeq" local i = `i' + 1 } local i 1 while `i' <= `neq' { RmColl `touse' "`dep`i''" "`ind`i''" "`nc`i''" "ind`i'" local i = `i'+1 } local cc 0 if "`constan'" == "" { local cc 1 } preserve keep if `touse' local lst "`dep`regeq'' `ind`regeq''" local nms "`ind`regeq''" local i 1 local nwreal = 0 while `i' <= `neq' { if `i' != `regeq' { local lst "`lst' `ind`i''" local nms "`nms' `eq`i''" capture confirm var `eq`i'' if _rc == 0 { di in red "illegal equation name. " _c di in red "`eq`i'' exists as a variable." exit 198 } local nind : word count `ind`i'' local k 1 while `k' <= `nind' { local w : word `k' of `ind`i'' count if `w'!=. local nwreal = `nwreal'+r(N) local k = `k'+1 } } local i = `i'+1 } order `lst' local tlist "`nms'" local p : word count `ind`regeq'' if "`nc`regeq''" == "" { local nms "`nms' _cons" local p = `p'+1 } local nw = `neq' local nw1 = `nw'-1 tempname wmat matrix `wmat' = J(1,`nw',0) matrix `wmat'[1,1] = `nw1' local i 1 local k 2 while `i' <= `neq' { if `i' ~= `regeq' { local numw : word count `ind`i'' matrix `wmat'[1,`k'] = `numw' local k = `k'+1 } local i = `i'+1 } local px = `neq'-1 local nvars = `p'+`px' local hassv 0 if "`from'" != "" { ChkB0 `from' `tlist' local hassv `r(flag)' } tempname beta if `hassv' == 0 { summ `dep' local mm = r(mean) mat `beta' = J(1,`nvars',0) mat `beta'[1,`nvars'] = `mm' } else mat `beta' = `from' FixBeta `beta' tempname cv var describe local nobs = r(N) if "`boot'" == "" { local calccv 0 local boot 0 } else { local boot 1 local calccv 1 /* Later change to 1 !! */ } if `message' > 0 { local jj "noi" } #delimit ; noi qvfmex 2 `message' `fcode' `famarg' `lcode' `lnkarg' `ltolerance' `iterate' `scalex' `calccv' `brep' `btrim' `seed' `nvars' `nobs' `beta' `cv' "`saving'" `cc' `suu' `uutype' `mean' `method' `srep' `theta' `nleps' `nlrep' `px' `nwreal' `wmat' ; #delimit cr if `status' { _qvferr `status' `message' exit `status' } qui FixName `beta' `cv' `theta' `lamm0' "`nms'" /* If we did not bootstrap, then the returning variance matrix is simply the last qvf iteration's vce which is not valid, so we zero it out */ mat `cv' = `boot'*`cv' /* ****************************** (*) check status for error if no error (*) `beta' has the coefficient vector (*) `cv' has the variance matrix (*) `var' has the dispersion ****************************** */ local obs = _N local dof = `obs'-`p'-(`neq'-1) tempvar mui eret post `beta' `cv' , depname(`dep`regeq'') /* */ obs(`obs') dof(`dof') if `mean' == 0 { eret local type "Mean" } else { eret local type "Median" } if `method' == 0 { eret local method "Quadratic" eret local calc "Linear regression" } else if `method' == 1 { eret local method "Rational" eret local calc "Nonlinear least squares" } else { eret local method "Linear" eret local calc "Linear regression" } test `tlist', min capture eret matrix suu = `suu' eret scalar F = r(F) eret scalar df_m = r(df_r) eret scalar df_p = r(df) eret local family "`fam'" eret local link "`lnk'" eret local depvar "`dep'" eret local vart "`fam'" eret local lnkt "`lnk'" eret local varf "`fstr'" eret local lnkf "`lstr'" local df = `dof' /* eret scalar pdis = `disp' eret scalar pdev = `disp'*`df' eret scalar dis = `dev'/`df' eret scalar dev = `dev' */ eret scalar N_sim = `srep' if `boot' { eret local vcetype "Bootstrap" eret scalar N_boot = `brep' } if "`disp'" != "" { eret scalar dispers = `disp' } eret matrix theta = `lamm' eret scalar N = `obs' eret local cmd "simex" } DispEst ", `opt'" end program define DispEst local options "Level(integer $S_level)" parse "`*'" #delimit ; noi di as txt _n "Simulation extrapolation" /* as txt "Family = " as res "`e(family)'" */ _col(49) as txt "No. of obs" _col(68) "=" _col(70) as res %9.0g e(N) ; #delimit cr if e(N_boot) != . { #delimit ; di /* as txt "Link = " as res "`e(link)'" */ as txt _col(49) "Bootstraps reps " _col(68) "=" _col(70) as res %9.0g e(N_boot) ; #delimit cr } /* else { di in gr "Link = " as res "`e(link)'" } */ #delimit ; di as txt _n "Residual df = " as res %9.0g e(df_m) as txt _col(49) "Wald F(" in ye e(df_p) as txt "," as res e(df_m) in gr ")" _col(68) "=" as res _col(70) %9.2f e(F) ; di as txt _col(49) "Prob > F" _col(68) "=" as res _col(70) %9.4f fprob(e(df_p),e(df_m),e(F)) ; #delimit cr /* di as txt "Deviance" _col(18) "=" as res _col(20) %12.0g e(dev) /* */ as txt _col(52) "(1/df) Deviance" /* */ _col(68) "=" as res _col(70) %9.0g e(dis) di as txt "Pearson" _col(18) "=" as res _col(20) %12.0g e(pdev) /* */ as txt _col(52) "(1/df) Pearson" /* */ _col(68) "=" as res _col(70) %9.0g e(pdis) */ di di as txt "Variance Function: " as res "V(u) = " /* */ as res _col(27) "`e(varf)'" /* */ _col(52) as txt "[" as res "`e(vart)'" as txt "]" di as txt "Link Function : " as res "g(u) = " /* */ as res _col(27) "`e(lnkf)'" /* */ _col(52) as txt "[" as res "`e(lnkt)'" as txt "]" di mat mlout, level(`level') end program define ChkB0, rclass local mat "`1'" mac shift local vlist "`*'" local p : word count `vlist' local p = `p'+1 local nc = colsof(`mat') if `nc' != `p' { mat `mat' = J(1,`p',0) ret scalar flag 0 } matrix colnames `mat' = `vlist' _cons ret scalar flag = 1 end program define FixName local b "`1'" local v "`2'" local m "`3'" local m0 "`4'" local names "`5'" tempname b1 b2 b3 b4 vu vd local n = colsof(`b') mat `b1' = `b'[1,1] mat `b2' = `b'[1,2..`n'] mat `b' = `b2',`b1' mat `vu' = (-1) mat `vd' = `m0'' mat `b3' = `m'[1...,1] mat `b4' = `m'[1...,2...] mat `m' = `vu',`b' mat `b3' = `vd',`b4',`b3' mat `m' = `m' \ `b3' mat colnames `m' = theta `names' capture mat `b1' = `v'[1,1] if _rc { mat colnames `b' = `names' local nc = colsof(`b') mat `v' = J(`nc',`nc',0) mat colnames `b' = `names' mat colnames `v' = `names' mat rownames `v' = `names' exit } mat `b2' = `v'[1,2..`n'] mat `b3' = `v'[2..`n',1] mat `b4' = `v'[2..`n',2..`n'] mat `vu' = `b4',`b3' mat `vd' = `b2',`b1' mat `v' = `vu'\ `vd' mat colnames `b' = `names' mat colnames `v' = `names' mat rownames `v' = `names' end program define SetSamp args touse y x i regeq if "`x'" == "" & `i' != 1 { noi di in red "equation `i' has no measurement error covariates" exit 198 } if "`y'" != "" { c_local `regeq' `i' markout `touse' `y' `x' exit } tempvar mm egen `mm' = rmiss(`x') local nx : word count `x' replace `touse' = 0 if `mm'==`nx' end program define RmColl args touse y x nc ind if "`y'" == "" { exit } _rmcoll `x' if `touse' , `nc' c_local `ind' "`r(varlist)'" end program define CkFamLk local nf : word count `1' local nl : word count `2' if `nf' > 2 { noi di in red "illegal family option" exit 198 } if `nl' > 2 { noi di in red "illegal link option" exit 198 } local fam : word 1 of `1' local famarg : word 2 of `1' local lnk : word 1 of `2' local lnkarg : word 2 of `2' local fam = lower(trim("`fam'")) local lnk = lower(trim("`lnk'")) local fl = length("`fam'") local ll = length("`lnk'") if "`fam'" == substr("poisson",1,max(3,`fl')) { local family 1 local famstr "poisson" } else if "`fam'" == substr("gamma",1,max(3,`fl')) { local family 2 local famstr "gamma" } else if "`fam'" == substr("power",1,max(3,`fl')) { local family 3 local famstr "power" } else if "`fam'" == substr("binomial",1,max(3,`fl')) { local family -1 if "`famarg'" == "" { local famarg 1 } local famstr "binomial" } else if "`fam'" == substr("normal",1,max(3,`fl')) | /* */ "`fam'" == substr("gaussian",1,max(3,`fl')) | "`fam'" == "" { local family 0 local famstr "normal" } else if "`fam'" == substr("power",1,max(3,`fl')) { local family 4 local famstr "power" } else if "`fam'" == substr("igaussian",1,max(3,`fl')) { local family 5 local famstr "igaussian" } else if "`fam'" == substr("nbinomial",1,max(3,`fl')) { local family 6 local famstr "nbinomial" } else { noi di in red "unknown family function -- `fam'" exit 198 } if "`lnk'" == substr("identity",1,max(3,`ll')) { local link 0 } else if "`lnk'" == substr("log",1,max(3,`ll')) { local link 1 } else if "`lnk'" == substr("reciprocal",1,max(3,`ll')) { local link 2 } else if "`lnk'" == substr("logit",1,max(3,`ll')) { local link 3 } else if "`lnk'" == substr("power",1,max(3,`ll')) { local link 4 } else if "`lnk'" == substr("opower",1,max(3,`ll')) { local link 5 } else if "`lnk'" == substr("cloglog",1,max(3,`ll')) { local link 6 } else if "`lnk'" == substr("probit",1,max(3,`ll')) { local link 7 } else if "`lnk'" == substr("nbinomial",1,max(3,`ll')) { local link 8 } else if "`lnk'" == "" { if `family' == 0 { local link 0 } else if `family' == 1 { local link 1 } else if `family' == 2 { local link 2 } else if `family' == 3 { local link 0 } else if `family' == 4 { local link 3 } else if `family' == 5 { local lnkarg -2 local link 4 } else if `family' == 6 { local link 1 } else if `family' ==-1 { local link 3 } } else { noi di in red "unknown link function -- `lnk'" exit 198 } if `link' == 0 { local lnkstr "identity" } else if `link' == 1 { local lnkstr "log" } else if `link' == 2 { local lnkstr "reciprocal" } else if `link' == 3 { local lnkstr "logit" } else if `link' == 4 { local lnkstr "power" } else if `link' == 5 { local lnkstr "opower" } else if `link' == 6 { local lnkstr "cloglog" } else if `link' == 7 { local lnkstr "probit" } else if `link' == 8 { local lnkstr "nbinomial" } /* Check combination */ if `family' != -1 & (`link'==3 | `link'==6 | /* */ `link'== 7 | `link'==5) { noi di in red "illegal family link combination" exit 198 } if `family' != 6 & `link' == 8 { noi di in red "illegal family link combination" exit 198 } if "`lnkarg'" == "" { local lnkarg 0 } if "`lnkarg'" != "" { confirm number `lnkarg' } if "`famarg'" == "" { local famarg 0 } if "`famarg'" != "" { confirm number `famarg' } c_local family "`family'" c_local famarg "`famarg'" c_local link "`link'" c_local lnkarg "`lnkarg'" c_local famstr "`famstr'" c_local lnkstr "`lnkstr'" end program define MapFL, rclass args fam lnk MapF `fam' ret local fam `"`r(fam)'"' ret local famarg `"`r(farg)'"' ret local famcode `"`r(fcode)'"' ret local fstr `"`r(fstr)'"' ret local scale1 `"`r(scale1)'"' MapL "`r(fcode)'" "`r(farg)'" `lnk' ret local lnk `"`r(lnk)'"' ret local lnkarg `"`r(larg)'"' ret local lnkcode `"`r(lcode)'"' ret local lstr `"`r(lstr)'"' end program define MapL, rclass args fc farg lnk larg if `fc' != 2 { local farg = 1 } local lcode = -1 local l = lower(trim(`"`lnk'"')) local n = length(`"`l'"') if `"`l'"' == "" { if `fc' == 0 { local lcode = 0 } else if `fc' == 1 { local lcode = 1 } else if `fc' == 2 { local lcode = 1 } else if `fc' == 3 { local lcode = 2 } else if `fc' == 4 { local lcode = 9 } else if `fc' == 5 { local lcode = 9 } else if `fc' == 6 { local lcode = 2 } else { noi di in red "power family needs link specified" exit 198 } } else if `"`l'"'==substr("identity",1,`n') { local lcode = 0 } else if `"`l'"'==substr("logit",1,max(4,`n')) { local lcode = 1 } else if `"`l'"'==substr("log",1,max(3,`n')) { local lcode = 2 } else if `"`l'"'==substr("nbinomial",1,max(3,`n')) { local lcode = 3 } else if `"`l'"'==substr("logc",1,max(4,`n')) { local lcode = 4 } else if `"`l'"'==substr("loglog",1,max(2,`n')) { local lcode = 5 } else if `"`l'"'==substr("cloglog",1,max(2,`n')) { local lcode = 6 } else if `"`l'"'==substr("probit",1,max(2,`n')) { local lcode = 7 } else if `"`l'"'==substr("reciprocal",1,max(2,`n')) { local lcode = 9 } else if `"`l'"'==substr("power",1,max(2,`n')) { local lcode = 9 } else if `"`l'"'==substr("opower",1,max(2,`n')) { local lcode = 10 } if "`larg'" == "" { local larg "1" } if `lcode' == 0 | (`lcode' == 9 & `larg' == 1) { local lnk "Identity" if "`farg'" == "1" { local lst "u" } else local lst "u/`farg'" } else if `lcode' == 1 | (`lcode' == 10 & `larg' == 0) { local lnk "Logit" if "`farg'" == "1" { local lst "log(u/(1-u))" } else local lst "log(u/(`farg'-u))" } else if `lcode' == 2 | (`lcode' == 9 & `larg' == 0) { local lnk "Log" if "`farg'" == "1" { local lst "ln(u)" } else local lst "ln(u/`farg')" } else if `lcode' == 3 { local lnk "Neg. Binomial" local lst "ln(u/(u+1/`larg')" } else if `lcode' == 4 { local lnk "Log complement" if "`farg'" == "1" { local lst "ln(1-u)" } else local lst "ln(1-u/`farg')" } else if `lcode' == 5 { local lnk "Log-log" if "`farg'" == "1" { local lst "-ln(-ln(u))" } else local lst "-ln(-ln(u/`farg'))" } else if `lcode' == 6 { local lnk "Complementary log-log" if "`farg'" == "1" { local lst "ln(-ln(1-u))" } else local lst "ln(-ln(1-u/`farg'))" } else if `lcode' == 7 { local lnk "Probit" if "`farg'" == "1" { local lst "invnorm(u)" } else local lst "invnorm(u/`farg')" } else if `lcode' == 8 | (`lcode' == 9 & `larg' == -1) { local lnk "Reciprocal" if "`farg'" == "1" { local lst "1/u" } else local lst "`farg'/u" local lcode = 9 local larg = -1 } else if `lcode' == 9 { local lnk "Power" if "`farg'" == "1" { local lst "u^(`larg')" } else local lst "(u/`farg')^(`larg')" } else if `lcode' == 10 { local lnk "Odds power" if "`farg'" == "1" { local lst "((u/(1-u))^(`larg')-1)/(`larg')" } else local lst "((u/(`farg'-u))^(`larg')-1)/(`larg')" } ret local lnk "`lnk'" ret local larg "`larg'" ret local lcode "`lcode'" ret local lstr "`lst'" end program define MapF, rclass args fam farg local fcode = -1 local f = lower(trim(`"`fam'"')) local n = length(`"`f'"') if `"`f'"' == "" { local fcode = 0 } else if `"`f'"'==substr("gaussian",1,max(3,`n')) { local fcode = 0 } else if `"`f'"'==substr("normal",1,`n') { local fcode = 0 } else if `"`f'"'==substr("binomial",1,`n') { local fcode = 2 } else if `"`f'"'==substr("bernoulli",2,`n') { local fcode = 1 } else if `"`f'"'==substr("poisson",1,`n') { local fcode = 3 } else if `"`f'"'==substr("gamma",1,max(3,`n')) { local fcode = 4 } else if `"`f'"'==substr("igaussian",1,max(2,`n')) { local fcode = 5 } else if `"`f'"'==substr("inormal",1,max(2,`n')) { local fcode = 5 } else if `"`f'"'==substr("ivg",1,max(2,`n')) { local fcode = 5 } else if `"`f'"'==substr("nbinomial",1,max(2,`n')) { local fcode = 6 } else if `"`f'"'==substr("power",1,max(3,`n')) { local fcode = 7 } if "`farg'" != "" { local n : word count `farg' if `n' > 1 { noi di in red "illegal family argument" exit 198 } capture confirm number `farg' if _rc { capture confirm numeric variable `farg' if _rc { noi di in red "unknown variable `farg'" exit 111 } capture assert bad==long(bad) if _rc { noi di in red "Variable `farg' is not integer" exit 499 } } else { if `farg' <= 0 { noi di in red "illegal family argument" exit 198 } if `fcode' == 2 { capture confirm integer number `farg' if _rc { noi di in red /* */ "Binomial argument must be integer" exit 198 } } } } else { local farg = 1 } if `fcode' == 2 & `farg' == 1 { local fcode = 1 } local scale1 0 if `fcode' == -1 { noi di in red "Unknown family function" exit 198 } else if `fcode' == 0 { local fam "Gaussian" local fst "1" } else if `fcode' == 1 { local fam "Bernoulli" local fst "u(1-u)" local scale1 1 } else if `fcode' == 2 { local fam "Binomial" local fst "u(1-u/(`farg'))" local scale1 1 } else if `fcode' == 3 { local fam "Poisson" local fst "u" local scale1 1 } else if `fcode' == 4 { local fam "Gamma" local fst "u^2" } else if `fcode' == 5 { local fam "Igauss" local fst "u^3" } else if `fcode' == 6 { local fam "Neg. Binomial" local fst "u+(`farg')u^2" local scale1 1 } else if `fcode' == 7 { local fam "Power" local fst "u^(`farg')" } ret local fam "`fam'" ret local farg "`farg'" ret local fcode "`fcode'" ret local fstr "`fst'" ret local scale1 "`scale1'" end program define FixBeta local beta "`1'" local nc = colsof(`beta') local nc1 = `nc'-1 mat `beta' = `beta'[1,`nc'], `beta'[1,1..`nc1'] end program define ChkReps args touse local neq = $S_WL1 local i 2 local ip1 = `neq'+1 local kmin = 1e300 while `i' <= `ip1' { local k : word count ${S_WL`i'} if `k' < `kmin' { local kmin = `k' } local i = `i'+1 } local cmp "" local i 2 while `i' <= `ip1' { tempvar miss`i' local eval "0" local j 1 local tp 1 while `j' <= `kmin' { local v`j' : word `j' of ${S_WL`i'} local eval "`eval'+`tp'*(`v`j''==.)" local j = `j'+1 local tp = `tp'*2 } qui gen `miss`i'' = `eval' qui replace `touse' = 0 if `miss`i'' != `miss2' local i = `i'+1 } local i 2 while `i' <= `ip1' { local nk : word count ${S_WL`i'} if `nk' > `kmin' { local lst "" local j 1 while `j' <= `kmin' { local xx : word `j' of ${S_WL`i'} local lst "`lst'`xx' " local j = `j'+1 } while `j' <= `nk' { local xx : word `j' of ${S_WL`i'} noi di as res "`xx'" as txt /* */ " (replication var) dropped" local j = `j'+1 } global S_WL`i' "`lst'" } local i= `i'+1 } end program define qvfmex, plugin