*! version 1.0.1 27 Apr 1995 (STB-25: sg38) program define mkquant version 4.0 local varlist "req ex max(1)" local if "opt" local in "opt" local weight "aweight fweight" local options "Genq(string) GENP(string) Number(int 100)" parse "`*'" if "`genq'" == "" { di in red "genq(newvar) required" exit 100 } confirm new variable `genq' if "`genp'" ~= "" { confirm new variable `genp' } local x "`varlist'" local max = `number' + 1 local old_N = _N if `max' > _N { *di in blu "number of observations will be reset to `max'" *di in blu "Press any key to continue, or Break to abort" *more set obs `max' } capture { tempvar doit n p y k i q pp mark `doit' `if' `in' [`weight'`exp'] markout `doit' `x' * Save original ordering. gen long `n' = _n * Sort. sort `doit' `x' * Compute sum of weights. summarize `doit' [`weight'`exp'] if `doit' if "`weight'" ~= "" { local exp = substr("`exp'",2,.) } else local exp = 1 * `p'/`number' = F(`x'), where F is empirical distribution function. gen double `p' = (`number'/_result(2))*sum(`exp') if `doit' * If `p' is an integer, then quantile = (`x' + `x'[_n+1])/2. * So save `x'[_n+1] if `p' is an integer. gen double `y' = `x'[_n+1] if abs(`p'-round(`p',1))<1e-7 /* */ & _n < _N & `doit' * Compute integer floor of `p'. replace `p' = cond(abs(`p'-round(`p',1))<1e-7, /* */ round(`p',1),int(`p')) + 1 if `doit' * The first occurrence of each unique value of `p' gives the * desired quantiles. gen long `k' = `p' if `p' ~= `p'[_n-1] & `doit' * Order `k' and, if necessary, fill in skipped-over quantiles. sort `k' summarize `k' in 1/`max' * Create `i' such that `k'[`i'] == `max'-_n+1 with lagged values. gen long `i' = _result(1) in 1 replace `i' = cond(`k'[`i'[_n-1]-1]==`max'-_n+1, /* */ `i'[_n-1]-1, `i'[_n-1]) in 2/`max' * Flip back. replace `k' = `i'[`max'-_n+1] in 1/`max' * Compute quantiles. replace `p' = cond(`y'[`k']~=. & `k'~=`k'[_n+1], /* */ (`x'[`k']+`y'[`k'])/2, `x'[`k']) in 1/`max' drop `y' `k' `i' * Reorder `p' so that after sorting by `n', `p' is in proper order. local type : type `x' if "`type'" ~= "double" { local type "float" } gen `type' `q' = cond(`n' <= `max', `p'[`n'], .) * Restore original ordering. sort `n' if "`genp'" ~= "" { gen float `pp' = cond(_n <= `max', (_n-1)/`number', .) } } if _rc { local rc = _rc if _N > `old_N' { quietly drop if _n > `old_N' } error `rc' } if "`genp'" ~= "" { rename `pp' `genp' label variable `genp' "Probability points for quantiles" } rename `q' `genq' label variable `genq' "Quantiles of `x'" end