*! version 1.1 19Sep2022 capture program drop plottwoway program define plottwoway, rclass version 16 syntax, FRame(string) [COMmand NODIAG YZero NODraw] qui { ** default colour palette local graph_syntax = "" local gr_counter = 0 ** (1) STOCKTAKING ***************************************************** ** how many plots are stored eventually? local I = 0 cap while _rc ==0 { local I = `I' + 1 frame `frame': cap confirm var x_val`I' } local I = `I'- 1 ** (2) CUSTOMIZATION ******************************************* ** global two-way options: frame `frame'_cust: local tw_op = cust_two[1] frame `frame'_cust: local oth_op = cust_oth[1] ** include zero on the y-axis (pt1) if "`yzero'" != "" local maxval = 0 ** produce the two-way graph from data stored in `frame', using the customization options stored in `frame'_cust forvalues j = 1/`I'{ local gr_counter = `gr_counter' + 1 ** options applicable to all plot types: frame `frame'_cust: local output = cust_out[`j'] frame `frame'_cust: local graph = cust_gra[`j'] frame `frame'_cust: local gs_op = cust_opt[`j'] ** are we using a secondary axis? local 0 plotaux , `gs_op' _parse expand cmd yax : 0 , common(YAXis()) if "`yax_op'" == "yaxis(2)" local ytitle2 ytitle(`output',axis(2)) else local ytitle1 ytitle(`output') ** include zero on the y-axis (pt2) if "`yzero'" != "" & "`yax_op'" != "yaxis(2)"{ frame `frame': qui sum y_val`j' if `maxval' < r(max) local maxval = r(max) } ** append graph syntax to the twoway command local graph_syntax `graph_syntax' (`graph' y_val`j' x_val`j', pstyle(p`j') `gs_op') ** CI options applicable to plotmeans & plotbetas: frame `frame'_cust: cap local rgraph= cust_rgr[`j'] frame `frame'_cust: cap local ci_leg= cust_lci[`j'] frame `frame'_cust: cap local ci_op = cust_oci[`j'] ** CI plotted if rgraph `j' is defined in `frame'_cust if "`rgraph'" !="" { ** CI transparency & colors local 0 x), `ci_op' _parse expand cmd citr : 0 , common(CoLor()) ** is color(+transparency) defined? tokenize `citr_op', parse("()") local ci_col `3' ** if no, is color for the main chart defined? local 999 plotaux , `gs_op' if `"`gs_op'"' != "" _parse expand x col : 999 , common(CoLor()) if `"`ci_col'"' =="" & `"`col_op'"' != "" { tokenize `col_op', parse("(%)") tokenize `3', parse("%") local ci_col `1' } ** is transparency for rarea graphs defined? if "`rgraph'" == "rarea" { tokenize `citr_op', parse("%)") if "`3'"=="" local ci_col `ci_col'%15 tokenize `col_op', parse(`"""') if "`2'" != "" local ci_col ""`ci_col'"" } ** extract all other ci options and save it as `cioth_op' local 0 (`cmd_1' _parse expand cmd cioth : 0 ** CI line width for rarea graphs (default = none) if "`rgraph'" == "rarea" { local 0 plotaux , `ci_op' if `"`ci_op'"' != "" _parse expand cmd lw : 0 , common(LWidth()) if `"`lw_op'"' == "" local cioth_op `cioth_op' lwidth(none) } ** copy axis options to the CI local 0 plotaux , `gs_op' if `"`gs_op'"' != "" _parse expand cmd ax : 0 , common(XAXis() YAXis()) local gr_counter = `gr_counter' + 1 ** updated options for ci area graphs local r_op pstyle(p`j') `cioth_op' if `"`ci_col'"' != "" local r_op color(`ci_col') `r_op' ** legends for ci area graphs if `"`ci_leg'"' != "" local r_op `r_op' legend(label(`gr_counter' "`ci_leg'")) ** rgraph syntax local graph_syntax `graph_syntax' (`rgraph' LCI_val`j' UCI_val`j' x_val`j' , `r_op' `ax_op') } } ** include zero on the y-axis (pt3) (add to the global two-way options) if "`yzero'" != "" { local exp = floor(log10(`maxval'/4)) local ystep = floor((`maxval'/4)/(10^`exp'))*(10^`exp') local ymax = `ystep'*5 local tw_op `tw_op' ysc(r(0 `ymax')) local 0 plotaux , `tw_op' if `"`tw_op'"' != "" _parse expand cmd yl : 0 , common(YLabel()) if `"`yl_op'"' == "" local tw_op `tw_op' ylabel(0(`ystep')`ymax') } ** information for troubleshooting if "`nodiag'"=="" n di as text " - output type: " "`output'" if "`nodiag'"=="" n di as text " - graph type: " "`graph'" if "`nodiag'"=="" & `"`tw_op'"' != "" n di as text " - twoway options: " `"`tw_op'"' if "`nodiag'"=="" & `"`gs_op'"' != "" n di as text " - graph-specific options: " `"`gs_op'"' ** default title of the y-axis (`output' type corresponding to the last plot) local 0 plotaux , `tw_op' if `"`tw_op'"' != "" _parse expand cmd yt : 0 , common(YTitle(string)) if `"`yt_op'"' == "" local tw_op `tw_op' `ytitle1' `ytitle2' ** default title of the x-axis (label of x_val in the last plot) if `"`tw_op'"' != "" _parse expand cmd xt : 0 , common(XTitle(string)) if `"`xt_op'"' == "" { cap frame `frame': local xlbl : variable label x_val`I' local tw_op `tw_op' xtitle("`xlbl'") } ** white background for s2color scheme unless specified otherwise local 0 plotaux , `tw_op' if `"`tw_op'"' != "" _parse expand cmd bg : 0 , common(SCHeme()) local cscheme = c(scheme) if "`bg_op'"=="" & "`cscheme'"=="s2color" { local 0 plotaux , `tw_op' if `"`tw_op'"' != "" _parse expand cmd bg2 : 0 , common(graphregion()) if "`bg2_op'" == "" local tw_op `tw_op' graphregion(fcolor(white) lcolor(white)) } if "`command'" != "" n di as text " - twoway graph command: " as res `"frame `frame': twoway `graph_syntax', `nodraw' `tw_op' `oth_op'"' ** run the twoway command (sourced from the `frame'): frame `frame': cap twoway `graph_syntax', `nodraw' `tw_op' `oth_op' if _rc !=0 { n di as err "Error: The plotted data were generated but some of the specified graphing options were inalid / not allowed." n di as err "Use the 'replace' option to replace yhe last plot or to correct the faulty graphing options. Use the 'clear' option to start again." frame `frame': twoway `graph_syntax', `nodraw' `tw_op' `oth_op' } if "`command'" != "" return local cmd frame `frame': twoway `graph_syntax', `nodraw' `tw_op' `oth_op' `nodraw' } end