********************************************************************************
* Plot Confidently
********************************************************************************

capture program drop plot_confidently
program plot_confidently

version 17

syntax varlist(numeric min=1) ///
		[if]            /// 
		[in],           /// 
		[Over(varname)] /// 
		[By(varname)]   ///
		[Graphopts(string asis)] ///
		[Scale]
			   
	/// temp file

	qui tempfile main 
	qui save  `main', replace

	/// sample indicator for mapping the [IF] condition

	marksample touse, strok

	/// keep if X == x

	qui keep if `touse' == 1
			
	local check : word 1 of `varlist'
	qui count if !(missing(`check'))
	local N = `r(N)'
	
	
if(`r(N)' <= 0){
			
	display as err "	Sorry! There are no observations to work with."

}

	
if(`r(N)'> 0){		
	
	unab vars : `varlist'	
	if(`: word count `vars'' > 1){
			
	display as err "	This program works with only one variable."
	display as err "	For multiple variables, please use mult_plot."
	display as err "	You need to run:" 
	display as err "	ssc install multi_plot, replace"
	exit 198
}
	
	/// this requires coefplot to work
	cap which coefplot
	if _rc == 111{
			
	display as err "	Sorry! This wrapper function requires the 'coefplot' package!"
	display as err "	You need to run:" 
	display as err "	ssc install coefplot, replace"
	exit 198
}

* Accounting for scale

	if "`scale'" !="" {
	
    global x_title "Percentage (%)"
	global xlabs "0(20)100"
}

	if "`scale'" == "" {
	
    global x_title ""
	global xlabs "#5"
}
	
* simple plot

	if "`over'" == "" & "`by'" == "" {
		
	estimates clear    
	qui mean `varlist'
	estimates store simple
	local n = e(N) 

	coefplot simple,                             ///  
	title("Estimates with confidence intervals (N=`n')", /// 
	size(medium))                               /// 
	xlab($xlabs)                                ///
	xtitle($x_title)                            ///
	mlabel format(%9.1f)                        /// 
	mlabposition(12)                            /// 
	mlabgap(*2)                                 /// 
	ciopts(recast(rcap))                        /// 
	`graphopts' 		
}

	if "`over'" == "" & "`by'" != "" {
		
	display as err "	Sorry! 'By' is a second order level of disaggregation for this command."
	display as err "	'By' can only be used in conjunction with 'over'"
	display as err "	If you want only one level of disaggregation, please use 'over'"
}

	if "`over'" != "" {
		
	* IF by has not been specified
		if "`by'" =="" {
	
	* Calculate N accounting for any missing observations under `over'
	
	qui summarize `varlist' if `over' != . 
	local N = `r(N)'
	local var_mean = strltrim("`: display %9.1f r(mean)'")
 
preserve

qui statsby,  /// 
by(`over')    /// 
clear:        /// 
ci            /// 
means         /// 
`varlist'

qui{
egen label = concat(`over'), decode p(" x ")
/// calculates the correct group-wise DoF --- note: DoF = N-1 foreach group mean
replace N  = N-1
/// making a matrix of summary stats
mkmat mean /// 
      se   /// 
	  lb   /// 
	  ub   /// 
	  N,   /// 
	  matrix(R)
mat  R = R' 
}

* labels
qui{
levelsof `over', local(levels)
local lbls
foreach   z of local levels {
    local lbl : label (`over') `z'
    local lbls      `" `lbls' "`lbl'" "'
}
local  lbls         `" `lbls' "'
matrix colnames R = `lbls'
restore
}

//// syntax to make a plot using coefplot() via a matrix
global call "(matrix(R), se(2) df(R[5,.]))"

/*
making the plot using the all globals and our matrices
*/
	
coefplot $call,                                       		///
xline(`var_mean',                                     		/// 
lcolor(red))                                          		///
ciopts(recast(rcap))                                  		///
title("`: var la `varlist''",  size(medium))          		///
subtitle("N = `N' and Mean = `var_mean'", size(small)) 		/// 
ytitle("`: var la `over' '")                       			///
xtitle("`: var la `varlist''")                       		///
mlabel                                                		/// 
format(%9.1f)                                         		/// 
mlabposition(12)                                      		///
legend(subtitle("`: var la `over' '",              			/// 
size(small)))                                         		/// 
legend(position(6)                                   		/// 
size(small)                                           		///
rows(1))                                              		/// 
levels(95)                                            		///
xlab($xlabs)                                		  		///
legend(off)                                           		///
plotregion(margin(large))                             		/// 
 `graphopts'                                          

}

	* IF by has been specified
		if "`by'" !="" {
	
	* Calculate N accounting for any missing observations under `over' or 'by'
	qui summarize `varlist' if (`by' != . & `over' != .)
	local N = `r(N)'
	local var_mean = strltrim("`: display %9.1f r(mean)'")
	
	
qui levelsof `by', local(plot_levels)
foreach p of local plot_levels {  
preserve

qui keep if `by' == `p'

qui statsby, /// 
by(`over')  /// 
clear:       /// 
ci           /// 
means        /// 
`varlist'

qui{
egen label = concat(`over'), decode p(" x ")
replace N = N-1
mkmat mean /// 
	  se   /// 
	  lb   /// 
	  ub   /// 
	  N,   /// 
	  matrix(R_`p')
mat R_`p' = R_`p'' 
}

qui{
levelsof `over', local(levels)
local lbls_`p'
foreach   z of local levels {
	local lbl_`p' : label (`over') `z'
    local lbls_`p' `" `lbls_`p'' "`lbl_`p''" "'
}
local lbls `" `lbls_`p'' "'
matrix colnames R_`p' = `lbls_`p''
restore
	}
}

qui { 
levelsof `by', local(levels)
global call
qui local labl : value label `by'
qui foreach l of local levels {
		         local `by'`l' : label `labl' `l'	
		
* creating an empty variable that is labelled with the command we need - we then extract the command from the label
		gen cat_`l'   = ""	
		lab var cat_`l'     "(matrix(R_`l'), se(2) df(R_`l'[5,.]) label(``by'`l''))"
			foreach v of varlist cat_* {
						global call "$call `: var la `v''"		
						drop cat_*
		}	
	}	
}	
	
/*
making the plot using the all globals and our new matrices
*/

coefplot $call,                                       	///
xline(`var_mean',                                     	/// 
lcolor(red))                                          	///
ciopts(recast(rcap))                                  	///
title("`: var la `varlist''",  size(medium))          	///
subtitle("N = `N' and Mean = `var_mean'", size(small)) 	/// 
ytitle("`: var la `over' '")                        	///
xtitle("`: var la `varlist''")                        	///
mlabel                                                	/// 
format(%9.1f)                                         	/// 
mlabposition(12)                                      	///
legend(subtitle("`: var la `by' '",              		/// 
size(small)))                                         	/// 
legend(position(6)                                    	/// 
size(small)                                           	///
rows(1))                                              	/// 
levels(95)                                            	///
xlab($xlabs)                                			///
legend(on)                                            	///
plotregion(margin(large))                             	///
`graphopts'                                           

	}

}	

	
	}
	
	cap macro drop call
	cap macro drop xlabs
	cap macro drop xtitle
	qui use `main', clear

end