program define svytabs version 7.0 *! version 4.0.1 by Michael Blasnik 3/11/2001 *! generates complex tables for publication using svytab syntax varlist [if], [by(varname) MUlti VCol2(varlist) SUBpops(varlist) /* */ STars SAVing(str) APPend REPlace DETail noTItle CTitle(str) TEXT(str) /* */ ROW(int 2) CI SE LEVel(int $S_level) NRaw NPop CHKval FLagerr(int 0) /* */ deff ifchi(str) SCreen ] quietly { set more off set linesize 200 svy_get strata local strvar "`s(varname)'" svy_get psu local psuvar "`s(psu)'" marksample touse, novarlist markout `touse' `strvar' `psuvar', strok * check for global macros set for options if "`npop'"=="" & "$tabnpop"=="1" {local npop "npop"} if "`nraw'"=="" & "$tabnraw"=="1" {local nraw "nraw"} tempname vPcnt vrawsum if "`chkval'"=="" & "$tabchkv"=="1" {local chkval "chkval"} if `flagerr'==0 & real("$tabflag")<. {local flagerr "$tabflag"} if "`se'"=="" & "$tabse"=="1" {local se "se"} if "`ci'"=="" & "$tabci"=="1" {local ci "ci"} if "`deff'"=="" & "$tabdeff"=="1" {local deff "deff"} if "`detail'"!="" | "$tabdet"=="1" {local noi "noisily"} if "`ci'"!="" | `flagerr'>0 {local svyci "ci"} local cilevel=`level'+(100-`level')/2 if "`screen'"=="" { local delim "," local nfmt "%6.1f" } else { local delim " " local nfmt "%8.1f" local sfmt "%8s" } * create fake byvar if none specified, tricks svytab into working local fakeby=0 if "`by'"=="" { if "`stars'"!="" { di as error "stars option meaningless without by(var)" exit 198 } tempvar dummy gen byte `dummy'=0 local by "`dummy'" local fakeby=1 } * get lengths of varlist(s) and check if OK local v1cnt: word count `varlist' local v2cnt: word count `vcol2' if `v1cnt'!=`v2cnt' & "`vcol2'"!="" { di in red "Second varlist not same length as primary" exit 198 } if "`multi'"!="" & (`v1cnt'>1 | `v2cnt'>0) { di in red "Can only specify 1 variable with multi option" exit 198 } local col "col" * set up logging of output local fliplog = ("`detail'"!="") & ("`saving'"!="") qui log local logname "`r(filename)'" local logon "`r(status)'" if "`saving'"!="" { cap log close log using ${tabdir}`saving', `append' `replace' text set linesize 255 } if "`detail'"!="" & "`logname'"=="" { di in red "Detail option is useless without a log file open" exit 198 } * create title line of table if "`title'"=="" & "`saving'"!="" { if substr(lower("`saving'"),1,5)=="table" { local title =substr("`saving'",1,5)+" "+substr("`saving'",6,.) local title "`title'. `text'" } else {local title "`saving'. `text'"} } if "`title'`saving'"=="" & "`text'"!="" {local title "`text'"} if "`ctitle'"!="" {local head2 "`ctitle'"} tempname v deffv erow ecol pct colsum local spopN: word count `subpops' local spopN=max(1,`spopN') local bylab: value label `by' * get variable and value labels tokenize "`varlist'" local c1wid=max(8,length("`ctitle'")) local i=1 while "``i''"!="" { local vallb`i': value label ``i'' local varlb`i': variable label ``i'' if "`varlb`i''"=="" {local varlb`i' "``i''"} * get rid of commas from any labels to maintain comma parsing local varlb`i': subinstr local varlb`i' `","' `"-"' , all if "`ctitle'"=="" & "`multi'"!="" { local head2 "`varlb`i''" local c1wid=max(`c1wid',length("`varlb`i''")) } local tablb`i' : char ``i''[tablab] if "`tablb`i''"=="" {local tablb`i' "``i''"} local c1wid=max(`c1wid',length("`tablb`i''")) local i=`i'+1 } local c1wid=`c1wid'+1 if "`screen'"!="" {local scrn "%-`c1wid's "} if "`multi'"!="" & "`screen'"!="" { local head2a "`head2'" local head2 "" } else { if "`head2'"=="" {local head2 " "} local head2 : di `scrn' "`head2'" } if `fakeby'==0 {local head1 : di `scrn' " "} if "`npop'"!="" {local head3 : di `scrn' " "} * go through varlist local vl=1 /* keep track of which varlist if vcol2 is specified */ local i=1 local var: word `i' of `varlist' while "`var'"!="" { if `vl'==1 & "`multi'"=="" { local disp: di `scrn' "`tablb`i''" local sedisp: di `scrn' " " local cidisp: di `scrn' " " local deffdi: di `scrn' " " local star } * go through subpops forvalues spopn =1/`spopN'{ local spop: word `spopn' of `subpops' if "`spop'"!="" {local subpop "subpop(`spop')"} cap local spopnm: char `spop'[tablab] if "`spopnm'"=="" {local spopnm "`spop'"} if "`screen'"!="" {local spopnm: di `sfmt' abbrev("`spopnm'",8)} * on first go within an spop, get col pop counts & make headers if `i'==1 { tempname Pcnt Pcat if "`spop'"!="" {local ifspop " & `spop'<. "} tab `by' if `touse' `ifspop' , matcell(`Pcnt') matrow(`Pcat') `subpop' local pcats=rowsof(`Pcnt') forvalues k=1/`pcats' { local Pcol`k'=`Pcnt'[`k',1] local Pcat`k'=`Pcat'[`k',1] if "`bylab'"!="" { local Pcnam`k': label `bylab' `Pcat`k'' } else {local Pcnam`k'=`Pcat`k''} local Pcnam`k': subinstr local Pcnam`k' `","' `"-"' , all if "`screen'"!="" { local Pcnam`k': di `sfmt' abbrev("`Pcnam`k''",8) } if !`fakeby' {local head2 "`head2'`delim'`Pcnam`k''"} if "`spop'"!="" {local head1 "`head1'`delim'`spopnm'"} if "`npop'"!="" { local npopd: di `sfmt' "(n=`Pcol`k'')" local head3 "`head3'`delim'`npopd'" } } if `pcats'<2 & `fakeby'==0 {local warn1 "Warning <2 columns detected"} local oldnrow=0 } * now run the svytab command & log it as needed if `fliplog' { cap log close log using `logname' , append } * if special condition for chi2 test, do it now and grab p if "`ifchi'"!=""{ `noi' di "svytab `var' `by' if `touse' & `ifchi', `col' `subpop' " `noi' svytab `var' `by' if `touse' & `ifchi', `col' `subpop' local pvar=e(p_Pear) } `noi' di "svytab `var' `by' if `touse', `col' `subpop' `svyci' `se' `deff'" `noi' svytab `var' `by' if `touse', `col' `subpop' `svyci' `se' `deff' if `fliplog' { log close log using ${dir}`saving', append text } * capture results of command local nrow=e(r) local ncol=e(c) mat `erow'=e(Row) mat `ecol'=e(Col) mat `pct'=e(Prop) local starlen=length("`star'") local star if "`ifchi'"=="" {local pvar=e(p_Pear)} mat `colsum'=J(1,`nrow',1) mat `colsum'=`colsum'*`pct' /* sum up column total proportions */ if "`se'`svyci'"!="" {mat `v'=e(V)} if "`deff'"!="" {mat `deffv'=e(Deff)} local t=invttail(e(N_psu)-e(N_strata),`cilevel'/100) if `i'>1 & `nrow'!=`oldnrow' {local warn2 "Warning, inconsistent number of rows"} local oldnrow=`nrow' if `nrow'>(max(2,`row')) & "`multi'"=="" {local warn3 "`warn3' `var'"} * if chkval option, grab name of category for var of interest local rowval if "`chkval'"!="" & `spopn'==`spopN' & "`multi'"==""{ local rowvl=`erow'[1,`row'] cap local rowval: label `vallb`i'' `rowvl' if "`rowval'"=="" {local rowval "`rowvl'"} local rowval: subinstr local rowval `","' `"-"' , all local rowval "`delim'`rowval'" } *calc statistical significance and add asterisks as needed if "`stars'"!="" { if `pvar'==. {local warn4 "`warn4'`var' "} else {local star=substr("**",1,(`pvar'<.05)+(`pvar'<.01))} } * if raw counts wanted, do tab to get them into matrix if "`nraw'"!="" { tab `var' `by' if `touse' `ifspop',`subpop' matcell(`vPcnt') mat `vrawsum'=J(1,`nrow',1) mat `vrawsum'=`vrawsum'*`vPcnt' } * now loop through categories of byvar * j is counter for column of byvar in pop local k=1 /* counter for column of byvar in results matrix */ forvalues j=1/`pcats' { local kplus=(`ecol'[1,`k']==`Pcat`j'') /* don't increment if column missing */ if "`multi'"=="" { cap local resval=`pct'[`row',`k']/(`colsum'[1,`k']*`kplus') local res=string(100*`resval',"`nfmt'") if "`res'"=="." {local res="--"} if "`screen'"!="" & `j'==1 { /* adjust screen display for asterisks */ local rfmt=8-`starlen' local rfmt="%`rfmt's" } else {local rfmt "`sfmt'"} local res: di `rfmt' "`res'" local disp "`disp'`delim'`res'" * accumulate min & max counts by varlistcol,column,subpop if "`nraw'"!="" { if `resval'!=. {local Nraw=`vrawsum'[1,`k']} else {local Nraw=0} if `i'==1 { local r`vl'n`j's`spopn'=`Nraw' local r`vl'x`j's`spopn'=`Nraw' } local r`vl'n`j's`spopn'=min(`Nraw',`r`vl'n`j's`spopn'') local r`vl'x`j's`spopn'=max(`Nraw',`r`vl'x`j's`spopn'') } * get standard errors or confidence intervals as requested if "`se'`svyci'"!="" { local elemnt=(`row'-1)*`ncol'+`k' secalc `v' `elemnt' `resval' `t' `flagerr' if "`se'"!="" {local sedisp: di "`sedisp'`delim'" `sfmt' "`r(se)'"} if "`ci'"!="" {local cidisp: di "`cidisp'`delim'" `sfmt' "`r(ci)'"} if `r(cimax)'>`flagerr' & `flagerr'>0 {local disp "`disp'~"} } * get deff as requested if "`deff'"!="" { local elemnt=(`row'-1)*`ncol'+`k' local deffval=`deffv'[1,`elemnt'] local deffval=string(`deffval',"%5.2f") local deffdi: di "`deffdi'`delim'" `sfmt' "{`deffval'}" } } else { /*else it's a multirow x-tab */ * get row labels of multicat var if `k'==1 & `spopn'==1 { local labwid=`c1wid' forvalues r=1/`nrow' { local val=`erow'[1,`r'] if "`vallb`i''"!=""{ local rlab: label `vallb`i'' `val' } else {local rlab "`val'"} local rlab: subinstr local rlab `","' `"-"' , all local disp`r' "`rlab'" local labwid=max(`labwid',length("`rlab'")) } if "`screen'"!="" { local xspace=`labwid'-`c1wid' if `xspace'>0 { local head1: di _dup(`xspace') " " "`head1'" local head3: di _dup(`xspace') " " "`head3'" } local head2: di %-`labwid's "`head2a'" %1s "`head2'" forvalues r=1/`nrow' { local disp`r': di %-`labwid's "`disp`r''" local sedis`r': di %`labwid's " " local cidis`r': di %`labwid's " " local deffd`r': di %`labwid's " " } } } forvalues r=1/`nrow' { cap local resval=`pct'[`r',`k']/(`colsum'[1,`k']*`kplus') local res=string(100*`resval',"`nfmt'") if "`res'"=="." {local res="--"} if "`screen'"!="" & `j'==1{ local rfmt=8-`starlen' local rfmt="%`rfmt's" } else {local rfmt "`sfmt'"} local res: di `rfmt' "`res'" local disp`r' "`disp`r''`delim'`res'" * get std err or conf int as requested if "`se'`svyci'"!="" { local elemnt=(`r'-1)*`ncol'+`k' secalc `v' `elemnt' `resval' `t' `flagerr' if "`se'"!="" {local sedis`r': di "`sedis`r''`delim'" `sfmt' "`r(se)'"} if "`ci'"!="" {local cidis`r': di "`cidis`r''`delim'" `sfmt' "`r(ci)'"} if `r(cimax)'>`flagerr' & `flagerr'>0 {local disp`r' "`disp`r''~"} } * get deff as requested if "`deff'"!="" { local elemnt=(`r'-1)*`ncol'+`k' local deffval=`deffv'[1,`elemnt'] local deffval=string(`deffval',"%5.2f") local deffd`r': di "`deffd`r''`delim'" `sfmt' "{`deffval'}" } if `j'==`pcats' {local disp`r' "`disp`r''`star'"} } } /* done with else its a multirow xtab */ local k=`k'+`kplus' } local disp "`disp'`star'" } /* go on to next subpop */ * display header if `i'==1 & (`vl'==2 | (`vl'==1 & `v2cnt'==0)){ if "`title'"!="notitle" {noi di as text "`title'"} if trim("`head1'")=="" & trim("`head2'")!="" {noi di as text "`head2'"} else { if `fakeby'==1 & trim("`head2'`head1'")!="" {noi di as text "`head2'`head1'"} else if trim("`head1'")!="" | trim("`head2'")!="" {noi di as text "`head1'" _newline "`head2'"} } if "`npop'"!="" {noi di as result "`head3'"} } * display results if "`multi'"=="" & (`vl'==2 | (`vl'==1 & `v2cnt'==0)) { noi di as result "`disp'`rowval'" if "`se'"!="" & "`sedisp'"!="" {noi di as result "`sedisp'"} if "`ci'"!="" & "`cidisp'"!="" {noi di as result "`cidisp'"} if "`deff'"!="" & "`deffdi'"!="" {noi di as result "`deffdi'"} } * increment to next var on list if `vl'==1 & `v2cnt'>0 { local var: word `i' of `vcol2' local vl=2 } else { local vl=1 local i=`i'+1 local var: word `i' of `varlist' } } /* go on to next variable */ * if its multicat, then display all results at end if "`multi'"!="" { local r=1 while "`disp`r''"!="" { noi di as result "`disp`r''" if "`se'"!="" & "`sedis`r''"!="" {noi di as result "`sedis`r''"} if "`ci'"!="" & "`cidis`r''"!="" {noi di as result "`cidis`r''"} if "`deff'"!="" & "`deffd`r''"!="" {noi di as result "`deffd`r''"} local r=`r'+1 } } * display min & max counts by column if "`nraw'"!="" { local rndisp: di `scrn' "Raw Counts" local ivl=1 while `ivl'<=(2-(`v2cnt'==0)) { forvalues ispop=1/`spopN' { forvalues icol=1/`pcats' { local rndis: di `sfmt' "`r`ivl'n`icol's`ispop''..`r`ivl'x`icol's`ispop''" local rndisp "`rndisp'`delim'`rndis'" } } local ivl=`ivl'+1 } noi di as result "`rndisp'" } * display notes and warnings if "`se'"!="" {noi di as text "standard errors displayed in parentheses below values"} if "`ci'"!="" {noi di as text "`level'% confidence intervals displayed in parentheses below values"} if "`deff'"!="" {noi di as text "deff displayed in braces below values"} if `flagerr'>0 { noi di as text "values with more than `flagerr' percentage point uncertainty at `level'% confidence flagged with ~" } if "`stars'"!="" & `pvar'<. { if "`ifchi'"!="" {local ifchi " (`ifchi')"} noi di as text "statistically signficant differences by `by'`ifchi' flagged: *=(p<.05) **=(p<.01)" } if "`warn1'"!="" {noi di as text "`saving': `warn1'"} if "`warn2'"!="" {noi di as text "`saving': `warn2'"} if "`warn3'"!="" {noi di as text "`saving': Warning, more than 2 levels detected for `warn3'"} if "`warn4'"!="" {noi di as text "`saving': Warning: Chi-square could not be calculated for `warn4'"} * clean up logs if "`saving'"!="" {log close} if "`logname'"!="" & "`saving'"!="" { log using `logname', append log `logon' } set more on } /* end of quietly zone */ end program define secalc, rclass version 7.0 args v elemnt resval t flagerr local seval=sqrt(`v'[`elemnt',`elemnt']) local sevald=string(100*`seval',"%6.1f") if `resval'==. { local seval=. local sevald "--" } local sedi "(`sevald')" local ub=1/(1+exp(-(log(`resval'/(1-`resval'))- /* */ `t'*`seval'/(`resval'*(1-`resval'))))) local lb=1/(1+exp(-(log(`resval'/(1-`resval'))+ /* */ `t'*`seval'/(`resval'*(1-`resval'))))) local cimx=100*max(`ub'-`resval',`resval'-`lb') local lb=string(100*`lb',"%5.1f") local ub=string(100*`ub',"%5.1f") local cidi "(`lb'-`ub')" return local se "`sedi'" return local ci "`cidi'" return local cimax "`cimx'" end