Kindly check this code? I am trying to calculate Median Absolute Deviations. What could be done better? Any errors in logic / calculations? Is the use of global macros justifiable here? The code has been adopted from Dr. Nicholas J. Cox's moments.ado, with his kind permission.
Code:
program mads, byable(recall) version 9.1 syntax [varlist] [if] [in] [aweight fweight] /// [, Matname(str) Format(str) ALLobs variablenames by(varlist) * ] qui { ds `varlist', has(type numeric) local varlist "`r(varlist)'" if "`allobs'" != "" marksample touse, novarlist else marksample touse count if `touse' if r(N) == 0 error 2000 local nct : word count `varlist' if "`by'" != "" { if `nct' > 1 { di as err /// "by() cannot be combined with `nct' variables" exit 198 } tempvar group egen `group' = group(`by') if `touse', label su `group', meanonly local nct = r(max) } else tokenize `varlist' if `nct' > _N { preserve set obs `nct' } tempvar a id n mean SD median mad which tempname mylbl gen long `which' = _n compress `which' gen `n' = "" label var `n' "n" foreach s in mean SD median mad { gen double ``s'' = . label var ``s'' "`s'" } if "`matname'" != "" mat `matname' = J(`nct',5,0) forval i = 1/`nct' { if "`by'" != "" { su `varlist' [`weight' `exp'] /// if `touse' & `group' == `i', detail global gillid = `varlist' global gillN = r(N) } else { su ``i'' if `touse' [`weight' `exp'], detail global gillid = ``i'' global gillN = r(N) } replace `n' = string(r(N)) in `i' replace `mean' = r(mean) in `i' replace `SD' = r(sd) in `i' replace `median' = r(p50) in `i' /* here gores replace `mad'*/ tempvar devi ge `devi' = abs($gillid - `median') in `i' su `devi' in `i', de replace `mad' = r(p50) * 1.4826 in `i' if "`matname'" != "" { mat `matname'[`i',1] = $gillN mat `matname'[`i',2] = r(mean) mat `matname'[`i',3] = r(sd) mat `matname'[`i',4] = r(p50) mat `matname'[`i',5] = `mad' } if "`by'" != "" { local V = trim(`"`: label (`group') `i''"') local rownames `"`rownames' `"`V'"'"' display _newline(2) "rownames = "`rownames'"" } else { local V = trim(`"`: variable label ``i'''"') if "`variablenames'" != "" | `"`V'"' == "" { local V "``i''" } } label def `mylbl' `i' `"`V'"', modify } if "`matname'" != "" { mat colnames `matname' = n mean SD median mad if "`by'" != "" { capture mat rownames `matname' = `rownames' if _rc { numlist "1/`nct'" mat rownames `matname' = `r(numlist)' } } else mat rownames `matname' = `varlist' } label val `which' `mylbl' if "`by'" != "" label var `which' "Group" else if "`allobs'" != "" label var `which' "Variable" else label var `which' "n = $gillN" local fmt "format(%9.3f)" if "`format'" != "" { tokenize `format' if "`4'" != "" { tempvar smad gen `smad' = string(`mad', "`4'") label var `smad' "mad" local mad "`smad'" } if "`3'" != "" { tempvar smean gen `smean' = string(`mean', "`3'") label var `smean' "mean" local mean "`mean'" } if "`2'" != "" { tempvar sSD gen `sSD' = string(`SD', "`2'") label var `sSD' "SD" local SD "`sSD'" } tempvar smean gen `smean' = string(`mean', "`1'") label var `smean' "mean" local mean "`smean'" } if "`allobs'`by'" != "" local shown "`n'" } tabdisp `which' if `which' <= `nct', /// c(`shown' `mean' `SD' `median' `mad') `options' `fmt' end
Comment