*! v2.0.0, 2020-04-21, Philippe Van Kerm, module to compute the 'adjusted' fractional rank from any variable * alternative, faster calculation (without -cumul-); allow all weights * v1.3.0, 2010-02-05, Philippe Van Kerm, module to compute the 'adjusted' fractional rank from any variable * allow time-series operators * v1.2.0, 2009-09-14, Philippe Van Kerm, module to compute the 'adjusted' fractional rank from any variable * add normalization of aweights * v1.0.1, 2007-11-19, Philippe Van Kerm, module to compute the 'adjusted' fractional rank from any variable * v1.0.0, 2007-02-07, Philippe Van Kerm, module to compute the 'adjusted' fractional rank from any variable * Alternative to -cumul, gen(p)- when one wants to compute normalized ranks for later usage (e.g. for S-gini or * concentration coefficient estimation). Adjusted fractional ranks ensure that the average fractional * rank is equal to 0.5 and is independent on sort order (all tied values end up with the same rank (averaged)). program define fracrank , rclass sortpreserve version 8.2 syntax varname(ts) [if] [in] [fweight aweight pweight iweight] , Generate(string) [OLDalgo] if ("`generate'"!="") { _my_parse_genvar generate `generate' if (`:word count `generate'' != 1 ) { di as error "option generate() invalid" exit 198 } } loc w "`weight'`exp'" marksample touse gettoken eq wexp : exp , parse(=) if ("`wexp'"=="") loc wexp 1 // normalize weights to 1 if ("`weight'"!="") { tempvar ww qui gen double `ww' = `wexp' if `touse' qui su `ww' if `touse' , meanonly qui replace `ww' = `ww'/r(mean) loc wexp `ww' } quietly { if ("`oldalgo'"=="") { /* FASTER ALTERNATIVE: */ tempvar wvar svar cusum gen double `wvar' = `wexp' if `touse' // it needs a variable gen double `svar' = `varlist' if `touse' sort `touse' `svar' `wvar' gen double `cusum' = sum(`wvar'*`touse') if `touse' loc N = `cusum'[_N] by `touse' `svar' : gen double `generate' = 0.5 * (`cusum'[_N] + `cusum'[1] - `wvar'[1])/`N' if `touse' } else { /* OLDER ALGO: */ if (inlist("`weight'","pweight","iweight")) { di as error "oldalgo is not compatible with pweight or iweight" exit 198 } tempvar svar padj sumw sumwp qui gen double `svar' = `varlist' if `touse' // to deal with ts operators not allowed by cumul // 0. get raw cumulative rank cumul `svar' [`w'] if `touse' , gen(`generate') // 1. use 'adjusted ranks' padj[i] = sum(w[1]::w[i]) - w[i]/2 // to ensure that expected adjusted rank = 0.5 sort `generate' gen `padj' = max(0,`generate'[_n-1]) + ( (( `generate' - max(0,`generate'[_n-1]))/2 ) ) if `touse' // 2. take average padj within all tied values of sortvar (relevant for use with concentration indices) gen `sumw' = . gen `sumwp' = . bys `svar' `touse' : replace `sumw' = sum(`wexp') if `touse' bys `svar' `touse' : replace `sumwp' = sum(`wexp'*`padj') if `touse' bys `svar' `touse' : replace `generate' = `sumwp'[_N]/`sumw'[_N] if `touse' } } end program define _my_parse_genvar version 8.2 gettoken locname 0 : 0 gettoken genvar genopts : 0 , parse(",") gettoken comma genopts : genopts , parse(",") if (trim("`genopts'")=="") confirm new variable `genvar' else { if (trim("`genopts'")=="replace") cap drop `genvar' else { di as error "`0' invalid" exit 198 } } c_local `locname' "`genvar'" end exit