*! version 1.8.6 22feb2023 Ben Jann program coefplot version 11 nobreak { capt mata: mata drop COEFPLOT_STRUCT capt n break _coefplot `macval(0)' local rc = _rc capt mata: mata drop COEFPLOT_STRUCT exit `rc' } end program _coefplot, rclass // get subgraphs and parse global options parse_subgraphs `macval(0)' // returns n_subgr, subgr_#, opts parse_globalopts `macval(opts)' // returns expanded global opts and twopts, // subgropts0, plotopts0, modelopts0, twplotopts0 // backup current estimates, initialize struct tempname ecurrent _est hold `ecurrent', restore estsystem nullok mata: COEFPLOT_STRUCT = coefplot_struct_init() // dryrun across subgraphs and plots to collect options local i 0 local N_plots 0 forv j = 1/`n_subgr' { if "`recycle'"=="" local i 0 local firstplot_`j' = `i'+1 parse_plots `j' `macval(subgr_`j')' // returns n_plots_j, plot_j_#, opts if ("`recycle'"=="" & `n_subgr'>1) { combine_plotopts, `macval(opts)' _opts0(`macval(plotopts1prev)') local plotopts1prev `macval(plotopts)' local opts `macval(plotopts)' `macval(options)' } merge_subgropts, `macval(opts)' _opts0(`subgropts0' `plotopts0' `macval(modelopts0)') // returns subgropts, plotopts1, modelopts1, twplotopts1 parse_subgropts `j', `subgropts' forv k = 1/`n_plots_`j'' { local ++i local twplotopts1_`i' `twplotopts1_`i'' `twplotopts1' parse_models `j' `k' `macval(plot_`j'_`k')' // returns n_models_j_k, model_j_k_#, opts if `n_models_`j'_`k''==1 & `"`model_`j'_`k'_1'"'=="_skip" { if `"`opts'"'!="" { di as err "options not allowed with _skip" exit 198 } continue } if (`i'>`N_plots') { // get p#() from twoplotopts0 parse_get_popt_i `i', `macval(twplotopts0)' // returns twplotopts0, plotopts if `"`macval(plotopts)'"'!="" { merge_plotopts, `macval(plotopts)' // to isolate the modelopts local popt_mopts_`i' `macval(modelopts2)' merge_plotopts, `macval(opts)' /// _opts0(`macval(modelopts2)' `plotopts' `_opts0' `options') // returns plotopts, modelopts2, options, _opts0 local opts `macval(modelopts2)' `plotopts' `_opts0' `options' } } else { if `"`macval(popt_mopts_`i')'"'!="" { // add modelopts from p#() merge_plotopts, `macval(opts)' _opts0(`macval(popt_mopts_`i')') // returns plotopts, modelopts2, options, _opts0 local opts `macval(modelopts2)' `plotopts' `_opts0' `options' } } if ("`recycle'"=="" & `n_subgr'>1) { combine_plotopts, `macval(opts)' _opts0(`macval(plotopts2_`i')') local plotopts2_`i' `macval(plotopts)' local opts `macval(plotopts)' `macval(options)' } merge_plotopts, `macval(opts)' _opts0(`macval(plotopts1)' `macval(modelopts1)') // returns plotopts, modelopts2, options, _opts0 if `"`_opts0'"'!="" error 198 local modelopts_`j'_`k' `macval(modelopts2)' local twplotopts_`i' `twplotopts_`i'' `options' local plotopts_`i' `plotopts' } local lastplot_`j' `i' local N_plots = max(`N_plots', `i') } // expand plotopts local customoffset 0 forv i = 1/`N_plots' { parse_plotopts `i', `plotopts_`i'' if `"`offset_`i''"'!="" local customoffset 1 } // parse cismooth forv i = 1/`N_plots' { local cis_`i' = `"`cismooth_`i''"'!="" if `cis_`i'' { if `"`cismooth_`i''"'=="cismooth" local cismooth_`i' parse_cismooth `i', `cismooth_`i'' // returns cis_levels_i, // cis_n_i, cis_lwidth_i, cis_intens_i, cis_color_i, cis_pstyle_i } else local cis_n_`i' = 0 } // parse models and collect results local i 0 forv j = 1/`n_subgr' { if "`recycle'"=="" local i 0 forv k = 1/`n_plots_`j'' { local ++i if `n_models_`j'_`k''==1 & `"`macval(model_`j'_`k'_1)'"'=="_skip" { continue } forv l = 1/`n_models_`j'_`k'' { parse_model `macval(model_`j'_`k'_`l')' // returns model, matrix, opts if `"`matrix'"'=="" { if `"`model'"'=="." { _est unhold `ecurrent' } else { qui est restore `model' } } collect_coefs `"`model'"' /// "`matrix'" /// matrix mode? "`atmode'" /// whether at() is used; will be replaced `i' /// plot number `j' /// subgraph number "`cis_levels_`i''" /// , `macval(opts)' _opts0(`macval(modelopts_`j'_`k')') // returns equation, atmode, n_ci // may reset mlabel_# and mlabvposition_# local n_ci = `n_ci' - `cis_n_`i'' if `"`matrix'"'=="" & `"`model'"'=="." { _est hold `ecurrent', restore estsystem nullok } if "`n_ci_`i''"=="" local n_ci_`i' 0 local n_ci_`i' = max(`n_ci_`i'', `n_ci') mata: coefplot_add_label(COEFPLOT_STRUCT, "by", `j', "model", 0) if `"`equation'"'!="" { if `"`model'"'=="." local model `"`equation'"' else local model `"`model'=`equation'"' } mata: coefplot_add_label(COEFPLOT_STRUCT, "plot", `i', "model", 0) } } } forv i = 1/`N_plots' { // expand ciopts if `n_ci_`i''>0 { parse_ciopts_nocilwincr `i', `ciopts_`i'' `cirecast_`i'' // returns nocilwincr_# parse_ciopts `i' `n_ci_`i'' `ciopts_`i'' `cirecast_`i'' } } mata: coefplot_set_r(COEFPLOT_STRUCT) // returns r, N_ci, N_aux, mlbllen local mlbllen = max(1, min(c(maxstrvarlen), `mlbllen')) if `r'==0 { di as txt "(nothing to plot)" exit } // cleanup and and arrange if `"`horizontal'`vertical'"'=="" { if `atmode' local vertical vertical else local horizontal horizontal } if `"`horizontal'"'!="" { local xaxis y local yaxis x local offdir "-" local reverse yscale(reverse) local plotregion plotregion(margin(t=0 b=0)) } else { // vertical local xaxis x local yaxis y local offdir "+" local plotregion plotregion(margin(l=0 r=0)) } if `atmode' { if "`bycoefs'"!="" { di as err "at() and bycoefs not both allowed" exit 198 } local grid `"`grid'`gridopts'"' foreach opt in order coeflabels eqlabels relocate headings /// groups grid { if `"``opt''"'!="" { di as err "at() and `opt'() not both allowed" exit 198 } } mata: coefplot_add_eq_and_grp(COEFPLOT_STRUCT) local reverse local plotregion local meqs 0 } else { if `"`eqstrict'"'!="" local meqs 1 else { mata: coefplot_multiple_eqs(COEFPLOT_STRUCT) // returns meqs } mata: coefplot_arrange(COEFPLOT_STRUCT) // updates local r mata: coefplot_coeflbls(COEFPLOT_STRUCT) coeflbls "`labels'" `"`clinteract'"' if "`bycoefs'"!="" { mata: coefplot_bycoefs(COEFPLOT_STRUCT) // returns n_subgr local meqs 0 } mata: coefplot_catvals(COEFPLOT_STRUCT) // modifies C.at; sets C.eq, C.grp; returns groups mata: coefplot_headings(COEFPLOT_STRUCT) // modifies C.at; returns hlbls } // save results to variables if `"`generate'"'=="" { if (_N > `r') & "`nodrop'"=="" { preserve qui keep in 1/`r' // remove extra observations to speed up } else if (_N < `r') { preserve qui set obs `r' } } else { if (_N < `r') { di as txt "need to create additional observations; " _c di as txt "press break to abort" more set obs `r' } } tempname by plot at mlbl mlpos b V se t df pval eq grp qui gen `by' = . qui gen `plot' = . qui gen `at' = . qui gen str`mlbllen' `mlbl' = "" qui gen `mlpos' = . qui gen `b' = . qui gen `V' = . qui gen `se' = . qui gen `t' = . qui gen `df' = . qui gen `pval' = . if `"`format'"'!="" { format `format' `b' `V' `se' `t' `pval' } qui gen `eq' = . qui gen `grp' = . forv i = 1/`N_ci' { tempname ll`i' ul`i' qui gen `ll`i'' = . qui gen `ul`i'' = . if `"`format'"'!="" { format `format' `ll`i'' `ul`i'' } } forv i = 1/`N_aux' { tempname aux`i' qui gen `aux`i'' = . if `"`format'"'!="" { format `format' `aux`i'' } } if `"`generate'"'!="" { preserve local returnvars local i 0 foreach v in by plot at mlbl mlpos b V se t df pval { local ++i local varl: word `i' of /// "subgraph ID" /// "plot ID" /// "plot position (category axis)" /// "marker label" /// "marker label position" /// "coefficient" /// "variance" /// "standard error" /// "t or z statistic" /// "degrees of freedom" /// "p-value" if "`replace'"!="" { capt confirm new variable `generate'`v', exact if _rc { drop `generate'`v' } } rename ``v'' `generate'`v' lab var `generate'`v' `"`varl'"' local `v' `generate'`v' local returnvars `returnvars' `generate'`v' } forv i = 1/`N_ci' { foreach v in ll ul { if "`v'"=="ll" local varl "CI`i': lower limit" else local varl "CI`i': upper limit" if "`replace'"!="" { capt confirm new variable `generate'`v'`i', exact if _rc { drop `generate'`v'`i' } } rename ``v'`i'' `generate'`v'`i' lab var `generate'`v'`i' `"`varl'"' local `v'`i' `generate'`v'`i' local returnvars `returnvars' `generate'`v'`i' } } forv i = 1/`N_aux' { local varl "Auxiliary variable `i'" if "`replace'"!="" { capt confirm new variable `generate'aux`i', exact if _rc { drop `generate'aux`i' } } rename `aux`i'' `generate'aux`i' lab var `generate'aux`i' `"`varl'"' local aux`i' `generate'aux`i' local returnvars `returnvars' `generate'aux`i' } } mata: coefplot_put(COEFPLOT_STRUCT) mata: coefplot_apply_transform(COEFPLOT_STRUCT) qui compress `at' `df' `plot' `by' `eq' `grp' `mlpos' // not really needed // get labels set_by_and_plot_labels `plot' `by' if `"`plotlabels'"'!="" { set_labels "`plot'" "`N_plots'" `"`plotlabels'"' } if `"`pltrunc'`plwrap'"'!="" { truncwrap_vlabels "`plot'" "`N_plots'" "`pltrunc'" /// "`plwrap'" "`plbreak'" } if "`bycoefs'"=="" { if `"`bylabels'"'!="" { set_labels "`by'" "`n_subgr'" `"`bylabels'"' } if `"`bltrunc'`blwrap'"'!="" { truncwrap_vlabels "`by'" "`n_subgr'" "`bltrunc'" /// "`blwrap'" "`blbreak'" } } if `atmode'==0 { if "`grid'"=="" & "`xaxis'"=="y" { if `N_plots'>1 & `"`offsets'"'=="" local grid between else local grid within } get_axis_labels `at' `eq' `grp' "`grid'" `"`groups'"' // => returns xlabels, xgrid, xrange, eqlabels, groups if `meqs'==0 | "`noeqlabels'"!="" local eqlabels if `"`cltrunc'`clwrap'"'!="" { if "`bycoefs'"=="" { truncwrap_labels xlabels "`cltrunc'" "`clwrap'" /// "`clbreak'" `"`xlabels'"' } else { truncwrap_vlabels "`by'" "`n_subgr'" "`cltrunc'" /// "`clwrap'" "`clbreak'" } } if "`bycoefs'"!="" { if `"`bylabels'"'!="" { reset_xlabels `"`bylabels'"' `"`xlabels'"' } if `"`bltrunc'`blwrap'"'!="" { truncwrap_labels xlabels "`bltrunc'" "`blwrap'" /// "`blbreak'" `"`xlabels'"' } } if `"`clangle'"'=="" local clangle angle(horizontal) local xlabel `xaxis'label(`xlabels', nogrid `clangle' `clopts') local xrange `xaxis'scale(range(`xrange')) if !inlist("`grid'", "", "none") { local xtick `xaxis'tick(`xgrid', notick tlstyle(none) grid `gridopts') // note: tlstyle(none) is required to prevent by() from drawing // the ticks } else local xtick if "`eqashead'"!="" { merge_eqlabels_hlbls `"`eqlabels'"' `"`hlbls'"' // => returns hlbls and clears eqlabels } if `"`eqtrunc'`eqwrap'"'!="" { if `"`eqlabels'"'!="" { truncwrap_labels eqlabels "`eqtrunc'" "`eqwrap'" /// "`eqbreak'" `"`eqlabels'"' } } if `"`gtrunc'`gwrap'"'!="" { if `"`groups'"'!="" { truncwrap_labels groups "`gtrunc'" "`gwrap'" /// "`gbreak'" `"`groups'"' } } if `"`htrunc'`hwrap'"'!="" { if `"`hlbls'"'!="" { truncwrap_labels hlbls "`htrunc'" "`hwrap'" /// "`hbreak'" `"`hlbls'"' } } } // compute offsets if `customoffset' { forv i = 1/`N_plots' { if "`offset_`i''"!="" { qui replace `at' = `at' `offdir' `offset_`i'' if `plot'==`i' } } } else if `atmode'==0 & `"`offsets'"'=="" & `N_plots'>1 { capt mata: coefplot_at_unique(COEFPLOT_STRUCT) // error if not true if _rc==1 exit _rc if _rc { if "`recycle'"=="" | `n_subgr'==1 { qui replace `at' = `at' - 0.5 + `plot'/(`N_plots'+1) } else { forv j=1/`n_subgr' { qui replace `at' = `at' - 0.5 + /// (`plot'-`firstplot_`j''+1) / /// (`lastplot_`j''-`firstplot_`j''+2) if `by'==`j' } } } } // inject tempvars forv i=1/`N_plots' { foreach opt in ifopt weightopt mlabel mlabvposition { if `"``opt'_`i''"'!="" { mata: coefplot_inject_temvars("`opt'_`i'", `N_ci', `N_aux') } } } // handle string expressions in mlabel() forv i=1/`N_plots' { if `"`mlabel_`i''"'!="" { if `"`mlabel_`i''"'=="mlabel(`mlbl')" continue parse_mlabel_exp, `mlabel_`i'' // returns mlblexp capt confirm variable `mlblexp' if _rc==0 continue capt replace `mlbl' = `mlblexp' if `plot'==`i' if _rc { di as err "invalid expression in mlabel()" exit 198 } local mlabel_`i' mlabel(`mlbl') } } // compile plot local addaxis 1 local eqaxis 2 local axisalt alt if (`"`eqlabels'"'!="" & `"`groups'"'!="") | (`"`addplotbelow'"'!="") local axisalt if `"`groups'"'!="" { local ++eqaxis local addaxis `addaxis' 2 local groupsopts `xaxis'scale(axis(2) `axisalt' noline) /// `xaxis'title("", axis(2)) /// `xaxis'label(`groups', axis(2) noticks tlstyle(none) `gopts') } if `"`eqlabels'"'!="" { local addaxis `addaxis' `eqaxis' local eqaxisopts `xaxis'scale(axis(`eqaxis') `axisalt' noline) /// `xaxis'title("", axis(`eqaxis')) /// `xaxis'label(`eqlabels', axis(`eqaxis') noticks /// tlstyle(none) `eqopts') } local axisalt if "`addaxis'"!="1" { local addaxis `xaxis'axis(`addaxis') if `"`addplotbelow'"'!="" { if (`"`eqlabels'"'!="")+(`"`groups'"'!="")==1 { local axisalt `xaxis'scale(alt) } } } else local addaxis if `"`hlbls'"'!="" { local hlblsopts /// `xaxis'label(`hlbls', custom add tlstyle(none) `hopts') } local j 0 if `"`addplot'"'!="" { mata: coefplot_inject_temvars("addplot", `N_ci', `N_aux') if `"`addplotbelow'"'!="" { capt two `addplot' ||, nodraw if _rc==0 local j `.Graph.last_style' capt confirm integer number `j' if _rc local j 0 } } local plots local legendlbls local legendorder forv i=1/`N_plots' { local key if "`n_ci_`i''"=="" { continue // plot does not exist (this can happen if _skip is // specified together with norecycle) } local n_ci = `n_ci_`i'' + `cis_n_`i'' if `n_ci'==0 & `"`cionly_`i''"'!="" { continue // can happen if noci and cionly is specified } local axis if `"`axis_`i''"'!="" { local axis `yaxis'axis(`axis_`i'') } local ciplots if (`n_ci')>0 { get_pstyle_id `=mod(`i'-1,`pcycle')+1', `pstyle_`i'' // returns pstyle_id forv k = 1/`n_ci' { local lw if `k'>`cis_n_`i'' { local l = `k' - `cis_n_`i'' local ciopts `ciopts_`i'_`l'' parse_ciopts_recast_pstyle, `ciopts' // returns cirecast, cipstyle, ciopts if "`nocilwincr_`i''"=="" { local lw = string(1 + log10(`l')/log10(2)) local lw lwidth(*`lw') } local ciplotcmd rspike `ll`k'' `ul`k'' `at' if (substr(`"`cirecast'"',1,2)=="pc") { // paired coordinates local ciplotcmd `cirecast' `ll`k'' `at' `ul`k'' `at' if `"`cirecast'"'=="pcrarrow" { local ciplotcmd pcarrow `ul`k'' `at' `ll`k'' `at' } } else if `"`cirecast'"'!="" { local ciopts `ciopts' recast(`cirecast') } } else { // cismooth local l 0 local cirecast local cipstyle `cis_pstyle_`i'' local lw: word `k' of `cis_lwidth_`i'' local lw lwidth(*`lw') local lcinten: word `k' of `cis_intens_`i'' local ciopts lcolor("`cis_color_`i''*`lcinten'") `cipstyle' local ciplotcmd rspike `ll`k'' `ul`k'' `at' } if `"`cipstyle'"'!="" local pstyle else { set_pstyle `pstyle_id' `"`cirecast'"' // returns pstyle } local ciplots `ciplots' /// (`ciplotcmd' if `plot'==`i'`ifopt_`i'', `addaxis' /// `pstyle' `lw' `axis' `ciopts' `horizontal') } } if "`citop_`i''"=="" & `n_ci'>0 { local plots `plots' `ciplots' local j = `j' + `cis_n_`i'' if inrange(`key_`i'', 1, `n_ci_`i'') { local key = `j' + `key_`i'' } local j = `j' + `n_ci_`i'' } if `"`cionly_`i''"'=="" { if `"`pstyle_`i''"'!="" local pstyle `pstyle_`i'' else { set_pstyle `=mod(`i'-1,`pcycle')+1' `"`recast_`i''"' // returns pstyle } if `"`recast_`i''"'!="" local recast recast(`recast_`i'') else local recast if `"`horizontal'"'=="" | inlist(`"`recast_`i''"', /// "area", "bar", "spike", "dropline", "dot") { local plots `plots' /// (scatter `b' `at' /// if `plot'==`i'`ifopt_`i''`weightopt_`i'', /// `addaxis' `pstyle' `twplotopts0' `twplotopts1_`i'' /// `axis' `recast' `mlabel_`i'' `mlabvposition_`i'' /// `twplotopts_`i'' `horizontal') } else { local plots `plots' /// (scatter `at' `b' /// if `plot'==`i'`ifopt_`i''`weightopt_`i'', /// `addaxis' `pstyle' `twplotopts0' `twplotopts1_`i'' /// `axis' `recast' `mlabel_`i'' `mlabvposition_`i'' /// `twplotopts_`i'') } local ++j if `key_`i''==0 { local key `j' } } local plotlab `"`: lab `plot' `i''"' gettoken trash : plotlab, qed(hasquotes) if `hasquotes'==0 { local plotlab `"`"`plotlab'"'"' } if "`citop_`i''"!="" & `n_ci'>0 { local plots `plots' `ciplots' local j = `j' + `cis_n_`i'' if inrange(`key_`i'', 1, `n_ci_`i'') { local key = `j' + `key_`i'' } local j = `j' + `n_ci_`i'' } if "`key'"!="" { local legendlbls `legendlbls' label(`key' `plotlab') local legendorder `legendorder' `key' } } if `"`legendorder'"'!="" { local legendorder all order(`legendorder') if `N_plots'==1 { if `n_subgr'==1 & `"`legend'"'=="" { local legendorder `legendorder' off } } } else local legendorder off if `n_subgr'>1 { local byopt `by', note("") if (`N_plots'==1 & `"`bylegend'"'=="") | `"`legendorder'"'=="off" { local byopt `byopt' legend(off) } local byopt by(`byopt' `bylegend' `byopts') } else local byopt if `"`plots'"'=="" { di as txt "(nothing to plot)" exit } if `"`addplot'"'!="" { if `"`addplotbelow'"'!="" { local plots `addplot' || `plots' || } else { local plots `plots' || `addplot' || } } local plots two `plots', `axisalt' `groupsopts' `eqaxisopts' /// `xlabel' `hlblsopts' `xtick' `xrange' `reverse' yti("") xti("") /// legend(`legendlbls' `legendorder') `legend' `plotregion' `byopt' `twopts' `plots' // return if `"`generate'"'!="" { restore, not di as txt _n "Generated variables:" _c describe `returnvars' } return local graph `plots' return local labels `"`xlabels'"' return local eqlabels `"`eqlabels'"' return local groups `"`groups'"' return local headings `"`hlbls'"' return local legend `"`legendlbls' `legendorder'"' return scalar n_plots = `N_plots' return scalar n_subgr = `n_subgr' return scalar n_ci = `N_ci' end program parse_subgraphs // input: "subgr || subgr ..., opts" local i 0 local empty 1 while (`"`macval(0)'"'!="") { gettoken subgraph 0 : 0, parse("|") bind if `"`macval(subgraph)'"'=="|" { gettoken subgraph 0 : 0, parse("|") bind if `"`macval(subgraph)'"'!="|" error 198 // require "||" if `empty' { local ++i c_local subgr_`i' "." // use active model } else local empty 1 continue } if `"`0'"'=="" { // get opts if last _parse comma subgraph opts : subgraph } if `"`macval(subgraph)'"'!="" { // skip last if empty local empty 0 local ++i c_local subgr_`i' `"`macval(subgraph)'"' } } if `i'==0 { // check if empty local i 1 c_local subgr_1 "." // use active model } c_local n_subgr `i' c_local opts `macval(opts)' end program parse_globalopts syntax [, /// /// globalopts HORizontal /// VERTical /// sort SORT2(str) /// orderby(str) /// order(str asis) /// BYCoefs /// noRECycle /// grid(str) /// noOFFsets /// format(str) /// noLABels /// COEFLabels(str asis) /// NOEQLABels /// EQLabels(str asis) /// eqstrict /// HEADings(str asis) /// GROUPs(str asis) /// PLOTLabels(str asis) /// bylabels(str asis) /// GENerate GENerate2(name) /// RELOCate(str asis) /// replace /// addplot(str asis) /// NODROP /// LEGend(passthru) /// BYOPts(str asis) /// Bname(passthru) /// so that b() is not b1title() rename(passthru) /// EQREName(passthru) /// PCYCle(int 15) /// /// twoway options not captured by _get_gropts, gettwoway play(passthru) /// XOVERHANGs /// YOVERHANGs /// fxsize(passthru) /// fysize(passthru) /// * /// ] _get_gropts, graphopts(`options') gettwoway local twopts `s(twowayopts)' `play' `xoverhangs' `yoverhangs' `fxsize' `fysize' local opts0 `bname' `macval(rename)' `macval(eqrename)' `s(graphopts)' if `"`sort'`sort2'"'!="" { parse_sort `sort2' // returns local sort } if `"`orderby'"'!="" { parse_orderby `orderby', `recycle' // returns local orderby } if `"`generate'"'!="" & `"`generate2'"'=="" { local generate "__" } else local generate `"`generate2'"' if `"`grid'"'!="" { parse_grid, `grid' // returns local grid, gridopts } if `"`coeflabels'"'!="" { parse_coeflabels `coeflabels' // returns coeflabels, cltrunc, clwrap, clbreak, clinteract, clangle, clopts } if `"`clinteract'"'=="" { local clinteract `"" # ""' } parse_eqlabels "`noeqlabels'" `eqlabels' // returns eqlabels, eqashead, eqxlab // if eqashead=="": also eqgap, eqwrap, eqtrunc, eqbreak, eqopts // if eqashead!="": also hoff, hgap, hwrap, htrunc, hbreak, hopts if `"`headings'"'!="" { if `"`eqashead'"'!="" { di as err "eqlabels(, asheadings) and headings() not both allowed" exit 198 } parse_headings `headings' // returns headings, hoff, hgap, hopts } else if `"`hgap'"'=="" local hgap 0 if `"`eqashead'"'!="" { if "`bycoefs'"!="" { di as err "eqlabels(, asheadings) and bycoefs not both allowed" exit 198 } } if `"`groups'"'!="" { parse_groups `groups' // returns groups, ggap, gwrap, gtrunc, gbreak, gopts } else local ggap 0 if `"`plotlabels'"'!="" { parse_plotlabels `plotlabels' // returns plotlabels, plwrap, pltrunc, plbreak } if `"`bylabels'"'!="" { parse_bylabels `bylabels' // returns bylabels, blwrap, bltrunc, blbreak } if `"`format'"'!="" { confirm numeric format `format' } if `"`horizontal'"'!="" { if `"`vertical'"'!="" { di as err "horizontal and vertical not both allowed" exit 198 } } if `"`addplot'"'!="" { parse_addplot `addplot' // returns addplot, addplotbelow } parse_byopts, `byopts' // returns bylegend, byopts foreach opt in /// horizontal /// vertical /// sort /// orderby /// order /// bycoefs /// recycle /// grid gridopts /// offsets /// format /// labels /// coeflabels cltrunc clwrap clbreak clinteract clangle clopts /// noeqlabels /// eqlabels eqashead eqxlab eqgap eqtrunc eqwrap eqbreak eqopts /// eqstrict /// headings hxlab hoff hgap htrunc hwrap hbreak hopts /// groups ggap gtrunc gwrap gbreak gopts /// plotlabels plwrap pltrunc plbreak /// bylabels blwrap bltrunc blbreak /// relocate /// generate /// replace /// addplot addplotbelow /// nodrop /// legend /// bylegend /// byopts /// { c_local `opt' `"``opt''"' } c_local pcycle `pcycle' c_local twopts `twopts' merge_subgropts, `macval(opts0)' c_local subgropts0 `subgropts' c_local plotopts0 `plotopts1' c_local modelopts0 `macval(modelopts1)' c_local twplotopts0 `twplotopts1' end program parse_sort syntax [anything] [, Descending by(str) ] if `"`anything'"'=="" { local subgr . local plot . } else { gettoken subgr rest : anything, parse(":") if `"`rest'"'=="" { // sort(#) local plot `"`subgr'"' local subgr . } else if `"`subgr'"'==":" { // sort(:#) local subgr . gettoken plot rest : rest } else { // sort(#:#) gettoken colon rest : rest, parse(":") if `"`colon'"'!=":" { di as err "sort(): invalid syntax" exit 198 } gettoken plot rest : rest } if `"`rest'"'!="" { di as err "sort(): invalid syntax" exit 198 } foreach t in subgr plot { if `"``t''"'=="" local `t' . else if `"``t''"'!="." { capt confirm integer number ``t'' if _rc==0 { local rc = (``t''<=0) } else local rc 1 if `rc' { di as err "sort(): invalid syntax" exit 198 } } } } capt parse_sort_by, `by' if _rc { di as err `"sort(): '`by'' not allowed in by()"' exit 198 } local descending = ("`descending'"!="") c_local sort `"`subgr' `plot' `descending' "`by'""' end program parse_sort_by syntax [, b v se t tabs df p ll ul aux * ] local by `b' `v' `se' `t' `tabs' `df' `p' `ll' `ul' `aux' if `: list sizeof by'>1 exit 198 if inlist("`by'","ll", "ul", "aux") { // by(ll/ul/aux #) if `"`options'"'=="" local by `by' 1 else { capt confirm integer number `options' if _rc==0 { local rc = (`options'<=0) } else local rc 1 if `rc' exit 198 local by `by' `options' } } else if `"`options'"'!="" exit 198 if `"`by'"'=="" local by b c_local by `by' end program parse_orderby syntax [anything] [, norecycle ] gettoken subgr rest : anything, parse(":") if `"`rest'"'=="" { // orderby(#) local plot `"`subgr'"' local subgr 1 } else if `"`subgr'"'==":" { // ordeby(:#) local subgr 1 gettoken plot rest : rest } else { // orderby(#:#) gettoken colon rest : rest, parse(":") if `"`colon'"'!=":" { di as err "orderby(): invalid syntax" exit 198 } if "`recycle'"!="" { di as err "orderby(): subgraph not allowed with norecycle" exit 198 } gettoken plot rest : rest } if `"`rest'"'!="" { di as err "orderby(): invalid syntax" exit 198 } foreach t in subgr plot { if `"``t''"'=="" local `t' 1 else { capt confirm integer number ``t'' if _rc==0 { local rc = (``t''<=0) } else local rc 1 if `rc' { di as err "orderby(): invalid syntax" exit 198 } } } if "`recycle'"!="" local subgr . c_local orderby `subgr' `plot' end program parse_grid syntax [, Between Within None * ] if ("`between'"!="") + ("`within'"!="") + ("`none'"!="") > 1 { di as err "grid(): only one of between, within, and none allowed" exit 198 } c_local grid `between' `within' `none' c_local gridopts `options' end program parse_coeflabels mata: coefplot_parsecomma("coeflabels", "0", "0") syntax [, Truncate(numlist integer max=1 >0) /// Wrap(numlist integer max=1 >0) noBreak /// Interaction(str asis) angle(passthru) * ] c_local coeflabels `"`coeflabels'"' c_local cltrunc `truncate' c_local clwrap `wrap' c_local clbreak `break' c_local clinteract `"`interaction'"' c_local clangle `angle' c_local clopts `options' end program parse_eqlabels gettoken noeqlabels 0 : 0 mata: st_local("0", strltrim(st_local("0"))) mata: coefplot_parsecomma("eqlabels", "0", "0") syntax [, LABels LABels2(str asis) /// OFFset(real 0) ASHEADings noGap Gap2(numlist max=1) /// Truncate(numlist integer max=1 >0) /// Wrap(numlist integer max=1 >0) noBreak * ] if "`labels'"!="" & `"`labels2'"'=="" { local labels2 `"" # ""' } if "`gap'"!="" local gap2 0 else if "`gap2'"=="" { if "`noeqlabels'"!="" local gap2 0 else local gap2 1 } if "`asheadings'"!="" { c_local hoff `offset' c_local hgap `gap2' c_local htrunc `truncate' c_local hwrap `wrap' c_local hbreak `break' c_local hopts `options' c_local eqgap 0 } else { if `offset'!=0 { di as err "eqlabels(): offset() only allowed with asheadings" exit 198 } c_local eqgap `gap2' c_local eqtrunc `truncate' c_local eqwrap `wrap' c_local eqbreak `break' c_local eqopts `options' } c_local eqxlab `"`labels2'"' c_local eqlabels `"`eqlabels'"' c_local eqashead `asheadings' end program parse_headings mata: coefplot_parsecomma("headings", "0", "0") syntax [, OFFset(real 0) noGap Gap2(real 1) /// Truncate(numlist integer max=1 >0) /// Wrap(numlist integer max=1 >0) noBreak * ] if "`gap'"!="" local gap2 0 c_local headings `"`headings'"' c_local hoff `offset' c_local hgap `gap2' c_local htrunc `truncate' c_local hwrap `wrap' c_local hbreak `break' c_local hopts `options' end program parse_groups mata: coefplot_parsecomma("groups", "0", "0") syntax [, noGap Gap2(real 1) /// Truncate(numlist integer max=1 >0) /// Wrap(numlist integer max=1 >0) noBreak * ] if "`gap'"!="" local gap2 0 c_local groups `"`groups'"' c_local ggap `gap2' c_local gtrunc `truncate' c_local gwrap `wrap' c_local gbreak `break' c_local gopts `options' end program parse_plotlabels mata: coefplot_parsecomma("plotlabels", "0", "0") syntax [, Truncate(numlist integer max=1 >0) /// Wrap(numlist integer max=1 >0) noBreak ] c_local plotlabels `"`plotlabels'"' c_local pltrunc `truncate' c_local plwrap `wrap' c_local plbreak `break' end program parse_bylabels mata: coefplot_parsecomma("bylabels", "0", "0") syntax [, Truncate(numlist integer max=1 >0) /// Wrap(numlist integer max=1 >0) noBreak ] c_local bylabels `"`bylabels'"' c_local bltrunc `truncate' c_local blwrap `wrap' c_local blbreak `break' end program parse_addplot _parse expand addplot addplotopts : 0 , /// common(below by() nodraw draw name() SAVing() play()) forv i=1/`addplot_n' { local addplot `addplot' (`addplot_`i'') } local addplot `addplot' `addplotopts_if' `addplotopts_in' _parse combop addplotopts_op : addplotopts_op, option(below) opsin rightmost parse_addplotopts, `addplotopts_op' // returns below, options if `"`options'"'!="" { local addplot `addplot', `options' } c_local addplot `addplot' c_local addplotbelow `below' end program parse_addplotopts syntax [, below by(passthru) NODRAW draw name(passthru) /// SAVing(passthru) play(passthru) * ] foreach opt in nodraw draw { if `"``opt''"'!="" { di as err "`opt' not allowed within addplot()" exit 198 } } foreach opt in by name saving play { if `"``opt''"'!="" { di as err "`opt'() not allowed within addplot()" exit 198 } } local options: subinstr local options "below" "", all word // to be sure c_local below `below' c_local options `options' end program parse_byopts syntax [, LEGend(passthru) * ] c_local bylegend `legend' c_local byopts `options' end program merge_subgropts merge_plotopts `macval(0)' // returns modelopts2, plotopts, options, _opts0 _merge_subgropts, `options' _merge_subgropts _opt0_, `_opts0' if `"`_opt0_options'"'!="" error 198 if `"`bylabel'"'!="" { c_local subgropts `bylabel' } else { c_local subgropts `_opt0_bylabel' } c_local modelopts1 `macval(modelopts2)' c_local plotopts1 `plotopts' c_local twplotopts1 `options' end program _merge_subgropts syntax [anything] [, BYLABel(passthru) * ] c_local `anything'bylabel `bylabel' c_local `anything'options `options' end program parse_subgropts syntax anything [, BYLABel(str asis) ] gettoken lbl rest : bylabel, qed(qed) // remove outer quotes if `"`lbl'"'!="" & `"`rest'"'=="" & `qed' { local bylabel `"`lbl'"' } mata: coefplot_add_label(COEFPLOT_STRUCT, "by", `anything', "bylabel", 0) end program parse_plots // input: "j (plot) (plot) ..., opts" gettoken j 0 : 0 _parse comma 0 opts : 0 // get opts gettoken comma opts : opts, parse(",") // strip comma local i 0 while (`"`macval(0)'"'!="") { gettoken plot 0: 0, match(hasparen) local estexpand 0 // expand wildcards? if `"`hasparen'"'=="" { // - not if "(...)" if strpos(`"`plot'"',"(")==0 { // - not it "mat(...)" if strpos(`"`plot'"',"*") | strpos(`"`plot'"',"?") { local estexpand 1 } } } if `estexpand' { qui estimates dir `plot' foreach plot in `r(names)' { local ++i c_local plot_`j'_`i' `"`macval(plot)'"' } } else { local ++i c_local plot_`j'_`i' `"`macval(plot)'"' } } if `i'==0 { // check if empty local i 1 c_local plot_`j'_1 "." // use active model } c_local n_plots_`j' `i' c_local opts `macval(opts)' end program parse_get_popt_i gettoken i 0 : 0, parse(",") syntax [, p`i'(str asis) * ] c_local plotopts `macval(p`i')' c_local twplotopts0 `macval(options)' end program combine_plotopts syntax [, _opts0(str asis) * ] _merge_plotopts, `macval(options)' _merge_plotopts _opt0_, `macval(_opts0)' if `"`mlabels'"'!="" local _opt0_mlabel if `"`mlabel'"'!="" local _opt0_mlabels if `"`cismooths'"'!="" local _opt0_cismooth if `"`cismooth'"'!="" local _opt0_cismooths if `"`nokey'`key'`key2'"'!="" { local _opt0_nokey local _opt0_key local _opt0_key2 } local 0 foreach opt of local opts { // opts is set by _merge_plotopts if `"``opt''"'!="" { local 0 `0' ``opt'' } else { local 0 `0' `_opt0_`opt'' } } c_local plotopts `0' c_local options `macval(options)' end program merge_plotopts merge_modelopts `macval(0)' // returns modelopts, mlabels2, options, _opts0 _merge_plotopts, `options' _merge_plotopts _opt0_, `_opts0' if `"`mlabels'"'!="" local _opt0_mlabel if `"`mlabel'"'!="" local _opt0_mlabels if `"`mlabels'`mlabel'"'!="" local mlabels2 if `"`cismooths'"'!="" local _opt0_cismooth if `"`cismooth'"'!="" local _opt0_cismooths if `"`nokey'`key'`key2'"'!="" { local _opt0_nokey local _opt0_key local _opt0_key2 } local 0 foreach opt of local opts { // opts is set by _merge_plotopts if `"``opt''"'!="" { local 0 `0' ``opt'' } else { local 0 `0' `_opt0_`opt'' } } c_local modelopts2 `macval(modelopts)' `mlabels2' c_local plotopts `0' c_local options `options' c_local _opts0 `_opt0_options' end program _merge_plotopts syntax [anything] [, /// LABel(passthru) /// offset(passthru) /// PSTYle(passthru) /// AXis(passthru) /// recast(passthru) /// MLabels MLabel(passthru) /// MLABVposition(passthru) /// cionly /// citop /// CISmooths CISmooth(passthru) /// CIOPts(passthru) /// CIREcast(passthru) /// IFopt(passthru) /// Weightopt(passthru) /// NOKEY key KEY2(passthru) /// * ] if `"`mlabel'"'!="" local mlabels if `"`cismooth'"'!="" local cismooths local opts /// label /// offset /// pstyle /// axis /// recast /// mlabels mlabel /// mlabvposition /// cionly /// citop /// cismooths cismooth /// ciopts /// cirecast /// ifopt /// weightopt /// nokey key key2 foreach opt of local opts { c_local `anything'`opt' ``opt'' } c_local `anything'options `options' c_local opts `opts' end program parse_plotopts syntax anything [, /// LABel(str asis) /// offset(str asis) /// PSTYle(passthru) /// AXis(numlist integer max=1 >0 <10) /// recast(str) /// MLabels MLabel(passthru) /// MLABVposition(passthru) /// cionly /// citop /// CISmooths CISmooth(str asis) /// CIOPts(str asis) /// CIREcast(str) /// IFopt(str asis) /// Weightopt(str asis) /// NOKEY key KEY2(str) /// ] if `"`label'"'!="" { gettoken lbl rest : label, qed(qed) // remove outer quotes if `"`lbl'"'!="" & `"`rest'"'=="" & `qed' { local label `"`lbl'"' } mata: coefplot_add_label(COEFPLOT_STRUCT, "plot", `anything', "label", 1) } if `"`mlabels'"'!="" local mlabel mlabel(@b) if `"`cismooths'"'!="" local cismooth cismooth if `"`cirecast'"'!="" local cirecast recast(`cirecast') if `"`offset'"'!="" { capt parse_offset `offset' if _rc { di as err `"invalid offset(): `offset'"' exit 198 } } if `"`ifopt'"'!="" local ifopt `" & (`ifopt')"' if `"`weightopt'"'!="" local weightopt `" [aw=`weightopt']"' local key0 0 // default if `"`nokey'"'!="" local key0 -1 // suppress key if `"`key'`key2'"'!="" { if `key0'<0 { di as err "nokey and key() not both allowed" exit 198 } if `"`key2'"'!="" { gettoken key2ci key2 : key2 if `"`key2ci'"'!="ci" { di as err "invalid syntax in key()" exit 198 } if `"`key2'"'!="" { capt confirm integer number `key2' if _rc==0 { capt assert (`key2'>0) } if _rc { di as err "invalid syntax in key()" exit 198 } } else local key2 1 local key0 `key2' } } local key `key0' foreach opt in /// offset /// pstyle /// axis /// recast /// mlabel /// mlabvposition /// cionly /// citop /// cismooth /// ciopts /// cirecast /// ifopt /// weightopt /// key /// { c_local `opt'_`anything' `"``opt''"' } end program parse_offset local offset = `0' local 0 `", offset(`offset')"' syntax [, offset(numlist max=1) ] c_local offset `offset' end program parse_models // input: "j k model \ model ..., opts" gettoken j 0 : 0 gettoken k 0 : 0 local i 0 local empty 1 while (`"`macval(0)'"'!="") { gettoken model 0 : 0, parse("\") bind if `"`macval(model)'"'=="\" { if `empty' { local ++i c_local model_`j'_`k'_`i' "." // use active model } else local empty 1 continue } _parse comma model opts : model if `"`macval(0)'"'=="" { // get plotopts if last gettoken comma plotopts : opts, parse(",") // strip comma local opts } if `"`model'`macval(opts)'"'!="" { // skip last if empty local empty 0 if strpos(`"`model'"',"(") { // mat(...) local ++i c_local model_`j'_`k'_`i' `"`model'`macval(opts)'"' } else { if `"`model'"'=="" local model . foreach ename of local model { if strpos(`"`ename'"',"*") | strpos(`"`ename'"',"?") { qui estimates dir `ename' local ename `"`r(names)'"' } foreach mm of local ename { local ++i c_local model_`j'_`k'_`i' `"`mm'`macval(opts)'"' } } } } } if `i'==0 { // check if empty local i 1 c_local model_`j'_`k'_1 "." // use active model } c_local n_models_`j'_`k' `i' c_local opts `macval(plotopts)' end program parse_model // input: "name, opts" or "matrix(name[...]), opts" _parse comma 0 opts : 0 gettoken comma opts : opts, parse(",") // strip comma capt parse_model_matrix, `0' // returns model, matrix if _rc { gettoken model rest : 0 if `"`rest'"'!="" { di as err `"`rest' not allowed"' exit 198 } if `"`model'"'=="" local model . } c_local model `"`model'"' c_local matrix `"`matrix'"' c_local opts `macval(opts)' end program parse_model_matrix syntax, Matrix(str) gettoken model : matrix, parse(" [") if `"`model'"'=="" error 198 c_local model `"`model'"' c_local matrix `"`matrix'"' end program merge_modelopts syntax [, _opts0(str asis) * ] _merge_modelopts, `macval(options)' _merge_modelopts _opt0_, `macval(_opts0)' if `"`sename'"'!="" local _opt0_vname if `"`vname'"'!="" local _opt0_sename if `"`asequation'"'!="" local _opt0_asequation2 local 0 foreach opt of local opts { // opts is set by _merge_modelopts if `"``opt''"'!="" { if "`opt'"=="mlabels2" { c_local mlabels2 ``opt'' } else { local 0 `macval(0)' `macval(`opt')' } } else { if "`opt'"=="mlabels2" { c_local mlabels2 `_opt0_`opt'' } else { local 0 `macval(0)' `macval(_opt0_`opt')' } } } c_local modelopts `macval(0)' c_local options `options' c_local _opts0 `_opt0_options' end program _merge_modelopts syntax [anything] [, /// OMITted /// BASElevels /// Bname(passthru) /// ATname ATname2(passthru) /// SWAPnames /// keep(passthru) /// drop(passthru) /// rename(passthru) /// EQREName(passthru) /// ASEQuation ASEQuation2(passthru) /// eform EFORM2(passthru) /// rescale(passthru) /// TRANSform(passthru) /// MLABELS2(passthru) /// noci /// Levels(passthru) /// CIname(passthru) /// Vname(passthru) /// SEname(passthru) /// DFname(passthru) /// citype(passthru) /// aux(passthru) /// * ] if "`atname'"!="" & `"`atname2'"'=="" local atname2 "atname2(at)" if `"`asequation2'"'!="" local asequation if "`eform'"!="" & `"`eform2'"'=="" local eform2 "eform2(*)" if `"`sename'"'!="" & `"`vname'"'!="" { di as err "se() and v() not both allowed" exit 198 } local opts /// omitted /// baselevels /// bname /// atname2 /// swapnames /// keep /// drop /// rename /// eqrename /// asequation /// asequation2 /// eform2 /// rescale /// transform /// mlabels2 /// ci /// levels /// ciname /// vname /// sename /// dfname /// citype /// aux foreach opt of local opts { c_local `anything'`opt' `macval(`opt')' } c_local `anything'options `options' c_local opts `opts' end program collect_coefs gettoken model 0 : 0 gettoken matrix 0 : 0 // matrix mode? gettoken atmode 0 : 0 // whether at() is used gettoken i 0 : 0 // plot number gettoken j 0 : 0 // subgraph number gettoken cis 0 : 0 // cismooth levels // get options merge_modelopts `macval(0)' // returns modelopts, mlabels2, options, _opts0 local 0 , `macval(modelopts)' `mlabels2' `options' `_opts0' syntax [, /// OMITted /// BASElevels /// Bname(str) /// ATname2(str) /// SWAPnames /// keep(str asis) /// drop(str asis) /// rename(str asis) /// EQREName(str asis) /// ASEQuation ASEQuation2(str) /// EFORM2(str asis) /// rescale(str asis) /// TRANSform(str asis) /// MLABELS2(str asis) /// noci /// Levels(numlist) /// CIname(str asis) /// Vname(str) /// SEname(str) /// DFname(str) /// citype(str) /// aux(str) /// ] if `"`atname2'"'!="" { if "`atmode'"=="0" { di as err "must specify at for all or none" exit 198 } local atmode 1 parse_at_transform `atname2' // replaces atname2, returns attransform capt parse_at_is_matrix, `atname2' // syntax at(matrix(...)) } else { if "`atmode'"=="1" { di as err "must specify at for all or none" exit 198 } local atmode 0 } if `"`macval(rename)'"'!="" { parse_rename `macval(rename)' } if `"`macval(eqrename)'"'!="" { parse_eqrename `macval(eqrename)' } if "`cis'"!="" local ci // disable noci parse_cilevels `"`levels'"' `"`ciname'"' "`cis'" // returns levels, ciname parse_citype, `citype' // replaces citype if `"`matrix'"'!="" local bname `"`matrix'"' if "`asequation'"!="" & `"`asequation2'"'=="" { if "`model'"=="." local asequation2 "_" else local asequation2 `"`model'"' } if `"`aux'"'!="" { parse_aux `aux' // returns aux } // collect results local empty 0 local equation mata: coefplot_keepdrop(COEFPLOT_STRUCT) // returns empty, n_ci, equation if `empty' { local n_ci 0 di as txt /// `"(`model': no coefficients found, all dropped, or none kept)"' } // returns c_local equation `equation' c_local atmode `atmode' c_local n_ci `n_ci' if `"`mlabels2'"'!="" { c_local mlabel_`i' mlabel(@mlbl) c_local mlabvposition_`i' mlabvposition(@mlpos) } end program parse_at_transform syntax [anything] [, Transform(str) ] if `"`anything'"'=="" local anything at c_local atname2 `"`anything'"' c_local attransform `"`transform'"' end program parse_at_is_matrix syntax, Matrix(str) c_local atname2 `"`matrix'"' c_local atismatrix "matrix" end program parse_rename mata: coefplot_parsecomma("rename", "0", "0") syntax [, Regex] c_local `eq'rename `"`macval(rename)'"' c_local `eq'renameregex `regex' end program parse_eqrename mata: coefplot_parsecomma("rename", "0", "0") syntax [, Regex] c_local eqrename `"`macval(rename)'"' c_local eqrenameregex `regex' end program parse_aux // remove spaces in aux() gettoken s 0 : 0, bind while (`"`s'"'!="") { local s = subinstr(`"`s'"', " ", "", .) if substr(`"`s'"', 1, 1)=="[" { local aux `aux'`s' } else { local aux `aux' `s' } gettoken s 0 : 0, bind } c_local aux `"`aux'"' end program parse_citype local citypes logit probit atanh log syntax [, `citypes' NORMal ] local citype `logit' `probit' `atanh' `log' `normal' if `: list sizeof citype'>1 { di as err "citype(): only one of logit, probit, atanh, log, and normal allowed" exit 198 } local citype: list posof "`citype'" in citypes c_local citype `citype' end program parse_cilevels args levels names cis if "`cis'"!="" { foreach level of local cis { local ll `ll' `level' local nn `"`nn'`space'"""' local space " " } } while (1) { gettoken l levels : levels gettoken n names : names, match(paren) if `"`l'`n'"'=="" { continue, break } if `"`n'"'=="" { parse_cilevel, levels(`l') // returns level local ll `ll' `level' local nn `"`nn'`space'"""' } else { capt confirm number `n' if _rc { gettoken empty : n if `"`empty'"'=="" { // set default level parse_cilevel // returns level local ll `ll' `level' } else { local ll `ll' . } local nn `"`nn'`space'`"`n'"'"' } else { parse_cilevel, levels(`n') // returns level local ll `ll' `level' local nn `"`nn'`space'"""' } } local space " " } if `"`ll'"'=="" { // set default level parse_cilevel // returns level local ll `level' local nn `""""' } c_local levels `ll' c_local ciname `"`nn'"' end program parse_cilevel syntax [, level(cilevel) levels(numlist min=1 max=1 >0 <100) ] if `"`levels'"'=="" { c_local level `level' } else { c_local level `levels' } end program parse_cismooth syntax anything(name=j) [, Color(str) PSTYle(passthru) n(int 50) /// Intensity(numlist min=2 max=2 >=0 <=100) /// LWidth(numlist min=2 max=2 >=0 <=1000) ] if `n'<4 { di as err "cismooth(n()) must be >= 4" exit 198 } if "`intensity'"!="" { gettoken imin imax : intensity } else { local imin = (1+3) / (ceil(`n'/2)+3) * 100 local imax 100 } if "`lwidth'"!="" { gettoken wmin wmax : lwidth local lwidth } else { local wmin 2 local wmax 15 } local d = 100/`n' local lmax = 100 - `d'/2 forv i = 1/`n' { if mod(`i',2)==0 { local l = `d'/2 + (`i'/2-1)*`d' } else { local l = `d'/2 + (`n'-`i'/2-.5)*`d' } local levels `levels' `=string(`l')' local inten = (`imin' + (`imax'-`imin') / (ceil(`n'/2)-1) * /// (ceil(`i'/2)-1))/100 local intens `intens' `=string(`inten')' local lw = 4 + (`l'-1)/(`lmax'-1) * (100-4) // if n=50 max lw is 25 local lw = 100 / `lw' local lw = `wmin' + (`lw'-1) / (25-1) * (`wmax'-`wmin') local lwidth `lwidth' `=string(`lw')' } c_local cis_levels_`j' `levels' c_local cis_n_`j' `n' c_local cis_intens_`j' `intens' c_local cis_lwidth_`j' `lwidth' c_local cis_color_`j' `"`color'"' c_local cis_pstyle_`j' `"`pstyle'"' end program get_pstyle_id syntax anything(name=i) [, PSTYle(str) ] if `"`pstyle'"'=="" { local id `i' } else { local id = substr(`"`pstyle'"', 2, 2) // p##... capt confirm number `id' if _rc { local id = substr(`"`pstyle'"', 2, 1) // p#... capt confirm number `id' } if _rc { // invalid pstyle local id `i' } } c_local pstyle_id `id' end program parse_ciopts_nocilwincr syntax anything(name=i) [, recast(str) LWidth(str) * ] if `"`recast'`lwidth'"'!="" { c_local nocilwincr_`i' 1 } end program parse_ciopts_recast_pstyle syntax [, recast(str) PSTYle(str) * ] if `"`pstyle'"'!="" { local options `options' pstyle(`pstyle') } c_local cirecast `"`recast'"' c_local cipstyle `"`pstyle'"' c_local ciopts `options' end program set_pstyle args i recast if `"`recast'"'=="" { c_local pstyle pstyle(p`i') exit } if inlist(`"`recast'"', "line", "rline") /// c_local pstyle pstyle(p`i'line) else if inlist(`"`recast'"', "area", "rarea") /// c_local pstyle pstyle(p`i'area) else if inlist(`"`recast'"', "bar", "rbar") /// c_local pstyle pstyle(p`i'bar) else if inlist(`"`recast'"', "dot") /// c_local pstyle pstyle(p`i'dot) else c_local pstyle pstyle(p`i') end program parse_ciopts gettoken j 0 : 0 gettoken n 0 : 0 gettoken opt 0 : 0, bind local opts while (`"`opt'"'!="") { // get rid of possible spaces between opt and () gettoken paren: opt, parse("(") if `"`paren'"'=="(" { local opts `opts'`opt' } else { local opts `opts' `opt' } gettoken opt 0 : 0, bind } local ciopts `", `opts'"' gettoken opt opts : opts, bind local i 0 while (`"`opt'"'!="") { local ++i gettoken optname optcontents : opt, parse("(") if `"`optcontents'"'=="" { gettoken opt opts : opts, bind continue } _parse factor ciopts : ciopts, option(`optname') to(`optname'(X)) gettoken opt opts : opts, bind } _parse factordot ciopts : ciopts, n(`n') // _parse combine only works up to p20 gettoken opt ciopts : ciopts // get rid of comma gettoken opt ciopts : ciopts, bind // get first opt while (`"`opt'"'!="") { mata: coefplot_combine_ciopts() // appends opt_# or options gettoken opt ciopts : ciopts, bind // get next opt } forv i=1/`n' { c_local ciopts_`j'_`i' `opt_`i'' `options' } end program parse_mlabel_exp syntax [ , MLabel(str asis) ] c_local mlblexp `"`mlabel'"' end program coeflbls args labels interact mata: coefplot_get_coefs(COEFPLOT_STRUCT) local i 0 foreach v of local coefs { local ++i if (`"`v'"'=="") continue // gap from order() if (`"`v'"'==`"`last'"') { mata: coefplot_add_label(COEFPLOT_STRUCT, "coef", `i', "coeflbl", 1) continue } mata: coefplot_get_coeflbl(COEFPLOT_STRUCT, `i') if `"`coeflbl'"'=="" { if `"`labels'"'!="" { local coeflbl `"`v'"' } else { compile_xlabel, v(`v') interact(`interact') // returns coeflbl } } mata: coefplot_add_label(COEFPLOT_STRUCT, "coef", `i', "coeflbl", 1) } end program compile_xlabel syntax [, v(str) interact(str) ] gettoken vi vrest: v, parse("#") while (`"`vi'"') !="" { local xlabi if `"`vi'"'=="#" { local xlabi `"`interact'"' } else if strpos(`"`vi'"',".")==0 { capt confirm variable `vi', exact if _rc==0 { local xlabi: var lab `vi' } if `"`xlabi'"'=="" { local xlabi `"`vi'"' } } else { gettoken li vii : vi, parse(".") gettoken dot vii : vii, parse(".") capt confirm variable `vii', exact if _rc==0 & `"`vii'"'!="" { capt confirm number `li' if _rc { local xlabi: var lab `vii' if (`"`xlabi'"'=="") local xlabi `"`vii'"' if (substr(`"`li'"',1,1)=="c") /// local li = substr(`"`li'"',2,.) if (`"`li'"'!="") local xlabi `"`li'.`xlabi'"' } else { local viilab : value label `vii' if `"`viilab'"'!="" { local xlabi: label `viilab' `li' } else { local viilab: var lab `vii' if (`"`viilab'"'=="") local viilab `"`vii'"' local xlabi `"`viilab'=`li'"' } } } if `"`xlabi'"'=="" { local xlabi `"`vi'"' } } local xlab `"`xlab'`xlabi'"' gettoken vi vrest: vrest, parse("#") } c_local coeflbl `"`xlab'"' end program set_by_and_plot_labels args plot by // plot capt label drop `plot' qui levelsof `plot', local(levels) foreach l of local levels { mata: coefplot_get_plotlbl(COEFPLOT_STRUCT, `l') // returns plotlbl lab def `plot' `l' `"`plotlbl'"', add } lab val `plot' `plot', nofix // by capt label drop `by' qui levelsof `by', local(levels) foreach l of local levels { mata: coefplot_get_bylbl(COEFPLOT_STRUCT, `l') // returns bylbl lab def `by' `l' `"`bylbl'"', add } lab val `by' `by', nofix end program get_axis_labels args x eq grp grid groups // eqlabels qui levelsof `eq', local(levels) local j 0 foreach l of local levels { local ++j su `x' if `eq'==`l', meanonly local pos = string(r(min) + (r(max)-r(min))/2) local pos: list retok pos mata: coefplot_get_eqlbl(COEFPLOT_STRUCT, `j') // returns eqlbl local eqlabels `eqlabels' `pos' `"`eqlbl'"' } c_local eqlabels `"`eqlabels'"' // groups if `"`groups'"'!="" { local j 0 foreach glab of local groups { local ++j foreach l of local levels { // equations (from above) su `x' if `grp'==`j' & `eq'==`l', mean if r(N)>0 { local pos = string(r(min) + (r(max)-r(min))/2) local pos: list retok pos local glbls `glbls' `pos' `"`glab'"' } } } c_local groups `glbls' } // ticks and xlabels mata: coefplot_ticks_and_labels(COEFPLOT_STRUCT) c_local xrange `xrange' c_local xlabels `xlabels' c_local xgrid `xgrid' end program merge_eqlabels_hlbls args eqlab hlab gettoken lab eqlab : eqlab // skip value gettoken lab eqlab : eqlab, quotes while (`"`lab'"'!="") { gettoken val hlab : hlab local hlbls `"`hlbls'`val' `lab' "' gettoken lab eqlab : eqlab // skip value gettoken lab eqlab : eqlab, quotes } c_local hlbls `"`hlbls'"' c_local eqlabels "" end program truncwrap_vlabels args v n trunc wrap break forv i = 1/`n' { local lbl: label `v' `i' truncwrap_label lbl "`trunc'" "`wrap'" "`break'" `"`lbl'"' // may fail if label contains compound quotes lab def `v' `i' `"`lbl'"', modify } end program truncwrap_labels args local trunc wrap break lbls local labels local skip 1 foreach lbl of local lbls { if `skip' { local labels `labels' `lbl' local skip 0 continue } truncwrap_label lbl "`trunc'" "`wrap'" "`break'" `"`lbl'"' // may fail if label contains compound quotes local labels `labels' `"`lbl'"' local skip 1 } c_local `local' `"`labels'"' end program truncwrap_label args local trunc wrap break lbl capt mata: coefplot_lbl_is_multiline() // error if label is multiline if _rc exit if "`break'"!="" local break ", `break'" if "`trunc'"!="" { local lbl: piece 1 `trunc' of `"`lbl'"'`break' capt truncwrap_label_check_quotes `"`lbl'"' if _rc exit } if "`wrap'"!="" { local i 0 local space while (1) { local ++i local piece: piece `i' `wrap' of `"`lbl'"'`break' capt truncwrap_label_check_quotes `"`piece'"' if _rc exit if `"`piece'"'=="" { if `i'==1 { local newlbl `"`lbl'"' // lbl is empty } else if `i'==2 { // workaround for multiline label graph bug local newlbl `"`newlbl'`space'"""' } continue, break } local newlbl `"`newlbl'`space'`"`piece'"'"' local space " " } local lbl `"`newlbl'"' } c_local `local' `"`lbl'"' end program truncwrap_label_check_quotes // checks for unmatched compound quotes syntax [anything] end program set_labels args v n lbls local i 0 foreach lbl of local lbls { local ++i if `i'>`n' continue, break lab def `v' `i' `"`lbl'"', modify } end program reset_xlabels args lbls xlbls local labels local skip 1 foreach lbl of local xlbls { if `skip' { local labels `labels' `lbl' local skip 0 continue } if `"`lbls'"'!="" { gettoken lbl lbls : lbls } local labels `labels' `"`lbl'"' local skip 1 } c_local xlabels `"`labels'"' end version 11 mata: mata set matastrict on struct coefplot_struct { real scalar r, xmin real colvector b, V, se, t, df, pval, at, plot, by, eq, grp, mlpos real matrix ci, aux string colvector coefnm, eqnm, coeflbl, eqlbl, plotlbl, bylbl, mlbl, trans } struct coefplot_struct scalar coefplot_struct_init() { struct coefplot_struct scalar C return(C) } void coefplot_keepdrop(struct coefplot_struct scalar C) { real scalar i, j, level, r, brow, bcol, row, col, emode, firsteqonly, meqs, citype real colvector b, p, at, V, se, t, df, pval, mlpos real matrix ci, aux, tmp string scalar model, bname, cname, rename, attrans, attmp string rowvector keep, drop, cnames, levels, llul string colvector eqnm, coefnm, mlbl, trans // get results emode = (st_local("matrix")=="") // - coefficients model = st_local("model") bname = st_local("bname") if (bname=="") { if (st_global("e(mi)")=="mi") bname = "b_mi" else bname = "b" } coefplot_parse_input(model, "b", bname, brow, bcol) if (emode) bname = "e(" + bname + ")" b = st_matrix(bname) if (b==J(0,0,.)) { st_local("empty", "1") return } coefplot_invalid_subscript(model, bname, b, brow, bcol) b = b[brow, bcol] if (brow<.) { b = b' eqnm = st_matrixcolstripe(bname)[.,1] coefnm = st_matrixcolstripe(bname)[.,2] } else { eqnm = st_matrixrowstripe(bname)[.,1] coefnm = st_matrixrowstripe(bname)[.,2] } _editvalue(eqnm, "", "_") meqs = !allof(eqnm, eqnm[1]) r = rows(b) // - get variances and standard errors se = J(r,1,.) V = J(r,1,.) if ((cname = st_local("sename"))!="") { coefplot_parse_cname(model, "se", cname, row, col, emode, 0, bname, brow, bcol) tmp = st_matrix(cname) if (coefplot_notfound(model, cname, tmp)==0) { coefplot_invalid_subscript(model, cname, tmp, row, col) tmp = tmp[row, col] if (row<.) tmp = tmp' if (coefplot_notconformable(model, cname, tmp, r, 1)==0) { se = tmp V = tmp:^2 } } } else if ((cname = st_local("vname"))!="") { if (emode) cname = "e(" + cname + ")" tmp = st_matrix(cname) if (coefplot_notfound(model, cname, tmp)==0) { if (coefplot_notconformable(model, cname, tmp, r, r)==0) { V = diagonal(tmp) se = sqrt(V) } } } else if (emode){ if (st_global("e(mi)")=="mi") cname = "e(V_mi)" else cname = "e(V)" tmp = st_matrix(cname) if (coefplot_notfound(model, cname, tmp, 1)==0) { if (coefplot_notconformable(model, cname, tmp, r, r, 1)==0) { V = diagonal(tmp) se = sqrt(V) } } } // - get DFs df = J(r,1,.) if ((cname = st_local("dfname"))!="") { if (strtoreal(cname)<. | cname==".") { df = J(r, 1, strtoreal(cname)) } else { coefplot_parse_input(model, "df", cname, row, col) if (emode) cname = "e(" + cname + ")" tmp = st_matrix(cname) if (coefplot_notfound(model, cname, tmp)==0) { coefplot_invalid_subscript(model, cname, tmp, row, col) tmp = tmp[row, col] if (row<.) tmp = tmp' if (coefplot_notconformable(model, cname, tmp, r, 1)==0) { df = tmp } } } } else if (emode) { if ((st_global("e(mi)")=="mi") & (tmp=st_matrix("e(df_mi)")')!=J(0,0,.)) { if (coefplot_notconformable(model, "e(df_mi)", tmp, r, 1)==0) { df = tmp } } else if (st_numscalar("e(df_r)")!=J(0,0,.)) { df = J(r, 1, st_numscalar("e(df_r)")) } } // - CIs ci = J(r, 0, .) if (st_local("ci")=="") { cnames = tokens(st_local("ciname")) levels = tokens(st_local("levels")) citype = strtoreal(st_local("citype")) for (j=1; j<=cols(levels); j++) { ci = ci, J(r, 2, .) if ((cname = strtrim(cnames[j]))!="") { if (cols(tokens(cname))==1) { // "name" llul = (cname+"[1]", cname+"[2]") } else { if (strpos(cname, "[")==0) { // "ll ul" llul = tokens(cname) if (cols(llul)!=2) { printf("{txt}(%s: invalid syntax in %s)\n", model, "ci()") exit(error(198)) } } else { if (strpos(cname, "]")==strlen(cname)) { // "ll ul[]" llul = (substr(cname, 1, strpos(cname, " ")-1), substr(cname, strpos(cname, " ")+1, .)) } else { // "ll[] ul[]" llul = (substr(cname, 1, strpos(cname, "]")), substr(cname, strpos(cname, "]")+1, .)) } } } for (i=1; i<=2; i++) { cname = llul[i] coefplot_parse_cname(model, "ci", cname, row, col, emode, 0, bname, brow, bcol) tmp = st_matrix(cname) if (coefplot_notfound(model, cname, tmp)==0) { coefplot_invalid_subscript(model, cname, tmp, row, col) tmp = tmp[row, col] if (row<.) tmp = tmp' if (coefplot_notconformable(model, cname, tmp, r, 1)==0) { ci[,(j*2-2+i)] = tmp } } } } else { level = 1 - (1 - strtoreal(levels[j])/100)/2 tmp = J(r, 1, .) for (i=1; i<=r; i++) { tmp[i] = df[i]>2e17 ? invnormal(level) : invttail(df[i], 1-level) } if (citype==1) { // logit tmp = tmp :* se :/ (b:* (1 :- b)) ci[|1,(j*2-1) \ .,(j*2)|] = invlogit((logit(b) :- tmp, logit(b) :+ tmp)) } else if (citype==2) { // probit tmp = tmp :* se :/ normalden(invnormal(b)) ci[|1,(j*2-1) \ .,(j*2)|] = normal((invnormal(b) :- tmp, invnormal(b) :+ tmp)) } else if (citype==3) { // atanh tmp = tmp :* se :/ (1 :- b:^2) // missing if b in {-1,1} ci[|1,(j*2-1) \ .,(j*2)|] = tanh((atanh(b) :- tmp, atanh(b) :+ tmp)) } else if (citype==4) { // log tmp = tmp :* se :/ b ci[|1,(j*2-1) \ .,(j*2)|] = exp((ln(b) :- tmp, ln(b) :+ tmp)) } else { // normal ci[|1,(j*2-1) \ .,(j*2)|] = (b :- tmp:*se, b :+ tmp:*se) } } } } // - at at = J(r,1,1) cname = st_local("atname2") if ((cname!="") & (cname!="_coef") & (cname!="_eq")) { if ( emode & st_global("e(cmd)")=="margins" & (st_local("bname")=="" | st_local("bname")=="b") & (st_numscalar("e(k_at)")!=J(0,0,.) ? st_numscalar("e(k_at)")>0 : 0) & (cname=="at" | strtoreal(cname)<.) ) { if (cname=="at") cname = "1" at = coefplot_get_margins_at("e", strtoreal(cname), coefnm)' // (modifies coefnm) } else { coefplot_parse_cname(model, "at", cname, row, col, emode, st_local("atismatrix")!="", bname, brow, bcol) tmp = st_matrix(cname) if (coefplot_notfound(model, cname, tmp)==0) { coefplot_invalid_subscript(model, cname, tmp, row, col) tmp = tmp[row, col] if (row<.) tmp = tmp' if (coefplot_notconformable(model, cname, tmp, r, 1)==0) { at = tmp } } } } // - auxiliary variables cnames = tokens(st_local("aux")) // spaces in mspec not allowed aux = J(r, cols(cnames), .) for (j=1; j<=cols(cnames); j++) { cname = cnames[j] coefplot_parse_cname(model, "aux", cname, row, col, emode, 0, bname, brow, bcol) tmp = st_matrix(cname) if (coefplot_notfound(model, cname, tmp)==0) { coefplot_invalid_subscript(model, cname, tmp, row, col) tmp = tmp[row, col] if (row<.) tmp = tmp' if (coefplot_notconformable(model, cname, tmp, r, 1)==0) { aux[,j] = tmp } } } // keep, drop, etc. // - clear "bn" coefnm = subinstr(coefnm,"bn.", ".") // #bn. coefnm = subinstr(coefnm,"bno.", "o.") // #bno. // - remove omitted p = J(r, 1, 1) if (st_local("omitted")=="") { p = p :* (!strmatch(coefnm, "*o.*")) } else { coefnm = substr(coefnm, 1:+2*(substr(coefnm, 1, 2):=="o."), .) // o. coefnm = subinstr(coefnm, "o.", ".") // #o. } // - remove baselevels if (st_local("baselevels")=="") { p = p :* (!strmatch(coefnm, "*b.*")) } else { coefnm = subinstr(coefnm, "b.", ".") // #b. } // keep firsteqonly = 1 keep = st_local("keep") if (keep!="") { keep = coefplot_parse_namelist(keep, "", "keep") if (!allof(keep[,1], "")) firsteqonly = 0 keep[,1] = editvalue(keep[,1],"","*") p = p :* (rowsum(strmatch(eqnm, keep[,1]') :& strmatch(coefnm, keep[,2]')):>0) } // drop drop = st_local("drop") if (drop!="") { drop = coefplot_parse_namelist(drop, "", "drop") if (!allof(drop[,1], "")) firsteqonly = 0 drop[,1] = editvalue(drop[,1],"","*") p = p :* (!(rowsum(strmatch(eqnm, drop[,1]') :& strmatch(coefnm, drop[,2]')))) } // equation if (firsteqonly) { for (i=1; i<=r; i++) { // look for first nonzero equation if (p[i]==1) { p = p :* (eqnm:==eqnm[i]) break } } } // apply selection if (allof(p, 0)) { st_local("empty", "1") return } b = select(b, p) V = select(V, p) se = select(se, p) df = select(df, p) ci = select(ci, p) eqnm = select(eqnm, p) coefnm = select(coefnm, p) at = select(at, p) aux = select(aux, p) r = rows(b) // t and p values t = b:/se pval = J(r,1,.) for (i=1; i<=r; i++) { pval[i] = (df[i]>=. ? 1-normal(abs(t[i])) : ttail(df[i],abs(t[i])))*2 } // eform coefplot_eform(b, ci, eqnm, coefnm) // rescale coefplot_rescale(b, ci, eqnm, coefnm) // collect transforms trans = coefplot_collect_transforms(eqnm, coefnm) // collect mlabels mlbl = J(r,1,"") mlpos = J(r,1,.) coefplot_mlabels(mlbl, mlpos, eqnm, coefnm) // rename rename = st_local("rename") if (rename!="") { coefplot_rename(rename, st_local("renameregex")!="", eqnm, coefnm) // modifies coefnm } // rename equations and swap names if (st_local("asequation2")!="") { eqnm = J(r, 1, st_local("asequation2")) } rename = st_local("eqrename") if (rename!="") { coefplot_rename(rename, st_local("eqrenameregex")!="", J(r, 1, ""), eqnm) // modifies eqnm } // at is coef or eq if (st_local("atname2")=="_coef") { at = strtoreal(coefnm) } else if (st_local("atname2")=="_eq") { at = strtoreal(eqnm) } // apply at transform if ((attrans=st_local("attransform"))!="") { attmp = st_tempname() attrans = subinstr(attrans, "@", "scalar(" + attmp + ")") for (i=1; i<=r; i++) { st_numscalar(attmp, at[i]) stata("scalar " + attmp + " = " + attrans) at[i] = st_numscalar(attmp) } } // check missings coefplot_missing(model, b) for (j=1; j<=cols(levels); j++) { coefplot_cimissing(model, j, ci[|1,(j*2-1) \ .,(j*2)|]) } coefplot_atmissing(model, at) // return if (st_local("swapnames")!="") swap(coefnm, eqnm) st_local("n_ci", strofreal(cols(ci)/2)) if (cols(C.ci)>cols(ci)) { ci = ci, J(rows(ci), cols(C.ci)-cols(ci), .) } else if (cols(C.ci)cols(aux)) { aux = aux, J(rows(aux), cols(C.aux)-cols(aux), .) } else if (cols(C.aux)rows(b)) | (col<. & col>cols(b))) { printf("{err}%s: invalid subscript for %s\n", model, opt) exit(503) } } void coefplot_parse_input(string scalar model, string scalar opt, string scalar s, real scalar row, real scalar col) { transmorphic t string scalar r, c string rowvector tokens t = tokeninit(" ", ("[", "]", ",")) tokenset(t, s) tokens = tokengetall(t) if (cols(tokens)>6) coefplot_parse_input_error(model, opt) if (!st_isname(tokens[1])) coefplot_parse_input_error(model, opt) s = tokens[1] if (cols(tokens)==1) { // "name" row = 1; col = . return } if (cols(tokens)<4) coefplot_parse_input_error(model, opt) if (tokens[2]!="[" | tokens[cols(tokens)]!="]") coefplot_parse_input_error(model, opt) if (cols(tokens)==4) { // name[#] r = tokens[3] c = "." } else if ((r=tokens[3])==",") { // name[,#] if (cols(tokens)!=5) coefplot_parse_input_error(model, opt) r = "." c = tokens[4] } else { // name[#,] or name[#,.] or name[.,#] if (tokens[4]!=",") coefplot_parse_input_error(model, opt) r = tokens[3] if (cols(tokens)==5) c = "." else c = tokens[5] } if (((r==".") + (c=="."))!=1) coefplot_parse_input_error(model, opt) if (r==".") row = . else row = coefplot_parse_input_num(model,opt, r) if (c==".") col = . else col = coefplot_parse_input_num(model,opt, c) } real scalar coefplot_parse_input_num(string scalar model, string scalar opt, string scalar s) { real scalar num num = strtoreal(s) if (missing(num)) coefplot_parse_input_error(model, opt) return(num) } void coefplot_parse_input_error(string scalar model, string scalar opt) { printf("{err}%s: invalid syntax in %s()\n", model, opt) exit(198) } void coefplot_parse_cname(string scalar model, string scalar opt, string scalar cname, real scalar row, real scalar col, real scalar emode, real scalar atismat, string scalar bname, real scalar brow, real scalar bcol) { if (emode) { coefplot_parse_input(model, opt, cname, row, col) if (!atismat) cname = "e(" + cname + ")" } else { if (coefplot_parse_input_isposint(cname)) { row = brow; col = bcol if (row<.) row = strtoreal(cname) else col = strtoreal(cname) cname = bname } else coefplot_parse_input(model, opt, cname, row, col) } } real scalar coefplot_parse_input_isposint(string scalar cname) { real scalar n n = strtoreal(cname) return(!missing(n) & n==trunc(n) & n>0) } real scalar coefplot_notfound( string scalar model, string scalar name, real matrix e, | real scalar q) { if (e==J(0,0,.)) { if (args()<4 | q==0) { printf("{txt}(%s: %s not found)\n", model, name) } return(1) } return(0) } real scalar coefplot_notconformable( string scalar model, string scalar name, real matrix e, real scalar r, real scalar c, | real scalar q) { if (rows(e)!=r | cols(e)!=c) { if (args()<6 |q==0) { printf("{txt}(%s: %s not conformable)\n", model, name) } return(1) } return(0) } void coefplot_eform(real colvector b, real matrix ci, string colvector eq, string colvector coef) { real scalar i string matrix eform real colvector match, p eform = st_local("eform2") if (eform=="") { return } if (eform=="*") { b = exp(b) ci = exp(ci) return } eform = coefplot_parse_namelist(eform, "*", "eform") match = J(rows(b), 1, 0) for (i=1; i<=rows(eform); i++) { p = select(1::rows(match), strmatch(eq, eform[i,1]) :& strmatch(coef, eform[i,2])) if (rows(p)==0) continue match[p] = J(rows(p), 1, 1) } p = select(1::rows(match), match) if (rows(p)==0) return b[p] = exp(b[p]) ci[p,] = exp(ci[p,.]) } void coefplot_rescale(real colvector b, real matrix ci, string colvector eq, string colvector coef) { real scalar i, j string matrix rescale, names real colvector c, match, p rescale = st_local("rescale") if (rescale=="") { return } if (strtoreal(rescale)<.) { c = strtoreal(rescale) } else { rescale = coefplot_parse_matchlist(rescale, "rescale") c = J(rows(b), 1, 1) match = J(rows(b), 1, 0) for (i=1; i<=rows(rescale); i++) { if (strtoreal(rescale[i,2])>=.) { display("{err}rescale(): invalid value") exit(198) } names = coefplot_parse_namelist(rescale[i,1], "*", "rescale") for (j=1; j<=rows(names); j++) { p = select(1::rows(match), strmatch(eq, names[j,1]) :& strmatch(coef, names[j,2]) :& (match:==0)) if (rows(p)==0) continue c[p] = J(rows(p), 1, strtoreal(rescale[i,2])) match[p] = J(rows(p), 1, 1) } } } b = b :* c ci = ci :* c } string colvector coefplot_collect_transforms(string colvector eq, string colvector coef) { real scalar i, j string matrix trans, names string colvector T real colvector match, p T = J(rows(eq), 1, "") trans = st_local("transform") if (trans=="") { return(T) } trans = coefplot_parse_matchlist(trans, "transform") match = J(rows(eq), 1, 0) for (i=1; i<=rows(trans); i++) { names = coefplot_parse_namelist(trans[i,1], "*", "transform") for (j=1; j<=rows(names); j++) { p = select(1::rows(match), strmatch(eq, names[j,1]) :& strmatch(coef, names[j,2]) :& (match:==0)) if (rows(p)==0) continue T[p] = J(rows(p), 1, trans[i,2]) match[p] = J(rows(p), 1, 1) } } return(T) } void coefplot_mlabels(string colvector mlbl, real colvector mlpos, string colvector eq, string colvector coef) { real scalar i, j string matrix mlab, names real colvector match, p mlab = st_local("mlabels2") if (mlab=="") { return } mlab = coefplot_parse_matchlist(mlab, "mlabels", 2) match = J(rows(eq), 1, 0) for (i=1; i<=rows(mlab); i++) { names = coefplot_parse_namelist(mlab[i,1], "*", "mlabels") for (j=1; j<=rows(names); j++) { p = select(1::rows(match), strmatch(eq, names[j,1]) :& strmatch(coef, names[j,2]) :& (match:==0)) if (rows(p)==0) continue mlbl[p] = J(rows(p), 1, mlab[i,3]) mlpos[p] = J(rows(p), 1, strtoreal(mlab[i,2])) match[p] = J(rows(p), 1, 1) } } } void coefplot_rename(string scalar rename, real scalar regex, string colvector eq, string colvector coef) { real scalar i, j, rl real colvector p, p0, match string matrix names if (regex) { rename = coefplot_parse_matchlist(rename, "rename") p0 = 1::rows(coef) for (i=1; i<=rows(rename); i++) { names = coefplot_parse_namelist(rename[i,1], "*", "rename") for (j=1; j<=rows(names); j++) { if (rows(p0)==0) return match = (strmatch(eq[p0], names[j,1]) :& regexm(coef[p0], names[j,2])) p = select(p0, match) if (rows(p)==0) continue coef[p] = coefplot_regexr(coef[p], names[j,2], rename[i,2]) p0 = select(p0, match:==0) } } return } rename = coefplot_parse_matchlist(rename, "rename") p0 = 1::rows(coef) for (i=1; i<=rows(rename); i++) { // syntax: *abc for suffix rename // abc* for prefix rename // abc for exact rename names = coefplot_parse_namelist(rename[i,1], "*", "rename") for (j=1; j<=rows(names); j++) { if (rows(p0)==0) return if (substr(names[j,2],1,1)=="*") { rl = strlen(names[j,2])-1 match = strmatch(eq[p0], names[j,1]) :& (substr(coef[p0], -rl, .):==substr(names[j,2], -rl, .)) p = select(p0, match) if (rows(p)==0) continue coef[p] = substr(coef[p], 1, strlen(coef[p]) :- rl) :+ rename[i,2] } else if (substr(names[j,2],-1,1)=="*") { rl = strlen(names[j,2])-1 match = strmatch(eq[p0], names[j,1]) :& (substr(coef[p0], 1, rl):==substr(names[j,2], 1, rl)) p = select(p0, match) if (rows(p)==0) continue coef[p] = rename[i,2] :+ substr(coef[p], 1 + rl, .) } else { match = strmatch(eq[p0], names[j,1]) :& (coef[p0]:==names[j,2]) p = select(p0, match) if (rows(p)==0) continue coef[p] = J(rows(p), 1, rename[i,2]) } p0 = select(p0, match:==0) } } } string matrix coefplot_regexr(string matrix x, string matrix y, string matrix z) { string matrix res real scalar r, R, c, C transmorphic scalar rx, cx, ry, cy, rz, cz R = max((rows(x),rows(y),rows(z))) C = max((cols(x),cols(y),cols(z))) rx = (rows(x)==1 ? &1 : (rows(x)cols(atstats)) continue j = atstats[pos] p = select(1..c, strmatch(coefnm, strofreal(i) + "._at*")') at[p] = J(1, cols(p), at0[i,j]) } return(at) } void coefplot_missing(string scalar model, real colvector b) { if (hasmissing(b)) { printf("{txt}(%s: b missing for some coefficients)\n", model) } } void coefplot_atmissing(string scalar model, real colvector at) { if (hasmissing(at)) { if (nonmissing(at)) { printf("{txt}(%s: 'at' missing for some coefficients)\n", model) return } printf("{txt}(%s: could not determine 'at')\n", model) } } void coefplot_cimissing(string scalar model, real scalar ci, real matrix tmp) { if (hasmissing(tmp)) { if (nonmissing(tmp)) { printf("{txt}(%s: CI%g missing for some coefficients)\n", model, ci) return } printf("{txt}(%s: could not determine CI%g)\n", model, ci) } } void coefplot_add_label(struct coefplot_struct scalar C, string scalar name, real scalar i, string scalar lbl, real scalar force) { pointer(string colvector) scalar l if (name=="plot") l = &C.plotlbl else if (name=="by") l = &C.bylbl else if (name=="coef") l = &C.coeflbl else return if (rows(*l)1) c = strtoreal(s[2]) else c = 1 s = s[1] // get relevant data p = p0 if (subgr<.) { p = select(p, C.by[p]:==subgr) if (rows(p)==0) return("") } if (plot<.) { p = select(p, C.plot[p]:==plot) if (rows(p)==0) return("") } if (s=="b") v = C.b[p] else if (s=="v") v = C.V[p] else if (s=="se") v = C.se[p] else if (s=="t") v = C.t[p] else if (s=="tabs") v = abs(C.t[p]) else if (s=="df") v = C.df[p] else if (s=="p") v = C.pval[p] else if (s=="ll") { if ((c*2)>cols(C.ci)) return("") v = C.ci[p,c*2-1] } else if (s=="ul") { if ((c*2)>cols(C.ci)) return("") v = C.ci[p,c*2] } else if (s=="aux") { if (c>cols(C.aux)) return("") v = C.aux[p,c] } // establish sort order (within equations) if (desc) v = -v eqs = C.eqnm[p] eq = J(rows(eqs),1,1) for (i=2; i<=rows(eq); i++) { if (eqs[i]!=eqs[i-1]) eq[i] = eq[i-1]+1 else eq[i] = eq[i-1] } p = sort((eq, v, p), 1..3)[,3] // collect ordered names eqs = ("`"+`"""') :+ C.eqnm[p] :+ (`"""' + "'") coefs = ("`"+`"""') :+ C.coefnm[p] :+ (`"""' + "'") s = eqs[1] + ": " + coefs[1] for (i=2; i<=rows(p); i++) { if (eqs[i]!=eqs[i-1]) s = s + " * " + eqs[i] + ":" s = s + " " + coefs[i] } s = s + " *" return(s) } void coefplot_order(real colvector p0, string scalar order, struct coefplot_struct scalar C) { real scalar i, j, k real colvector p, tag, tmp string colvector eqs if (order=="") return order = coefplot_parse_namelist(order, "", "order") if (order[1,1]=="" & !allof(order[,1], "")) { display("{err}inconsistent order(): " + "specify equations for all or for none") exit(198) } p = J(0,1,.) tag = J(C.r, 1, 0) k = 0 // order coefficients (general) if (order[1,1]!="") { for (i=1; i<=rows(order); i++) { k++ if (order[i,2]==".") { coefplot_appendemptyrow(C, order[i,1], tag, p0) p = p \ C.r continue } tag = tag :+ (k * strmatch(C.coefnm[p0], order[i,2]) :* !tag :* (C.eqnm[p0]:==order[i,1])) if (anyof(tag, k)) { p = p \ select(p0, tag:==k) } } if (anyof(tag, 0)) { p = p \ select(p0, tag:==0) } swap(p,p0); return } // order coefficients within equations order = order[,2]' eqs = C.eqnm[p0[1]] for (i=2; i<=C.r; i++) { // get equations (in right order) if (C.eqnm[p0[i]]!=C.eqnm[p0[i-1]]) { eqs = eqs \ C.eqnm[p0[i]] } } for (j=1; j<=rows(eqs); j++) { for (i=1; i<=cols(order); i++) { k++ if (order[i]==".") { coefplot_appendemptyrow(C, eqs[j], tag, p0) p = p \ C.r continue } tag = tag :+ (k * strmatch(C.coefnm[p0], order[i]) :* !tag :* (C.eqnm[p0]:==eqs[j])) if (anyof(tag, k)) { p = p \ select(p0, tag:==k) } } tmp = (tag:==0):&(C.eqnm[p0]:==eqs[j]) if (any(tmp)) { p = p \ select(p0, tmp) tag = tag :+ tmp } } swap(p,p0); return } void coefplot_appendemptyrow(struct coefplot_struct scalar C, string scalar eq, real colvector tag, real colvector p0) { C.b = C.b \ . C.V = C.V \ . C.se = C.se \ . C.t = C.t \ . C.df = C.df \ . C.pval = C.pval \ . C.at = C.at \ 1 C.aux = C.aux \ J(1, cols(C.aux), .) C.mlbl = C.mlbl \ "" C.mlpos = C.mlpos \ . C.plot = C.plot \ . C.by = C.by \ . C.ci = C.ci \ J(1, cols(C.ci), .) C.coefnm = C.coefnm \ "" C.eqnm = C.eqnm \ eq C.trans = C.trans \ "" tag = tag \ . C.r = C.r + 1 p0 = p0 \ C.r } void coefplot_coeflbls(struct coefplot_struct scalar C) { real scalar i, j, k real colvector tag string matrix labels, names C.coeflbl = J(C.r, 1, "") tag = J(C.r, 1, 0) labels = coefplot_parse_matchlist(st_local("coeflabels"), "coeflabels") for (j=1; j<=rows(labels); j++) { names = coefplot_parse_namelist(labels[j,1], "*", "coeflabels") for (k=1; k<=rows(names); k++) { tag = tag :+ j * strmatch(C.eqnm, names[k,1]) :* strmatch(C.coefnm, names[k,2]) :* (tag:==0) } } _editmissing(tag, 0) for (i=1; i<=C.r; i++) { if (tag[i] & C.plot[i]<.) { // C.plot is missing for gaps from order() C.coeflbl[i] = labels[tag[i],2] } } } void coefplot_multiple_eqs(struct coefplot_struct scalar C) { real scalar i, meqs string matrix eq eq = C.eqnm, strofreal(C.plot), strofreal(C.by) _sort(eq, (3,2,1)) meqs = 0 for (i=2; i<=rows(eq); i++) { if (eq[i,1]!=eq[i-1,1] & eq[i,2]==eq[i-1,2] & eq[i,3]==eq[i-1,3]) { meqs = 1 break } } if (meqs==0) { C.eqnm = J(rows(C.eqnm), 1, "_") } st_local("meqs", strofreal(meqs)) } void coefplot_bycoefs(struct coefplot_struct scalar C) { real scalar i, j, k, meqs real colvector p string scalar eql string colvector bylbl, last, eqlbls meqs = (st_local("meqs")!="0") & (st_local("noeqlabels")=="") if (meqs) eqlbls = tokens(st_local("eqlabels"))' bylbl = C.bylbl C.bylbl = C.coeflbl swap(C.at, C.by) j = 0 k = 1 for (i=1; i<=C.r; i++) { if (i>1) { if (C.eqnm[i]!=C.eqnm[i-1]) k++ } if ((C.eqnm[i], C.coefnm[i])!=last) j++ last = (C.eqnm[i], C.coefnm[i]) C.by[i] = j if (meqs) { if (k<=rows(eqlbls)) eql = eqlbls[k] else eql = C.eqnm[i] C.bylbl[j] = eql + ": " + C.bylbl[i] } else C.bylbl[j] = C.bylbl[i] } C.bylbl = C.bylbl[|1 \ j|] C.eqnm = J(C.r, 1, "_") C.coefnm = strofreal(C.at) C.coeflbl = J(C.r, 1, "") for (i=1; i<=C.r; i++) { C.coeflbl[i] = bylbl[C.at[i]] } C.at = J(C.r, 1, 1) p = coefplot_niceorder(C.eqnm, C.coefnm, C.plot, C.by, C.r) C.b = C.b[p] C.V = C.V[p] C.se = C.se[p] C.t = C.t[p] C.df = C.df[p] C.pval = C.pval[p] C.at = C.at[p] C.aux = C.aux[p,] C.mlbl = C.mlbl[p] C.mlpos = C.mlpos[p] C.plot = C.plot[p] C.by = C.by[p] C.ci = C.ci[p,] C.coefnm = C.coefnm[p] C.eqnm = C.eqnm[p] C.trans = C.trans[p] C.coeflbl = C.coeflbl[p] st_local("n_subgr", strofreal(rows(C.bylbl))) } void coefplot_catvals(struct coefplot_struct scalar C) { real scalar i, j, k, e, eqgap, ggap real colvector pos, at0 string scalar glbls, xlab string colvector eqs string matrix groups, names // determine plot positions for (i=2; i<=C.r; i++ ) { C.at[i] = C.at[i-1] + ((C.coefnm[i]!=C.coefnm[i-1]) // new coefficient | (C.eqnm[i]!=C.eqnm[i-1]) // new equation | (C.plot[i]==.)) // gap from order() } // reposition coefplot_relocate(C) C.xmin = min(C.at) // equation numbers and labels eqs = tokens(st_local("eqlabels"))' xlab = st_local("eqxlab") C.eq = J(C.r, 1, 1) C.eqlbl = J(C.r, 1, "") j = 1 if (j>rows(eqs)) C.eqlbl[j] = coefplot_get_xlab(C.eqnm[1], xlab) else C.eqlbl[j] = eqs[j] for (i=2; i<=C.r; i++ ) { C.eq[i] = C.eq[i-1] if (C.eqnm[i]!=C.eqnm[i-1]) { j++ if (j>rows(eqs)) C.eqlbl[j] = coefplot_get_xlab(C.eqnm[i], xlab) else C.eqlbl[j] = eqs[j] C.eq[i] = C.eq[i] + 1 } } C.eqlbl = C.eqlbl[|1,1 \ j,.|] // group IDs groups = st_local("groups") C.grp = J(C.r, 1, 0) if (groups!="") { groups = coefplot_parse_matchlist(groups, "groups") eqs = uniqrows(C.eqnm) for (e=1; e<=rows(eqs); e++) { for (j=1; j<=rows(groups); j++) { names = coefplot_parse_namelist(groups[j,1], "*", "groups") for (k=1; k<=rows(names); k++) { C.grp = C.grp :+ j * strmatch(C.eqnm, names[k,1]) :* strmatch(C.coefnm, names[k,2]) :* (C.grp:==0) :* (C.eqnm:==eqs[e]) :* (C.plot:<.) } for (i=1; i<=C.r; i++) { pos = select(1::C.r, (C.grp:==j) :& (C.eqnm:==eqs[e])) if (length(pos)>0) { C.grp[|pos[1] \ pos[rows(pos)]|] = J((pos[rows(pos)]-pos[1]+1), 1, j) } } } } for (j=1; j<=rows(groups); j++) { glbls = glbls + " " + "`" + `"""' + groups[j,2] + `"""' + "'" } st_local("groups", strtrim(glbls)) } // add gaps between equations and groups eqgap = strtoreal(st_local("eqgap")) ggap = strtoreal(st_local("ggap")) if (eqgap==0 & ggap==0) return at0 = C.at for (i=2; i<=C.r; i++ ) { C.at[i] = C.at[i-1] + (at0[i,1] - at0[i-1,1]) + // update downstream (C.eqnm[i]!=C.eqnm[i-1])*eqgap + // new eq (C.eqnm[i]==C.eqnm[i-1] & C.grp[i]!=C.grp[i-1])*ggap // new group } } string scalar coefplot_get_xlab(string scalar v, string scalar interact) { if (interact=="") return(v) stata("compile_xlabel, v(" + v + ") interact(" + interact + ")") return(st_local("coeflbl")) } void coefplot_relocate(struct coefplot_struct scalar C) { real scalar i, j, k real colvector tag, p string matrix pos, names if (st_local("relocate")=="") return // set positions tag = J(C.r, 1, 0) pos = coefplot_parse_matchlist(st_local("relocate"), "relocate") for (j=1; j<=rows(pos); j++) { names = coefplot_parse_namelist(pos[j,1], "*", "relocate") for (k=1; k<=rows(names); k++) { tag = tag :+ j * strmatch(C.eqnm, names[k,1]) :* strmatch(C.coefnm, names[k,2]) :* (tag:==0) } } _editmissing(tag, 0) p = strtoreal(pos[,2]) for (i=1; i<=C.r; i++) { if (tag[i] & (C.plot[i]<.)) { C.at[i] = p[tag[i]] } } // reorder p = order((C.at, (1::C.r)), (1,2)) C.b = C.b[p] C.V = C.V[p] C.se = C.se[p] C.t = C.t[p] C.df = C.df[p] C.pval = C.pval[p] C.at = C.at[p] C.aux = C.aux[p,] C.mlbl = C.mlbl[p] C.mlpos = C.mlpos[p] C.plot = C.plot[p] C.by = C.by[p] C.ci = C.ci[p,] C.coefnm = C.coefnm[p] C.eqnm = C.eqnm[p] C.trans = C.trans[p] C.coeflbl = C.coeflbl[p] } void coefplot_headings(struct coefplot_struct scalar C) { real scalar i, j, k, off, gap, fskip real colvector tag string scalar hlbls string matrix headings, names off = strtoreal(st_local("hoff")) gap = strtoreal(st_local("hgap")) // if headings are equations if (st_local("eqashead")!="") { fskip = C.at[1] j = 0 for (i=1; i<=C.r; i++) { if (C.eq[i]!=j) { C.at[|i \ .|] = C.at[|i \ .|] :+ 1 :+ (gap*(i>1)) hlbls = hlbls + " " + strofreal(C.at[i] - fskip + off) } j = C.eq[i] } st_local("hlbls", strtrim(hlbls)) return } // if headings are not equations headings = st_local("headings") if (headings=="") { st_local("hlbls", "") return } tag = J(C.r, 1, 0) if (C.r>1) { tag[|2 \ .|] = tag[|2 \ .|] :+ (C.at[|2 \ .|]:==C.at[|1 \ C.r-1|]) _editvalue(tag, 1, .) } headings = coefplot_parse_matchlist(headings, "headings") for (j=1; j<=rows(headings); j++) { names = coefplot_parse_namelist(headings[j,1], "*", "headings") for (k=1; k<=rows(names); k++) { tag = tag :+ j * strmatch(C.eqnm,names[k,1]) :* strmatch(C.coefnm, names[k,2]) :* (tag:==0) } } _editmissing(tag, 0) for (i=1; i<=C.r; i++) { if (tag[i] & (C.plot[i]<.)) { C.at[|i \ .|] = C.at[|i \ .|] :+ 1 :+ (gap*(i>1)) hlbls = hlbls + " " + strofreal(C.at[i] - 1 + off) + " " + "`" + `"""' + headings[tag[i],2] + `"""' + "'" } } st_local("hlbls", strtrim(hlbls)) } string matrix coefplot_parse_matchlist(string scalar s, string scalar opt, | real scalar nc0) { real scalar c, a, b, j, i, nc real rowvector eqpos string rowvector stok string matrix res if (args()==3) nc = nc0 else nc = 1 if (strtrim(s)=="") return(J(0, 1+nc, "")) stok = _coefplot_parse_matchlist_stok(s) c = cols(stok) a = b = i = 1 eqpos = select(1::c, stok':=="=")' res = J(cols(eqpos), 1+nc, "") for (j=1; j<=cols(eqpos); j++) { b = eqpos[j] if (b==a | b==c | (b+nc)>cols(stok)) { printf("{err}%s(): invalid matchlist\n", opt) exit(198) } res[i,] = (invtokens(stok[|a \ b-1|]), stok[|b+1 \ b+nc|]) a = b + 1 + nc i++ } if (a<=c) { printf("{err}%s(): invalid matchlist\n", opt) exit(198) } nc = nc + 1 for (i=1; i<=rows(res); i++) { // strip quotes in last column if (substr(res[i,nc], 1, 1)==`"""') { res[i,nc] = substr(res[i,nc], 2, strlen(res[i,nc])-2) } else if (substr(res[i,nc], 1, 2)=="`" + `"""') { res[i,nc] = substr(res[i,nc], 3, strlen(res[i,nc])-4) } } return(res) } string rowvector _coefplot_parse_matchlist_stok(string scalar s) { real scalar i, c, j string scalar tok, t0 string rowvector pchars, stok transmorphic t // Step 1: split input at blanks and equal signs while binding on quotes // and parentheses pchars = (" ", "=") t = tokeninit("", pchars, (`""""', `"`""'"', "()")) tokenset(t, s) stok = tokengetall(t) // Step 2: remove blanks and merge "(...)" with surrounding tokens (unless // blank or equal sign) c = cols(stok) j = c + 1 for (i=c; i; i--) { tok = stok[i] if (tok==" ") continue // remove blanks if (i>1) { if (substr(tok,1,1)=="(") { if (!anyof(pchars, stok[i-1])) { stok[i-1] = stok[i-1] + tok continue } } else if (tok!="=") { if (substr(stok[i-1],-1,1)==")") { stok[i-1] = stok[i-1] + tok continue } } } stok[--j] = tok } // return result if (j>c) return(J(1,0,"")) return(stok[|j \ .|]) } string matrix coefplot_parse_namelist(string scalar s, string scalar defeq, string scalar opt) { transmorphic t real scalar i, c string rowvector stok string matrix res if (s=="") return(J(0,2,"")) t = tokeninit(" ", ":") tokenset(t, s) stok = tokengetall(t) c = cols(stok) for (i=1; i<=c; i++) { // strip quotes if (substr(stok[i], 1, 1)==`"""') { stok[i] = substr(stok[i], 2, strlen(stok[i])-2) } else if (substr(stok[i], 1, 2)=="`" + `"""') { stok[i] = substr(stok[i], 3, strlen(stok[i])-4) } } res = J(0, 2, "") for (i=1;i<=c;i++) { if (i+1<=c) { if (stok[i+1]==":") { if (stok[i]==":") { printf("{err}%s(): invalid namelist\n", opt) exit(198) } if (i+2<=c) { if (stok[i+2]==":") { printf("{err}%s(): invalid namelist\n", opt) exit(198) } if (i+3<=c) { if (stok[i+3]==":") { // "... eq: eq: ..." res = res \ (stok[i], "*") i++ continue } } res = res \ (stok[i], stok[i+2]) // "... eq:name ..." defeq = stok[i] i = i + 2 continue } res = res \ (stok[i], "*") // "... eq:" i++ continue } } if (stok[i]==":") { printf("{err}%s(): invalid namelist\n", opt) exit(198) } res = res \ (defeq, stok[i]) } return(res) } void coefplot_put(struct coefplot_struct scalar C) { real scalar i real rowvector vi st_store((1,C.r), st_local("b"), C.b) st_store((1,C.r), st_local("V"), C.V) st_store((1,C.r), st_local("se"), C.se) st_store((1,C.r), st_local("t"), C.t) st_store((1,C.r), st_local("df"), C.df) st_store((1,C.r), st_local("pval"), C.pval) st_store((1,C.r), st_local("at"), C.at) st_sstore((1,C.r), st_local("mlbl"), C.mlbl) st_store((1,C.r), st_local("mlpos"), C.mlpos) st_store((1,C.r), st_local("plot"), C.plot) st_store((1,C.r), st_local("by"), C.by) st_store((1,C.r), st_local("eq"), C.eq) st_store((1,C.r), st_local("grp"), C.grp) vi = J(1, cols(C.ci), .) for (i=1; i<=(cols(vi)/2); i++) { vi[1,i*2-1] = st_varindex(st_local("ll" + strofreal(i))) vi[1,i*2] = st_varindex(st_local("ul" + strofreal(i))) } st_store((1,C.r), vi, C.ci) vi = J(1, cols(C.aux), .) for (i=1; i<=cols(vi); i++) { vi[1,i] = st_varindex(st_local("aux" + strofreal(i))) } st_store((1,C.r), vi, C.aux) } void coefplot_at_unique(struct coefplot_struct scalar C) { assert(rows(uniqrows((C.by,C.at)))==C.r) } void coefplot_apply_transform(struct coefplot_struct scalar C) { real scalar i, j, rc, x0, x1, mis string scalar trans0, trans, trans1 string rowvector vname real rowvector vpos if (allof(C.trans[i], "")) return vname = J(1, cols(C.ci), "") for (j=1; j<=(cols(C.ci)/2); j++) { vname[j*2-1] = st_local("ll"+strofreal(j)) vname[j*2] = st_local("ul"+strofreal(j)) } vname = st_local("b"), vname vpos = st_varindex(vname) mis = 0 for (i=1; i<=C.r; i++) { if (C.trans[i]=="") continue if (C.trans[i]!=trans0) trans0 = C.trans[i] trans = _coefplot_inject_temvars(trans0, cols(C.ci), cols(C.aux)) for (j=1; j<=cols(vname); j++) { trans1 = subinstr(trans, "@", vname[j]) x0 = _st_data(i, vpos[j]) rc = _stata("replace " + vname[j] + " = " + trans1 + " in " + strofreal(i), 1) if (rc) { printf("{err}transform '%s' invalid\n", trans0) exit(198) } x1 = _st_data(i, vpos[j]) if (x1>=. & x1!=x0) mis = 1 } } if (mis) { display("{txt}(transform missing for some coefficients or CIs)") } } void coefplot_lbl_is_multiline() { string scalar lbl lbl = strtrim(st_local("lbl")) if ((substr(lbl, 1, 1)==`"""' | substr(lbl, 1, 2)==("`" + `"""'))) { return(499) } } void coefplot_get_coefs(struct coefplot_struct scalar C) { st_local("coefs", invtokens("`" :+ `"""' :+ C.coefnm' :+ `"""' :+ "'")) } void coefplot_get_coeflbl(struct coefplot_struct scalar C, real scalar i) { st_local("coeflbl", C.coeflbl[i]) } void coefplot_get_plotlbl(struct coefplot_struct scalar C, real scalar i) { st_local("plotlbl", C.plotlbl[i]) } void coefplot_get_bylbl(struct coefplot_struct scalar C, real scalar i) { st_local("bylbl", C.bylbl[i]) } void coefplot_get_eqlbl(struct coefplot_struct scalar C, real scalar i) { st_local("eqlbl", C.eqlbl[i]) } void coefplot_ticks_and_labels(struct coefplot_struct scalar C) { real scalar i, between string scalar labels, grid, space between = (st_local("grid")=="between") st_local("xrange", strofreal(C.xmin-0.5) + " " + strofreal(max(C.at)+0.5)) if (between & C.plot[1]<.) { if (C.xmin1) { if ((C.eqnm[i], C.coefnm[i])==(C.eqnm[i-1], C.coefnm[i-1])) { continue } if (between & C.plot[i-1]<.) { grid = grid + space + strofreal(C.at[i-1] + min((0.5, (C.at[i]-C.at[i-1])/2))) } } if (C.plot[i]<.) { labels = labels + space + strofreal(C.at[i]) + " `" + `"""' + C.coeflbl[i] + `"""' + "'" if (between==0) grid = grid + space + strofreal(C.at[i]) else if (i>1) { grid = grid + space + strofreal(C.at[i] - min((0.5, (C.at[i]-C.at[i-1])/2))) } space = " " } } st_local("xlabels", labels) st_local("xgrid", grid) } void coefplot_combine_ciopts() { string scalar opt, p opt = st_local("opt") p = substr(opt, 2, strpos(opt,"(")-2) // get # from "p#(...)" if (strtoreal(p)<.) { opt = substr(opt, 3+strlen(p), strlen(opt)-3-strlen(p)) // get contents st_local("opt_"+p, st_local("opt_"+p) + " " + opt) } else { st_local("options", st_local("options") + " " + opt) } } void coefplot_parsecomma(string scalar lhs, string scalar rhs, string scalar lin) { transmorphic t string scalar l, r, token t = tokeninit("", ",", (`""""', `"`""'"'), 0, 0) tokenset(t, st_local(lin)) while ((token = tokenget(t))!="") { if (token==",") { r = token while ((token = tokenget(t))!="") { r = r + token } st_local(lhs, l) st_local(rhs, r) return } l = l + token } st_local(lhs, l) st_local(rhs, r) } void coefplot_inject_temvars(string scalar s, real scalar nci, real scalar naux) { st_local(s, _coefplot_inject_temvars(st_local(s), nci, naux)) } string scalar _coefplot_inject_temvars(string scalar s, real scalar nci, real scalar naux) { real scalar i string scalar v, vname string rowvector nspace nspace = J(1, nci*2 + naux, "") for (i=1; i<=nci; i++) { nspace[i*2-1] = "ll" + strofreal(i) nspace[i*2] = "ul" + strofreal(i) } for (i=1; i<=naux; i++) { nspace[nci*2+i] = "aux" + strofreal(i) } nspace = nspace, ("b", "V", "se", "t", "df", "pval", "at", "mlbl", "mlpos", "plot", "by") while (regexm(s,"@[Va-z]+[0-9]*")) { v = regexs() vname = substr(v, 2, .) if (vname=="ll" | vname=="ul" | vname=="aux") { vname = vname + "1" } if (anyof(nspace, vname)==0) { printf("{err}%s not found\n", v) exit(error(111)) } s = subinstr(s, v, st_local(vname), 1) } return(s) } end