/*****************************************************************************
LIVING INCOME CALCULATIONS AND OUTPUTS

This stata ado-file produces density (kernel smoothened) plots as fractions about
the total household income with the goal of comparing to the benchmark value

It produces graphs similar to what can be seen at:
https://www.kit.nl/wp-content/uploads/2019/01/Analysis-of-the-income.pdf
https://docs.wixstatic.com/ugd/0c5ab3_93560a9b816d40c3a28daaa686e972a5.pdf

Type
help kitli_compare2bm for more details

---------------------------------------------------------------------------

This opensource file was created and is maintained by Marcelo Tyszler
(m.tyszler@kit.nl), from KIT Royal Tropical Institute, Amsterdam.

This project was jointly done with COSA, and it was supported by
ISEAL, Living Income Community of Practice and GIZ

You are free to use it and modify for your needs. BUT PLEASE CITE US:

Tyszler, et al. (2020). Living Income Calculations Toolbox. KIT ROYAL TROPICAL
INSTITUTE and COSA. Available at: https://github.com/mtyszler/KIT_LivingIncome/

This work is licensed under the Creative Commons Attribution-ShareAlike 4.0 International License.
To view a copy of this license, visit http://creativecommons.org/licenses/by-sa/4.0/.

-----------------------------------------------------------------------------
Last Update:
07/08/2020

*****************************************************************************/

capture program drop kitli_compare2bm
program define kitli_compare2bm, sortpreserve rclass
	syntax varname(numeric) [if] [in], ///
	hh_income(varname numeric) ///
	[grouping_var(varname numeric) ///
	food_value(varname numeric) ///
	label_benchmark(string) ///
	label_food_value(string) ///
	ytitle(string) ///
	spacing(real 0.02) ///
	placement(string) ///
	step_size(integer -1) ///
	colors(string) ///
	show_distribution_graph ///
	show_detailed_graph ///
	show_bar_graph ///
	save_graph_as(string) ///
	]

	version 14


	********************************************
	** Prepare observations which will be used
	marksample touse, novarlist
	qui: replace `touse' = 0 if `varlist' == .
	qui: replace `touse' = 0 if `hh_income' == .
	if "`food_value'" !="" {
		qui: replace `touse' = 0 if `food_value' == .
	}


	** color can only be provided if graph is requested:
	if "`show_distribution_graph'" == ""  & "`show_detailed_graph'" == ""  & ("`colors'" !="" | "`ytitle'" !="" | `spacing' !=0.02 | `step_size' != -1 | "`placement'" !="" ) {
		display as error "WARNING: Graph options will be ignored if neither {it:show_distribution_graph} nor {it:show_detailed_graph} are requested."
	}


	* Save graph can only be used if graph is requested
	if "`save_graph_as'" !="" & "`show_detailed_graph'" == ""  & "`show_distribution_graph'" == ""  & "`show_bar_graph'" == ""   {
		display as error "WARNING: {it:save_graph_as} will be ignored if neither {it:show_distribution_graph} nor {it:show_detailed_graph}  nor {it:show_bar_graph} are requested."
	}

	* food value matching  matching elements
	if "`label_food_value'" !="" & "`food_value'" == ""   {
		display as error "WARNING: {it:label_food_value} will be ignored if {it:food_value} is not provided."
	}


	** load defaults in case optional arguments are skipped:
	capture confirm existence `label_benchmark'
	if _rc == 6 {
		local label_benchmark = "Living Income Benchmark"
	}

	capture confirm existence `label_food_value'
	if _rc == 6 {
		local label_food_value = "(including the value of food)"
	}

	capture confirm existence `colors'
	if _rc == 6 {
		if `c(stata_version)' < 15 {
			local colors = "ebblue | blue | green | orange"
		}
		else {
			local colors = "ebblue%30 | blue%30 | green%30 | orange%30"
		}
	}

	capture confirm existence `ytitle'
	if _rc == 6 {
		local ytitle = "Proportion of households (%)"
	}

	capture confirm existence `placement'
	if _rc == 6 {
		local placement = "right"
	}

	if "`placement'" != "right" & "`placement'" != "left" {
		display as error "WARNING: {it:placement} is provided with value different than {it:right} or {it:left}. This may cause errors in rendering the graph. Consult the help file for valid parameter values"
	}

	********************************************
     * Identify groups:
     if "`grouping_var'" !="" {

        qui: levelsof `grouping_var' if `touse', local(group_levels)

     }


	********************************************
	*** create tempvars
	** rename key variable:
	local li_benchmark = "`varlist'"

	* key components
	tempvar temp_bm_not_achieved temp_hh_income
	qui: gen `temp_hh_income' = `hh_income' if `touse'
	if "`food_value'" !="" {
		qui: replace `temp_hh_income' = `temp_hh_income' + `food_value' if `touse'
	}

	if "`grouping_var'" !="" {
		qui: gen `temp_bm_not_achieved' =  `temp_hh_income' < `li_benchmark' if `touse' & `grouping_var' !=. & `temp_hh_income' !=. & `li_benchmark'!=.
	}
	else {
		qui: gen `temp_bm_not_achieved' =  `temp_hh_income' < `li_benchmark' if `touse'	& `temp_hh_income' !=. & `li_benchmark'!=.
	}

	* for kernels
	tempvar temp_att


  	********************************************
 	 * Identify groups:
	if "`grouping_var'" !="" {
		qui: sum `temp_hh_income' if `touse' & `grouping_var' !=.
	}
	else {
		qui: sum `temp_hh_income' if `touse'
	}

	if `r(N)' == 0 {
		error 2000 // no observations
	}

	********************************************
	if "`show_distribution_graph'" !="" | "`show_detailed_graph'" !="" | {

		local Note_full = `""N (All) = `r(N)'""'
		local labels_cmd = `"label( 1 "All") "'

		local hh_income_label: variable label `hh_income'
		if "`food_value'" !="" {
			local hh_income_label = `" "`hh_income_label'" "`label_food_value'" "'
		}

		* Append group information:
		if "`grouping_var'" !="" {
			local counter = 2
			local cmd_order = "order (1 "
			foreach group in `group_levels' {

				qui: sum `temp_hh_income' if  `grouping_var' == `group' & `touse'

				local group_label: label (`grouping_var') `group'

				local Note_full= `"`Note_full' "N (`group_label') = `r(N)'""'
				local labels_cmd = `"`labels_cmd' label( `counter' "`group_label'")"'
				local cmd_order = "`cmd_order' `counter'"
				local counter = `counter'+1

			}

			local cmd_order = "`cmd_order')"
			local labels_cmd = `"`labels_cmd' `cmd_order'"'
		}
		else {
			local labels_cmd = `"label( 1 "All") order(1)"'
		}

		********************************************
		 * Prepare graph:

		if `step_size' == -1 {
			if r(max) < =  2 {
				local w = 0.1
			}
			else if r(max) < = 50 {
				local w = 1
			}
			else if r(max) < = 100 {
				local w = 10
			}
			else if r(max) < = 500 {
				local w = 25
			}
			else if r(max) < = 1000 {
				local w = 50
			}
			else if r(max) < = 2000 {
				local w = 100
			}
			else if r(max) < = 5000 {
				local w = 200
			}
			else if r(max) < = 20000 {
				local w = 1000
			}
			else if r(max) < = 50000 {
				local w = 10000
			}
			else if r(max) < = 1000000 {
				local w = 100000
			}
			else {
				local w = 1000000
			}
		}
		else {
			local w = `step_size'
		}
		local ticks_x  = "xlabel(0(`w')`r(max)')"

		* Density bin size is defined as half step of the histogram-like bin size
		local w_2 = `w'/2
		local Note_full = `"`Note_full' "bin size = `w_2'""'
		local att_steps = ceil(r(max)/(`w_2')) // number of steps needed
		egen `temp_att' = seq(), from(0) to(`att_steps') // place holder for the steps
		qui: replace `temp_att' = . if [_n]>`att_steps'
		qui: replace `temp_att' = `temp_att'*(`w_2') // replace for the actual value of the step

		** Prepare additional options to be passed to the kernel computation function
		** for details type
		** help kdensity
		local extras = "at(`temp_att') bw(`w')"

		local current_max = 0
		local all_colors = "`colors'"

		** Compute kernels of each group
		if "`grouping_var'" !="" {
			local group_graph = ""
			local counter = 1
			foreach group in `group_levels' {

				local group_label: label (`grouping_var') `group'

				capture drop temp_x_`group' temp_y_`group'
				capture tempvar temp_x_`group' temp_y_`group'
				kdensity `temp_hh_income' if `grouping_var' == `group' & `touse', gen(`temp_x_`group'' `temp_y_`group'') nograph kernel(gaus) `extras'
				if `r(scale)' == . {
					display as error "ERROR: density estimation failed. Please check variables provided, and/or provide a different step size for estimation"
					error 321
					exit
				}
				qui: replace `temp_y_`group'' = `temp_y_`group''*`r(scale)'
				qui: sum `temp_y_`group''
				local current_max = max(`r(max)',`current_max')

				gettoken this_color all_colors: all_colors, parse("|")
				if "`this_color'" == "|" {
					gettoken this_color all_colors: all_colors, parse("|")
				}

				local group_graph = "`group_graph' || line `temp_y_`group'' `temp_x_`group'', color(`this_color') recast(area)"
				local counter = `counter'+1
			}
		}
		else {
			gettoken this_color all_colors: all_colors, parse("|")
			local group_graph = " color(`this_color') recast(area) lcolor(black)"
		}


		* Compute kernel for the whole sample
		capture drop temp_x temp_y
		capture tempvar temp_x temp_y
		if "`grouping_var'" !="" {
			kdensity `temp_hh_income' if `touse' & `grouping_var' !=., gen(`temp_x' `temp_y') nograph kernel(gaus) `extras'
				if `r(scale)' == . {
					display as error "ERROR: density estimation failed. Please check variables provided, and/or provide a different step size for estimation"
					error 321
					exit
				}
		}
		else {
			qui: kdensity `temp_hh_income' if `touse' , gen(`temp_x' `temp_y') nograph kernel(gaus) `extras'
				if `r(scale)' == . {
					display as error "ERROR: density estimation failed. Please check variables provided, and/or provide a different step size for estimation"
					error 321
					exit
				}
		}
		qui: replace `temp_y' = `temp_y'*`r(scale)'
		qui: sum `temp_y'

		local current_max = max(`r(max)',`current_max')

		local h =  round(`current_max',0.01)


		* ticks y
		if `h'>0.16 {
			local ssize = 0.05
		}
		else {
			local ssize = 0.01
		}

		local n_ticks = round(`h'/`ssize')
		local ticks_y = `"ylabel(0 "0" "'
		forvalues i = 1(1)`n_ticks'{
			local t_y = `i'*`ssize'
			local t_y_perc = round(`i'*`ssize'*100)

			local ticks_y = `"`ticks_y' `t_y' "`t_y_perc'" "'
		}
		local ticks_y = `"`ticks_y' )"'

		local all_colors = "`colors'"


		* Genereate detailed information and graphs:
		if "`grouping_var'" !="" {
			local all_colors = "`colors'"
			local counter = 1
			foreach group in `group_levels' {
				local group_label: label (`grouping_var') `group'
				qui: sum `temp_hh_income' if  `grouping_var' == `group' & `touse', det
				local Note = "N = `r(N)'"
				local Note = "`Note', bin size = `w_2'"
				local this_mean = `r(mean)'
				local this_median = `r(p50)'

				qui: sum `temp_bm_not_achieved' if `grouping_var' == `group' & `touse'
				local share_li = round((`r(mean)')*100,0.1)
				local share_li_`counter' = ustrleft(string(`share_li'),4) + "%"

				qui: sum `li_benchmark' if `grouping_var' == `group' & `touse'
				local li_benchmark_`counter' = round(`r(mean)',1)

				if "`show_detailed_graph'" !="" | {

					gettoken this_color all_colors: all_colors, parse("|")
					if "`this_color'" == "|" {
						gettoken this_color all_colors: all_colors, parse("|")
					}

					capture graph drop "detailed_`counter'"
					line `temp_y_`group'' `temp_x_`group'', color(`this_color') recast(area) ///
					ytitle("`ytitle'") `ticks_x' `ticks_y'  xlabel(, labsize(small)) note("`Note'") graphregion(color(white)) ///
					legend(label( 1 "`group_label'") label(2 "`label_benchmark'") label(3 "mean") label(4 "median"))  || ///
					pci 0 `li_benchmark_`counter'' `h' `li_benchmark_`counter'', color(red) || ///
					pci 0 `this_mean' `h' `this_mean', color(blue) || ///
					pci 0 `this_median' `h' `this_median', color(green) ///
					xtitle(`hh_income_label') ///
					text(`h' `li_benchmark_`counter'' "`share_li_`counter'' below the benchmark", place(`placement')) ///
					name("detailed_`counter'")

					if "`save_graph_as'" != "" {
						graph export "`save_graph_as' detailed `group_label'.png", as(png) width(1000) replace
					}
				}


				local counter = `counter'+1
			}

			qui: sum `temp_hh_income' if  `touse' & `grouping_var' !=. , det
			local Note = "N = `r(N)'"
			local Note = "`Note', bin size = `w_2'"
			local this_mean = `r(mean)'
			local this_median = `r(p50)'

			qui: sum `temp_bm_not_achieved' if  `touse' & `grouping_var' !=.
			local share_li = round((`r(mean)')*100,0.1)
			local share_li_`counter' = ustrleft(string(`share_li'),4) + "%"

			qui: sum `li_benchmark' if  `touse'  & `grouping_var' !=.
			local li_benchmark_`counter' = round(`r(mean)',1)

			if "`show_detailed_graph'" !="" | {

				gettoken this_color all_colors: all_colors, parse("|")
				if "`this_color'" == "|" {
					gettoken this_color all_colors: all_colors, parse("|")
				}

				capture graph drop "detailed_all_groups"
				line `temp_y' `temp_x', color(`this_color') recast(area) ///
				ytitle("`ytitle'") `ticks_x' `ticks_y'  xlabel(, labsize(small)) note("`Note'") graphregion(color(white)) ///
				legend(label( 1 "All groups") label(2 "`label_benchmark'") label(3 "mean") label(4 "median"))  || ///
				pci 0 `li_benchmark_`counter'' `h' `li_benchmark_`counter'', color(red) || ///
				pci 0 `this_mean' `h' `this_mean', color(blue) || ///
				pci 0 `this_median' `h' `this_median', color(green) ///
				xtitle(`hh_income_label') ///
				text(`h' `li_benchmark_`counter'' "`share_li_`counter'' below the benchmark", place(`placement')) ///
				name("detailed_all_groups")

				if "`save_graph_as'" != "" {
					graph export "`save_graph_as' detailed all groups.png", as(png) width(1000) replace
				}
			}
		}
		else {

			local counter = 1
			qui: sum `temp_hh_income' if  `touse', det
			local Note = "N = `r(N)'"
			local Note = "`Note', bin size = `w_2'"
			local this_mean = `r(mean)'
			local this_median = `r(p50)'

			qui: sum `temp_bm_not_achieved' if  `touse'
			local share_li = round((`r(mean)')*100,0.1)
			local share_li_`counter' = ustrleft(string(`share_li'),4) + "%"

			qui: sum `li_benchmark' if  `touse'
			local li_benchmark_`counter' = round(`r(mean)',1)

			if "`show_detailed_graph'" !="" | {

				gettoken this_color all_colors: all_colors, parse("|")
				if "`this_color'" == "|" {
					gettoken this_color all_colors: all_colors, parse("|")
				}

				capture graph drop "detailed"
				line `temp_y' `temp_x', color(`this_color') recast(area) ///
				ytitle("`ytitle'") `ticks_x' `ticks_y'  xlabel(, labsize(small)) note("`Note'") graphregion(color(white)) ///
				legend(label( 1 "All") label(2 "`label_benchmark'") label(3 "mean") label(4 "median"))  || ///
				pci 0 `li_benchmark_`counter'' `h' `li_benchmark_`counter'', color(red) || ///
				pci 0 `this_mean' `h' `this_mean', color(blue) || ///
				pci 0 `this_median' `h' `this_median', color(green) ///
				xtitle(`hh_income_label') ///
				text(`h' `li_benchmark_`counter'' "`share_li_`counter'' below the benchmark", place(`placement')) ///
				name("detailed")

				if "`save_graph_as'" != "" {
					graph export "`save_graph_as' detailed.png", as(png) width(1000) replace
				}
			}

		}


		if "`show_distribution_graph'" !="" | {
			** All together
			** Decide on the heights, ordering by benchmark value:
			if "`grouping_var'" !="" {
				tempvar temp_order_height temp_order_height_counter current_sort
				local counter = 1
				qui: gen `temp_order_height' = .
				qui: gen `temp_order_height_counter' = .
				foreach group in `group_levels' {

					qui: replace `temp_order_height' =  `li_benchmark_`counter'' in `counter'
					qui: replace `temp_order_height_counter' =  `counter' in `counter'
					local counter = `counter'+1

				}

				gen `current_sort' = [_n]
				sort `temp_order_height'

				local counter = 1
				foreach group in `group_levels' {

					if `counter' == 1 {
						local this_counter = `temp_order_height_counter'[`counter']
						local h_`this_counter'  = `h'

					}
					else {
						local this_counter = `temp_order_height_counter'[`counter']
						local previous_counter = `temp_order_height_counter'[`counter'-1]
						local h_`this_counter'  = `h_`previous_counter'' - `spacing'
					}

					local counter = `counter'+1

				}

				sort `current_sort'
			}
			else {
				local h_1 = `h'
			}

			local all_colors = "`colors'"
			if "`grouping_var'" !="" {
					local group_bm_line = ""
					local group_bm_box = ""
					local counter = 1
					foreach group in `group_levels' {

						local group_label: label (`grouping_var') `group'

						gettoken this_color all_colors: all_colors, parse("|")
						if "`this_color'" == "|" {
							gettoken this_color all_colors: all_colors, parse("|")
						}
						local group_bm_line = "`group_bm_line' || pci 0 `li_benchmark_`counter'' `h_`counter'' `li_benchmark_`counter'', color(`this_color')"
						local group_bm_box = `"`group_bm_box' text(`h_`counter'' `li_benchmark_`counter'' "`label_benchmark' `group_label': `share_li_`counter'' below", size(small)  place(`placement') box margin(1 1 1 1) fcolor(`this_color'))"'

						local counter = `counter'+1



				}
			}
			else {
				gettoken this_color all_colors: all_colors, parse("|")
				local group_bm_line = " || pci 0 `li_benchmark_1' `h_1' `li_benchmark_1', color(`this_color')"
		        local group_bm_box = `" text(`h_1' `li_benchmark_1' "`label_benchmark': `share_li_1' below", size(small)  place(`placement') box margin(1 1 1 1) fcolor(`this_color'))"'
			}


			capture graph drop "all_combined"
			line `temp_y' `temp_x',   ///
			ytitle("`ytitle'") `ticks_x' `ticks_y'  xtitle(`hh_income_label') ///
			xlabel(, labsize(small)) note(`Note_full') graphregion(color(white)) ///
			legend(`labels_cmd') ///
			`group_graph' ///
			`group_bm_line' ///
			`group_bm_box' ///
			name("all_combined")

			* save graph *
			if "`save_graph_as'" != "" {
				graph export "`save_graph_as' distribution.png", as(png) width(1000) replace
			}
		}

	}

	if "`show_bar_graph'" !="" {

		local this_ylabel = " ylabel(0(10)100, grid)"

		if "`grouping_var'" !="" {
			local this_over = ", over(`grouping_var')"
			local Note_full = ""

			* Append group information:
			if "`grouping_var'" !="" {

				foreach group in `group_levels' {
					qui: sum `temp_hh_income' if  `grouping_var' == `group' & `touse'
					local group_label: label (`grouping_var') `group'
					local Note_full= `"`Note_full' "N (`group_label') = `r(N)'""'
				}
			}
		}
		else {
			local this_over = ", "
			qui: sum `temp_hh_income' if `touse'
			local Note_full = `""N = `r(N)'""'
		}

		tempvar temp_bm_not_achieved_pct
		qui: gen `temp_bm_not_achieved_pct' = `temp_bm_not_achieved'*100

		local this_title = "Share of observations below the `label_benchmark'"
		if "`food_value'" !="" {
			local this_title = `" "`this_title'" "`label_food_value'" "'
		}


		graph bar (mean)  `temp_bm_not_achieved_pct' if `touse'  `this_over' ///
		stack legend(label(1 "Share of observations below the `label_benchmark'")) ///
		ytitle("`ytitle'") `this_ylabel' ///
		bar(1, color("red")) ///
		blabel(bar, format(%9.0f) position(center) ) ///
		graphregion(color(white)) bgcolor(white) ///
		title(`this_title', size(medium)) ///
		note(`Note_full')


		if "`save_graph_as'" != "" {
			graph export "`save_graph_as' bar.png", as(png) width(1000) replace
		}


	}
	***************************************************
	* display table with results (and store in r-class)

	local txt_spacing = 35
	local txt_spacing = max(`txt_spacing', strlen("Below the `label_benchmark': "))

	display in b _newline
	display in b "Share of observations below the `label_benchmark'"
	if "`food_value'" !="" {
		display in b "`label_food_value'"
	}

	if "`grouping_var'" !="" { // show per group, than total
		return local grouping_var = "`grouping_var'"

		** per groups
		foreach group in `group_levels' {

			local group_label: label (`grouping_var') `group'

			qui: sum `temp_bm_not_achieved' if `grouping_var' == `group' & `touse'
			local share_li = `r(mean)'*100
			return scalar share_below_`group' = `share_li'
			return scalar N_`group' = `r(N)'
			display in b ""
			display in b "`group_label'"
			display in b "n = `r(N)'"
			display in b ""
			display as text %`txt_spacing's "Below the `label_benchmark': " /*
				*/ as result /*
				*/ %9.1f `share_li' "%"
			di as text "{hline 73}"
		}

		** all groups together
		qui: sum `temp_bm_not_achieved' if `grouping_var' != . & `touse'
		local share_li = `r(mean)'*100
		return scalar share_below = `share_li'
		return scalar N = `r(N)'
		display in b ""
		display in b "All groups"
		display in b "n = `r(N)'"
		display in b ""
		display as text %`txt_spacing's "Below the `label_benchmark': " /*
			*/ as result /*
			*/ %9.1f `share_li' "%"
		di as text "{hline 73}"
	}
	else { // no groups

		qui: sum `temp_bm_not_achieved' if  `touse'
		local share_li = `r(mean)'*100
		return scalar share_below = `share_li'
		return scalar N = `r(N)'
		display in b ""
		display in b "n = `r(N)'"
		display in b ""
		display as text %`txt_spacing's "Below the `label_benchmark': " /*
			*/ as result /*
			*/ %9.1f `share_li' "%"
		di as text "{hline 73}"
	}

end