*! 2.1 UK/NJC 14 Jan 2019
*! _gxtile version 2.0 UK 28 AUG 2016
*! Categorizes exp by its quantiles - byable

* Version history
// 2.0: Use levelsof instead of levels
// 1.2: Bug: Opt percentiles were treated incorrectely after implement. of option nq
//	   Allows By-Variables that are strings
// 1.1: Bug: weights are treated incorectelly in version 1.0. -> fixed
//     New option nquantiles() implemented
// 1.0: initial version

* Main program
program _gxtile, byable(onecall) sortpreserve
	version 8.2

** Syntax
	gettoken type 0 : 0
	gettoken h    0 : 0
	gettoken eqs  0 : 0

	syntax varname(numeric) [if] [in] [, ///
	  Percentiles(string) ///
	  Nquantiles(string) ///
	  Weights(string) ALTdef by(varlist) ]

	marksample touse

** Error Checks

	if "`altdef'" ~= "" & "`weights'" ~= "" {
		di as error "weights are not allowed with altdef"
		exit 111
	}

	if "`percentiles'" != "" & "`nquantiles'" != "" {
		di as error "do not specify percentiles and nquantiles"
		exit 198
	}

** Default Settings etc.

	if "`weights'" ~= "" {
		local weight "[aw = `weights']"
	}

	if "`percentiles'" != "" {
		local pctopt percentiles(`percentiles')
		local pct "`percentiles'"
	}

	else if "`nquantiles'" != "" 	{
		local pctopt nquantiles(`nquantiles')
		local pct "1/`=`nquantiles'-1'"
	}

	else if "`nquantiles'" == "" & "`percentiles'" == "" 	{
		local pctoption percentiles(50)
		local pct "1/2"
	}

	quietly {

		gen `type' `h' = .

*** Without by

		if "`by'"=="" {

			local i 1
			_pctile `varlist' `weight' if `touse', `pctopt' `altdef'
			foreach p of numlist `pct' {
				if `i' == 1 {
					replace `h' = `i' if `varlist' <= r(r`i') & `touse'
				}
				replace `h' = `++i' if `varlist' > r(r`--i')  & `touse'
				local i = `i' + 1
			}
			exit
		}

*** With by

		tempvar byvar
		by `touse' `by', sort: gen `byvar' = 1 if _n==1 & `touse'
		by `touse' (`by'): replace `byvar' = sum(`byvar')

		sum `byvar', meanonly
		forval k = 1/`r(max)' {
			local i 1
			_pctile `varlist' `weight' if `byvar' == `k' & `touse' , `pctopt' `altdef'
			foreach p of numlist `pct'  {
				if `i' == 1 {
					replace `h' = `i' if `varlist' <= r(r`i') & `byvar' == `k' & `touse'
				}
				replace `h' = `++i' if `varlist' > r(r`--i')  & `byvar' == `k' & `touse'
				local i = `i' + 1
				}
		}
	}

end
exit