*! 2.2.0 SPJ March 2024. Change from using -gsort- (speedup suggested Caspar Kaiser)
*! 2.1.0 SPJ Feb 2021 Add pweight so that use PVK's -rhsbsample- & svy bootstrap
*! 2.0.2 SPJ May 2008 (fix bug arising if bygroup() and `touse' lead to no obs in a group)
*!   bug fix method provided by Austin Nichols (many thanks!)
*! 2.0.1 SPJ August 2006 (new vbles created as doubles)
*! 2.0.0 SPJ August 2006 (port to Stata 8.2; additional saved results),
*!   with initial code rewriting contribution from Nick Cox (many thanks!)
*! version 1.6 April 2001 (made compatible with Stata 7; SSC)
*! version 1.0.1 Stephen P. Jenkins, April 1998   STB-48 sg104
*! Inequality indices, with optional decomposition by population subgroups

program ineqdeco, sortpreserve rclass

version 8.2
syntax varname(numeric) [aweight fweight pweight iweight] [if] [in] ///
	[, BYgroup(varname numeric) Welfare Summarize ]

if "`summarize'" != "" local summ "summ"
if "`welfare'" != ""    local w "w"
local inc "`varlist'"

tempvar fi totaly py gini wgini im1 i0 i1 i2                 	///
  nk vk fik meanyk varyk lambdak loglamk lgmeank             	///
  thetak im1k i0k i1k i2k  ginik pyk                         	///
  im1b i0b i1b i2b  wginik                              	///
  ahalf a1 a2 ahalfk a1k a2k 				      	///
  whalf w1 w2 whalfk w1k w2k                                 	///
  ahalfb a1b a2b edehalfk ede1k ede2k          			///
  edehalf ede1 ede2 withm1 with0 withh with1 with2 	     	///
  awithh awith1 awith2 wi first


if "`weight'" == "" gen byte `wi' = 1
else gen `wi' `exp'

marksample touse
if "`bygroup'" != "" markout `touse' `bygroup'

qui count if `touse'
if r(N) == 0 error 2000

lab var `touse' "All obs"
lab def `touse' 1 " "
lab val `touse' `touse'

if "`bygroup'" != "" {
	capture levelsof `bygroup' if `touse' , local(gp)
	qui if _rc levels `bygroup' if `touse' , local(gp)
	foreach x of local gp {
		if int(`x') != `x' | (`x' < 0) {
			di as error "`bygroup' contains non-integer or negative values"
			exit 459
		}
	}
}

set more off

quietly {

	count if `inc' < 0 & `touse'
	noi if r(N) > 0 {
		di " "
		di as txt "Warning: `inc' has `r(N)' values < 0." _c
		di as txt " Not used in calculations"
	}

	count if `inc' == 0 & `touse'
	noi if r(N) > 0 {
		di " "
		di as txt "Warning: `inc' has `r(N)' values = 0." _c
		di as txt " Not used in calculations"
	}

	replace `touse' = 0 if `inc' <= 0  // this replaces former 'badinc' stuff

	noi if "`summ'" != "" {
		di " "
		di as txt "Summary statistics for distribution of " _c
		di as txt "`inc'" ": all valid cases"
		sum `inc' [w = `wi'] if `touse', de
	}
	else  sum `inc' [w = `wi'] if `touse', de

	foreach P in 5 10 25 50 75 90 95 {
		local p`P'  = r(p`P')
	}

	local sumwi = r(sum_w)
	local meany = r(mean)
	local vary = r(Var)
	local sdy = r(sd)

	return scalar mean = r(mean)
	return scalar Var = r(Var)
	return scalar sd = r(sd)
	return scalar sumw = r(sum_w)
	return scalar N = r(N)
	return scalar min = r(min)
	return scalar max = r(max)

	foreach p in 5 10 25 50 75 90 95 {
		return scalar p`p' = r(p`p')
	}
	gen double `fi' = `wi' / `sumwi' if `touse'

	tempvar notuse 					// was: gsort -`touse' `inc'
	gen  byte `notuse' = -`touse'
	sort  `notuse'  `inc'

	gen double `py' = (2 * sum(`wi') - `wi' + 1)/(2 * `sumwi' ) if `touse'

	egen double `gini' = sum(`fi'*(2 / `meany') * `py' * (`inc' - `meany')) if `touse'
	egen double `im1' = sum(`fi' * ((`meany' / `inc') - 1) / 2) if `touse'
	egen double `i0' = sum(`fi' * log(`meany' / `inc')) if `touse'
	egen double `i1' = sum(`fi' * (`inc' / `meany') * log(`inc' / `meany')) if `touse'
	egen double `i2' = sum(`fi' * (((`inc' / `meany')^2) - 1) / 2) if `touse'

	gen double `wgini' = `meany' * (1 - `gini') if `touse'

	lab var `gini' "Gini"
	lab var `im1' "GE(-1)"
	lab var `i0' "GE(0)"
	lab var `i1' "GE(1)"
	lab var `i2' "GE(2)"

	tempvar v9010 v9050 v1050 v7525
	gen `v9010' = `p90'/`p10' in 1
	gen `v9050' = `p90'/`p50' in 1
	gen `v1050' = `p10'/`p50' in 1
	gen `v7525' = `p75'/`p25' in 1
	lab var `v9010' "p90/p10"
	lab var `v9050' "p90/p50"
	lab var `v1050' "p10/p50"
	lab var `v7525' "p75/p25"


	noi {
		di " "
		di as txt "Percentile ratios"
		tabdisp `touse' in 1, c(`v9010' `v9050' `v1050' `v7525') f(%9.3f)

		global S_9010 = `p90'/`p10'
		global S_7525 = `p75'/`p25'
		return scalar p90p10 = `p90'/`p10'
		return scalar p75p25 = `p75'/`p25'
		return scalar p90p50 = `p90'/`p50'
 		return scalar p10p50 = `p10'/`p50'
		return scalar p25p50 = `p25'/`p50'
		return scalar p75p50 = `p75'/`p50'

		di "  "
		di as txt "Generalized Entropy indices GE(a), where a = income difference"
		di as txt " sensitivity parameter, and Gini coefficient"
		tabdisp `touse' in 1, c(`im1' `i0' `i1' `i2' `gini') f(%9.5f)
	}

	// saved results compatible with previous versions of -ineqdeco-
	global S_gini = `gini'[1]
	global S_im1 = `im1'[1]
	global S_i0 = `i0'[1]
	global S_i1 = `i1'[1]
	global S_i2 = `i2'[1]

	return scalar gini = `gini'[1]
	return scalar gem1 = `im1'[1]
	return scalar ge0 = `i0'[1]
	return scalar ge1 = `i1'[1]
	return scalar ge2 = `i2'[1]

	drop `gini' `im1' `i0' `i1' `i2'

	egen double `edehalf' = sum(`fi' * sqrt(`inc') )  if `touse'
	replace `edehalf' = (`edehalf')^2 if `touse'
	gen double `ahalf' = 1 - `edehalf' / `meany'  if `touse'
	egen double `ede1' = sum(`fi' * log(`inc') ) if `touse'
	replace `ede1' = exp(`ede1')  if `touse'
	gen double `a1' = 1 - `ede1' / `meany'  if `touse'
	egen double `ede2' = sum(`fi' / `inc' )  if `touse'
	replace `ede2' = 1 / `ede2' if `touse'
	gen double `a2' = 1 - `ede2' / `meany'  if `touse'

	lab var `ahalf' "A(0.5)"
	lab var `a1' "A(1)"
	lab var `a2' "A(2)"

	noi {
		di "   "
		di as txt "Atkinson indices, A(e), where e > 0 is " _c
		di as txt "the inequality aversion parameter"
		tabdisp `touse' if `touse', c(`ahalf' `a1' `a2') f(%9.5f)
	}

	global S_ahalf = `ahalf'[1]
	global S_a1 = `a1'[1]
	global S_a2 = `a2'[1]

	return scalar ahalf = `ahalf'[1]
	return scalar a1 = `a1'[1]
	return scalar a2 = `a2'[1]

	drop `ahalf' `a1' `a2'

	// results for Yede, welfare indices if requested:

	if "`w'" == "w" {

		lab var `edehalf' "Yede(0.5)"
		lab var `ede1' "Yede(1)"
		lab var `ede2' "Yede(2)"

		noi {
			di "   "
			di as txt "Equally-distributed-equivalent incomes, Yede(e)"
			tabdisp `touse' in 1, c(`edehalf' `ede1' `ede2') f(%15.5f)
			di "   "
		}

		return scalar edehalf = `edehalf'[1]
		return scalar ede1 = `ede1'[1]
		return scalar ede2 = `ede2'[1]


		// Don't drop `edehalf' `ede1' `ede2' yet: needed in decomp

		egen double `whalf' = sum(`fi' * sqrt(`inc') * 2) if `touse'
		egen double `w1' = sum(`fi' * log(`inc') ) if `touse'
		egen double `w2' = sum(-`fi'/`inc') if `touse'
		lab var `whalf' "W(0.5)"
		lab var `w1' "W(1)"
		lab var `w2' "W(2)"
		lab var `wgini' "mean*(1-Gini)"

		noi {
			di as txt "Social welfare indices, W(e), and Sen's welfare index"
			tabdisp `touse' in 1, c(`whalf' `w1' `w2' `wgini') f(%15.5f)
		}


		return scalar whalf = `whalf'[1]
		return scalar w1 = `w1'[1]
		return scalar w2 = `w2'[1]
		return scalar wgini = `wgini'[1]


		drop `whalf' `w1' `w2'

	}

*************************
* SUBGROUP DECOMPOSITIONS
*************************

if "`bygroup'" != "" {

	qui {
		tempvar notuse
        	gen byte `notuse' = -`touse'
		sort `notuse' `bygroup' `inc'

		by `notuse' `bygroup': gen byte `first' = _n == 1 if `touse'
		by `notuse' `bygroup': egen double `nk' = sum(`wi') if `touse'

		gen double `vk' = `nk' / `sumwi' if `touse'
	  	gen double `fik' = `wi' / `nk' if `touse'
		by `notuse' `bygroup': egen double `meanyk' = sum(`fik' * `inc') if `touse'
		by `notuse' `bygroup': egen double `varyk' = sum(`fik'* (`inc' - `meanyk')^2) if `touse'
		gen double `loglamk' = log(`meanyk') if `touse'
		gen double `lambdak' = `meanyk' / `meany' if `touse'
		gen double `lgmeank' = log(`meanyk') if `touse'
		gen double `thetak' = `vk' * `lambdak' if `touse'
		by `notuse' `bygroup': egen double `im1k' = sum(`fik' * ((`meanyk' / `inc') - 1) / 2) if `touse'
		by `notuse' `bygroup': egen double `i0k' = sum(`fik' * log(`meanyk' / `inc')) if `touse'
		by `notuse' `bygroup': egen double `i1k' = sum(`fik' * (`inc' / `meanyk') * log(`inc' / `meanyk')) if `touse'
		by `notuse' `bygroup': egen double `i2k' = sum(`fik' * (((`inc' / `meanyk')^2) - 1) / 2) if `touse'

	}

	noi {
		di "  "
		di as txt "Subgroup summary statistics, for each subgroup k = 1,...,K:"
		if "`summ'" != "" {
			bys `bygroup': sum `inc' [w = `wi'] if `touse', de
		}
	}

	bysort `notuse' `bygroup' (`inc'): gen double `pyk' = (2 * sum(`wi') - `wi' + 1) / (2 * `nk' ) ///
		if `touse'

	by `notuse' `bygroup': egen double `ginik' = sum(`fik' * (2 / `meanyk') * `pyk' * (`inc' - `meanyk')) ///
		if `touse'

	gen double `wginik' = `meanyk' * (1 - `ginik') if `touse'

	lab var `vk' "Popn. share"
	lab var `meanyk' "Mean"
	lab var `lambdak' "Relative mean"
	lab var `thetak' "Income share"
	lab var `lgmeank' "log(mean)"
	lab var `ginik' "Gini"
	lab var `im1k' "GE(-1)"
	lab var `i0k' "GE(0)"
	lab var `i1k' "GE(1)"
	lab var `i2k' "GE(2)"
	lab var `wginik' "mean*(1-Gini)"

	noi {
		di "  "
		tabdisp `bygroup' if `first' , c(`vk' `meanyk' `lambdak' `thetak' `lgmeank') f(%15.5f)

		di "  "
		di as txt "Subgroup indices: GE_k(a) and Gini_k "
		tabdisp `bygroup' if `first' , c(`im1k' `i0k' `i1k' `i2k' `ginik')  f(%9.5f)
	}


	capture levelsof `bygroup' if `touse' , local(group)
	qui if _rc levels `bygroup' if `touse' , local(group)

	return local levels "`group'"

	tempvar firsts 				// was: gsort -`first' `bygroup'
	gen byte `firsts' = - `first'
	sort `firsts' `bygroup'

	local i = 1
	foreach k of local group	{
		return scalar gem1_`k' = `im1k'[`i']
		return scalar ge0_`k' = `i0k'[`i']
		return scalar ge1_`k' = `i1k'[`i']
		return scalar ge2_`k' = `i2k'[`i']
		return scalar gini_`k' = `ginik'[`i']

		return scalar mean_`k' = `meanyk'[`i']
		return scalar lgmean_`k' = `lgmeank'[`i']
		return scalar theta_`k' = `thetak'[`i']
		return scalar lambda_`k' = `lambdak'[`i']
		return scalar v_`k' = `vk'[`i']
		return scalar sumw_`k' = `nk'[`i']

		local ++i
	}

	drop `lgmeank' `ginik' `thetak' `nk' `pyk'

	egen double `withm1' = sum(`fi' * `im1k' / `lambdak') if `touse'
	egen double `with0' = sum(`fi' * `i0k') if `touse'
	egen double `with1' = sum(`fi' * `i1k' * `lambdak') if `touse'
	egen double `with2' = sum(`fi' * `i2k' * `lambdak'^2) if `touse'
	lab var `withm1' "GE(-1)"
	lab var `with0' "GE(0)"
	lab var `with1' "GE(1)"
	lab var `with2' "GE(2)"

	noi {
		di "  "
		di as txt "Within-group inequality, GE_W(a)"
		tabdisp `touse' in 1 if `touse', c(`withm1' `with0' `with1' `with2')  f(%9.5f)
	}

	return scalar within_gem1 = `withm1'[1]
	return scalar within_ge0 = `with0'[1]
	return scalar within_ge1 = `with1'[1]
	return scalar within_ge2 = `with2'[1]

	drop `im1k' `i0k' `i1k' `i2k' `withm1' `with0' `with1' `with2'

	** GE index between-group inequalities **

	egen double `im1b' = sum(`fi' * ((`meany' / `meanyk') - 1) / 2 ) if `touse'
	egen double `i0b' = sum(`fi' * log(`meany' / `meanyk')) if `touse'
	egen double `i1b' = sum(`fi' * (`meanyk' / `meany') * log(`meanyk' / `meany')) ///
		if `touse'
	egen double `i2b' = sum(`fi' * (((`meanyk' / `meany')^2) - 1) / 2) if `touse'
	lab var `im1b' "GE(-1)"
	lab var `i0b' "GE(0)"
	lab var `i1b' "GE(1)"
	lab var `i2b' "GE(2)"

	noi {
		di "              "
		di as txt "Between-group inequality, GE_B(a):"
		tabdisp `touse' in 1 if `touse' , c(`im1b' `i0b' `i1b' `i2b')  f(%9.5f)
	}

	return scalar between_gem1 = `im1b'[1]
	return scalar between_ge0 = `i0b'[1]
	return scalar between_ge1 = `i1b'[1]
	return scalar between_ge2 = `i2b'[1]

	drop `im1b' `i0b' `i1b' `i2b'

	** Subgroup Atkinson and welfare indices **

	sort `notuse' `bygroup'

	by `notuse' `bygroup': egen double `edehalfk' = sum(`fik' * sqrt(`inc')) if `touse'
	replace `edehalfk' = (`edehalfk')^2 if `touse'
	gen double `ahalfk' = 1 - `edehalfk' / `meanyk' if `touse'
	by `notuse' `bygroup': egen double `ede1k' = sum(`fik' * log(`inc')) if `touse'
	replace `ede1k' = exp(`ede1k') if `touse'
	gen `a1k' = 1 - `ede1k' / `meanyk' if `touse'
	by `notuse' `bygroup': egen double `ede2k' = sum(`fik' / `inc') if `touse'
	replace `ede2k' = 1 / `ede2k' if `touse'
	gen double `a2k' = 1 - `ede2k' / `meanyk' if `touse'

	lab var `ahalfk' "A(0.5)"
	lab var `a1k' "A(1)"
	lab var `a2k' "A(2)"

	noi {
		di "              "
		di as txt "Subgroup Atkinson indices, A_k(e)"
		tabdisp `bygroup' if `first' , c(`ahalfk' `a1k' `a2k')  f(%9.5f)
	}


	egen double `awithh' = sum(`fi' * `lambdak' * `ahalfk') if `touse'
	egen double `awith1' = sum(`fi' * `lambdak' * `a1k') if `touse'
	egen double `awith2' = sum(`fi' * `lambdak' * `a2k') if `touse'
	lab var `awithh' "A(0.5)"
	lab var `awith1' "A(1)"
	lab var `awith2' "A(2)"

	noi {
		di "  "
		di as txt "Within-group inequality, A_W(e)"
		tabdisp `touse' if `touse' , c(`awithh' `awith1' `awith2')  f(%9.5f)
	}

	tempvar firsts 				// was: gsort -`first' `bygroup'
	gen byte `firsts' = - `first'
	sort `firsts' `bygroup'

	local i = 1
	foreach k of local group	{
		return scalar ahalf_`k' = `ahalfk'[`i']
		return scalar a1_`k' = `a1k'[`i']
		return scalar a2_`k' = `a2k'[`i']
		local ++i
	}

	return scalar within_ahalf = `awithh'[1]
	return scalar within_a1 = `awith1'[1]
	return scalar within_a2 = `awith2'[1]

	drop `ahalfk' `a1k' `a2k' `awithh' `awith1' `awith2' `lambdak'

	* Atkinson between-group inequality (Blackorby et al., eqn (17))

	egen double `ahalfb' = sum(`fi' * `edehalfk' )  if `touse'
	replace `ahalfb' = 1 - `edehalf' / `ahalfb' if `touse'
	egen double `a1b' = sum(`fi' * `ede1k' )  if `touse'
	replace `a1b' = 1 - `ede1' / `a1b' if `touse'
	egen double `a2b' = sum(`fi' * `ede2k' )  if `touse'
	replace `a2b' = 1 - `ede2' / `a2b' if `touse'
	lab var `ahalfb' "A(0.5)"
	lab var `a1b' "A(1)"
	lab var `a2b' "A(2)"

	noi {
		di " "
		di as txt "Between-group inequality, A_B(e)"
		tabdisp `touse' in 1 if `touse'	, c(`ahalfb' `a1b' `a2b') f(%9.5f)
	}

	return scalar between_ahalf = `ahalfb'[1]
	return scalar between_a1 = `a1b'[1]
	return scalar between_a2 = `a2b'[1]
	return scalar edehalf = `edehalf'[1]
	return scalar ede1 = `ede1'[1]
	return scalar ede2 = `ede2'[1]

	drop `ahalfb' `a1b' `a2b' `edehalf' `ede1' `ede2'

	// results for Yede, welfare indices if requested

	if "`w'" == "w" {
		lab var `edehalfk' "Yede(0.5)"
		lab var `ede1k' "Yede(1)"
		lab var `ede2k' "Yede(2)"

		noi {
			di "              "
			di as txt "Subgroup equally-distributed-equivalent income, Yede_k(e)"
			tabdisp `bygroup' if `first', c(`edehalfk' `ede1k' `ede2k')  f(%15.5f)
		}

		tempvar firsts 				// was: gsort -`first' `bygroup'
		gen byte `firsts' = - `first'
		sort `firsts' `bygroup'

		local i = 1
		foreach k of local group	{
			return scalar edehalf_`k' = `edehalfk'[`i']
			return scalar ede1_`k' = `ede1k'[`i']
			return scalar ede2_`k' = `ede2k'[`i']
			local ++i
		}

		drop `edehalfk' `ede1k' `ede2k'


		sort `notuse' `bygroup'

		by `notuse' `bygroup': egen double `whalfk' = sum(`fik' * sqrt(`inc') * 2) if `touse'
		by `notuse' `bygroup': egen double `w1k' = sum(`fik' * log(`inc') ) if `touse'
		by `notuse' `bygroup': egen double `w2k' = sum(-`fik' / `inc') if `touse'
		lab var `whalfk' "W(0.5)"
		lab var `w1k' "W(1)"
		lab var `w2k' "W(2)"

		noi {
			di "              "
			di as txt "Subgroup welfare indices: W_k(e) and Sen's index"
			tabdisp `bygroup' if `first', c(`whalfk' `w1k' `w2k' `wginik')  f(%15.5f)
		}

		tempvar firsts 				// was: gsort -`first' `bygroup'
		gen byte `firsts' = - `first'
		sort `firsts' `bygroup'

		local i = 1
		foreach k of local group	{
			return scalar whalf_`k' = `whalfk'[`i']
			return scalar w1_`k' = `w1k'[`i']
			return scalar w2_`k' = `w2k'[`i']
			return scalar wgini_`k' = `wginik'[`i']
			local ++i
		}

		drop `whalfk' `w1k' `w2k'
	}

	drop `wginik' `fi'



} 	// end of  "`bygroup'"  block for subgroup decompositions


} 	// end quietly block

end