*! version 1.0.7 27nov2011 Daniel Klein pr chm ,by(o) vers 9.2 * parse user input gettoken chmcall usercmd : 0 ,p(:) if (`"`chmcall'"' == ":") { di as err "varlist required" e 100 } // command or prefix if (`"`chmcall'"' == `"`0'"') { // command loc iscmd 1 loc ifin [if] [in] loc replace_opt REPLACE loc mi_opt MI } else { // prefix loc iscmd 0 loc usercmd : subinstr loc usercmd ":" "" if (`"`usercmd'"' == "") { di as err "command required" e 100 } unabcmd `: word 1 of `usercmd'' loc cmd `r(cmd)' loc supported generate egen replace tabulate center if !(`: list cmd in supported') loc support 0 else loc support 1 } * parse args in standard syntax if _by() loc _byc by `_byvars' `_byrc0' : loc 0 `chmcall' syntax varlist(numeric) `ifin' , `replace_opt' /* */ [ MVC(numlist miss max = 1) SOFT SYSmiss EXECute `mi_opt' ] * options if (`iscmd') & ("`mi'" == "") & (`: word count `varlist'' < 2) { err 102 } if ("`mvc'" != "") { if (real("`mvc'") <= .) { di as err "{it:mvc} must be one of .a, .b, ..., .z" e 198 } } if ("`sysmiss'" != "") loc soft soft if !(`iscmd') { if !(`support') { if ("`execute'" == "") { di as err "`cmd' currently not supported" e 101 } di as txt "(note: `cmd' currently not supported)" } } * pass on to mi-subroutine if ("`mi'" != "") { _chmmidta `varlist' `if' `in' ,mvc(`mvc') `soft' by(`_byc') e 0 // done } else loc chmvars `varlist' * some settings if (`iscmd') { loc cpyto : word `: word count `chmvars'' of `chmvars' loc chmvars : list chmvars - cpyto * mark sample marksample touse ,nov qui cou if `touse' if (r(N) == 0) err 2000 } else { loc 0 `usercmd' syntax [anything(equalok)] [if][in] [fw aw iw] [ , *] // weights not used by chm but not an error * mark sample marksample touse ,nov qui cou if `touse' if (r(N) == 0) err 2000 loc cmd_ok 0 // generate and egen if (inlist("`cmd'", "generate", "egen")) { loc cmd_ok 1 gettoken new_var : usercmd ,p("=") if (strpos("`new_var'", ":")) { gettoken new_var : new_var ,p(":") } loc cpyto : word `: word count `new_var'' of `new_var' } // replace if ("`cmd'" == "replace") { tempname tmp_old loc cmd_ok 1 gettoken old_var : usercmd ,p("=") loc cpyto : word 2 of `old_var' qui g `: t `cpyto'' `tmp_old' = `cpyto' loc chmvars : list chmvars - cpyto loc chmvars `chmvars' `tmp_old' } // tabulate if ("`cmd'" == "tabulate") { loc cmd_ok 1 loc 0 ,`options' syntax ,Generate(name) [ * ] loc stubname `generate' } // center if ("`cmd'" == "center") { loc cmd_ok 1 loc anything : list anything - cmd loc 0 `anything' ,`options' syntax varlist [, Generate(string) PREfix(string) *] if ("`generate'" != "") loc cpyto `generate' else { if ("`prefix'" == "") loc prefix c_ foreach center_var of loc varlist { loc cpyto `cpyto' `prefix'`center_var' } } } * excecute command `_byc' `usercmd' * command not supported if !(`support') e 101 // done * get cpyto if command is -tabulate- if ("`cmd'" == "tabulate") { forv j = 1/`r(r)' { loc cpyto `cpyto' `stubname'`j' } } * check numeric variable if inlist("`cmd'", "generate", "egen", "replace") { cap conf numeric v `cpyto' if _rc { if inlist("`cmd'", "generate", "egen") drop `cpyto' if ("`cmd'" == "replace") qui replace `cpyto' = `tmp_old' di as err "string variables not allowed with chm" e 109 } } } * copy hard missings foreach v of loc chmvars { foreach c of loc cpyto { loc m_v_c = cond("`mvc'" != "", "mvc", "v") if ("`soft'" == "") loc nosoft & (`v' != .) qui `_byc' replace `c' = ``m_v_c'' /* */ if !inrange(string(`c'), ".a", ".z") /* */ & mi(`v') `nosoft' & `touse' } } end prog _chmmidta * check mi data if ("`_dta[mi_id]'" == "_mi") { loc _miid _mi loc _mim _mj } else { u_mi_assert_set flong loc _miid _mi_id loc _mim _mi_m } syntax varlist [if][in] [, MVC(numlist miss) SOFT by(str)] * mark sample marksample touse ,nov qui replace `touse' = 0 if `_mim' == 0 qui cou if `touse' if (r(N) == 0) err 2000 * set locals if ("`soft'" != "") loc eq "=" if ("`mvc'" != "") loc _mvc `mvc' foreach v of loc varlist { if ("`mvc'" == "") { qui levelsof `v' if (`v' >`eq' .) ,miss loc(_mvc) if (`: word count `_mvc'' == 0) continue } foreach _mv of loc _mvc { if ("`mvc'" == "") { qui levelsof `_miid' if (`v' == `_mv') ,loc(id2c) } else { qui levelsof `_miid' if (`v' >`eq' .) ,loc(id2c) if (`: word count `id2c'' == 0) continue } if (`: word count `id2c'' <= 249) { loc id2c : subinstr loc id2c " " "," ,all qui `by' replace `v' = `_mv' /* */ if inlist(`_miid', `id2c') & `touse' } else { foreach id of loc id2c { qui `by' replace `v' = `_mv' /* */ if (`_miid' == `id') & `touse' } } } } end e History 1.0.7 27nov2011 clean code check fatal conditions earlier preserve double variables remove subroutine -errex- option -execute- no longer documented 1.0.6 11jun2011 -by- supports -rc0- option -sysmiss- as synonym for -soft- (not documented) 1.0.5 03jun2011 add -mi- option and subroutine downward compatibility with Stata 9.2 change check commands (use unabcmd) 1.0.4 01apr2011 change check commands 1.0.3 na fixed bug (missing -marksample-) 1.0.2 na add -center- command and -execute- option minor changes in error messages 1.0.1 na do no longer run command quietly