I'm going to split my response across multiple posts. This post is for
the first request. The next post is for the second request. Then I'll
post the entire program with an example showing off both new features.
---
You can add the zeros with something like
Code:
collect get fvfrequency=0 fvpercent=0, tags(...)
add non-integer numeric categories, then you must use the bracket notation.
For example,
Code:
collect get fvfrequency=0 fvpercent=0, tags(cat2[3.5] female[0])
categorical() from
Code:
CATegorical(varlist) ///
Code:
CATegorical(string) ///
macro categorical containing the categorical variables and a new
macro that specifies where to add the zero results among the categorical
variables.
Code:
ParseCategorical `categorical' local categorical `"`s(varlist)'"' local FVzeros `"`s(zeros)'"'
Code:
program ParseCategorical, sclass syntax [varlist(default=none)] [, ZEROs(string)] if `:list sizeof varlist' == 0 { if `:list sizeof zeros' { di as err /// "option {bf:zeros()} requires categorical variables" exit 198 } } gettoken spec zeros : zeros , parse(" []") while `:length local spec' { capture noisily unab names : `spec' if c(rc) { di as err "in option {bf:zeros()}" exit c(rc) } foreach name of local names { if `:list posof "`name'" in varlist' == 0 { di as err "invalid {bf:zeros()} option" di as err /// "variable {bf:`name'} not found in list of categorical variables" exit 198 } } gettoken open zeros : zeros , parse(" []") if `"`open'"' == "" { di as err "invalid {bf:zeros()} option" di as err `"nothing found where {bf:[} expected"' exit 198 } if `"`open'"' != "[" { di as err "invalid {bf:zeros()} option" di as err `"{bf:`open'} found where {bf:[} expected"' exit 198 } gettoken tok zeros : zeros , parse(" []") while !inlist(`"`tok'"', "", "]") { capture noisily confirm number `tok' if c(rc) { di as err "in option {bf:zeros()}" exit c(rc) } foreach name of local names { local ZEROS `ZEROS' `name'[`tok'] } gettoken tok zeros : zeros , parse(" []") } if `"`tok'"' != "]" { di as err "invalid {bf:zeros()} option" di as err `"closing square bracket '{bf:]}' not found"' exit 198 } gettoken spec zeros : zeros , parse(" []") } sreturn local varlist `"`varlist'"' sreturn local zeros `"`ZEROS'"' end
specified zero results. Here is a code snippet for how I did this.
Code:
quietly collect levelsof `by' local by_levels = s(levels) foreach l of local by_levels { foreach z of local FVzeros { collect get fvfrequency=0 fvpercent=0, /// tags(`z' `by'[`l']) } }
call to
Code:
collect style autolevels `x' _hide `s(levels)', clear
of digits. To fix this I added a short Mata function call to fix the order of
the levels returned by collect levelsof. Here is the definition of the
Mata function I added at the end of the ado-file
Code:
mata: void mw_table_sort_cat_levels() { vector levels real vector sel real vector order levels = tokens(st_global("s(levels)")) sel = levels :!= "_hide" order = order(strtoreal(select(levels,sel))', 1) levels = levels[order] st_global("s(levels)", invtokens(levels)) } end
Code:
foreach x of local categorical {
quietly tabulate `x' `by', chi2
collect get nobs=(r(N)) p=(r(p)), tag(`x'[_hide])
collect style header `x', title(label)
quietly collect levelsof `x'
mata: mw_table_sort_cat_levels()
collect style autolevels `x' _hide `s(levels)', clear
}
Comment