*! NJC 1.0.0 26 Feb 2007 program hsmode, rclass byable(recall) version 9 syntax varlist(numeric) [if] [in] [, Name(int 32) Spaces(int 2) /// Format(str) BY(varname) Generate(str) ALLobs MISSing ] quietly { // what observations to use if "`allobs'" != "" marksample touse, novarlist else marksample touse if "`by'" != "" & "`missing'" == "" markout `touse' `by', strok count if `touse' if r(N) == 0 error 2000 // variable(s) or group(s) local nv : word count `varlist' // generate() option if "`generate'" != "" { if `nv' > 1 { di as err /// "generate() cannot be combined with `nv' variables" exit 198 } if _by() { di as err /// "generate() cannot be combined with by: : use by() option" exit 198 } confirm new var `generate' generate double `generate' = . } // by option if "`by'" != "" { if `nv' > 1 { di as err /// "by() cannot be combined with `nv' variables" exit 198 } tempname stub separate `varlist' if `touse', /// by(`by') g(`stub') veryshortlabel `missing' local varlist "`r(varlist)'" } if "`by'`allobs'" == "" { noi di _n as txt "(n = " as res r(N) as txt ")" } else noi di " " // display preparation and initiation local nam = 0 foreach v of local varlist { if "`by'" != "" { local nam = max(`nam', length(`"`: variable label `v''"')) } else local nam = max(`nam', length("`v'")) } local col = min(`name', `nam') + 1 if "`format'" == "" local format "%8.2g" local ndigits : subinstr local format "%" "" local ndigits : subinstr local ndigits "0" "" local ndigits : subinstr local ndigits "-" "" local ndigits = substr("`ndigits'", 1, 1) if "`ndigits'" == "d" { local ndigits = 9 local ldigits = 6 local lfmt "%6.0f" } else if `ndigits' < 6 { local fmt "`format'" local format : subinstr local format "`ndigits'" "6" noi di as txt "(note: format `fmt' changed to `format')" local ndigits = 6 } if "`ldigits'" == "" local ldigits = `ndigits' if "`lfmt'" == "" local lfmt "`format'" local sp "{space `spaces'}" local SP : di _dup(`spaces') " " if "`by'`allobs'" != "" local N : di %6s "n`SP'" noi di as txt "{col `col'}`sp'`N'`sp' mode" local line = `col' - 1 + 2 * `spaces' + length("`N' mode") noi di "{hline `line'}" tempvar thisuse gen byte `thisuse' = . // loop over variables (-separate- results if -by()-) foreach v of local varlist { local which = cond("`by'" != "", `"`: variable label `v''"', "`v'") replace `thisuse' = `touse' & `v' < . count if `thisuse' local n = r(N) mata : hs_mode("`v'", "`thisuse'") if "`by'`allobs'" != "" local nshow : di %6s "`n'`SP'" noi di as text `"`which'{col `col'}"' "`sp'" /// as res "`nshow'" /// as res `format' r(hsmode) // generate? if "`generate'" != "" { replace `generate' = r(hsmode) if `thisuse' } // leaves only last-calculated in memory return scalar hsmode = r(hsmode) return scalar N = `n' } } end mata : void hs_mode(string scalar varname, string scalar tousename) { real colvector y real scalar n, mode y = st_data(., varname, tousename) n = rows(y) if (n <= 3) { mode = report(y) } else { real matrix diff real scalar n2, i1, i2, nties i1 = 1 _sort(y, 1) while (n > 3) { n2 = floor(n/2) n1 = n - n2 i2 = i1 + n2 diff = y[i2 .. (i2 + n1 - 1)] - y[i1 .. (i1 + n1 - 1)] diff = diff, (i1 .. (i1 + n1 - 1))' _sort(diff, (1,2)) nties = colsum(diff[,1] :== diff[1,1]) i1 = diff[ceil(nties / 2), 2] n = n1 } mode = report(y[i1 .. (i1 + n1 - 1)]) } st_numscalar("r(hsmode)", mode) } real report(real colvector y) { if (rows(y) == 1) { return(y[1]) } else if (rows(y) == 2) { return((y[1] + y[2]) / 2) } else if (rows(y) == 3) { _sort(y, 1) if ((y[2] - y[1]) < (y[3] - y[2])) { return((y[1] + y[2]) / 2) } else if ((y[2] - y[1]) > (y[3] - y[2])) { return((y[3] + y[2]) / 2) } else return(y[2]) } } end