// This is just a prototype program define ftab syntax varlist [if] [in] , /// [SELect(str) Order(str)] /// [Missing] /// [Verbose] loc verbose = ("`verbose'" != "") // Trim data if ("`missing'" == "") { marksample touse, strok } else if ("`if'`in'" != "") { marksample touse, strok novarlist } //tempname table mata: ftab("`varlist'", "`touse'", "`table'", `verbose') ParseSelect, select(`select') order(`order') di as error "`select'-`Select'-`Selectint'-`order'" //Display, variable(`varlist') table(`table') end program ParseSelect * Taken from groups.ado from njc (!!!) // select option syntax, [select(str) order(str)] if "`select'" != "" { if real("`select'") < . { capture confirm integer number `select' if _rc { di as inp "`select' " /// as err "invalid argument for " /// as inp "select()" exit 198 } local Selectint 1 } else { tokenize "`select'", parse(" ><=") local w "`1'" local W : subinstr local select "`w'" "" if lower(substr("`w'",1,1)) == "r" { local w = lower("`w'") } local OK 0 foreach s in freq percent Freq Percent rfreq /// rpercent vpercent Vpercent rvpercent { if "`w'" == substr("`s'",1,length("`w'")) { local OK 1 local Select "``s''" continue, break } } // selection should specify an equality or inequality qui count if 1 `W' if _rc | !`OK' { di as inp "`select' " /// as err "invalid argument for " /// as inp "select()" exit 198 } local Selectint 0 } } c_local Select `Select' c_local Selectint `Selectint' // order option if "`order'" != "" { if `: word count `order'' > 1 { di as err "invalid " as inp "order()" as err "option" exit 198 } local orderlist "h hi hig high l lo low" if !`: list order in orderlist' { di as inp "`order' " /// as err "invalid argument for " /// as inp "order()" exit 198 } local order = substr("`order'",1,1) } c_local order `order' end program define Display syntax, variable(name) table(name) tempname mytab loc label : var label `variable' loc cols : rownames `table' , quoted loc rows : colnames `table' , quoted // Raw matrix list `table', title(`label') format(%8.2g) // More detailed // TODO: WRAP HEADER di .`mytab' = ._tab.new, col(4) lmargin(2) comma .`mytab'.width 13 | 12 12 12 .`mytab'.pad . 2 2 2 .`mytab'.numfmt . %8.0g %8.0g %4.2f .`mytab'.titlefmt %12s %8s %8s %8s .`mytab'.sep, top .`mytab'.titles "`label'" `rows' // .`mytab'.row "" `table'[1, 1] `table'[1, 2] `table'[1, 3] end findfile "ftools.mata" include "`r(fn)'" mata: mata set matastrict on void ftab(`Varname' var, `String' touse, `String' mat_name, `Boolean' verbose) { `Factor' F `Vector' perc, smpl `Matrix' ans `StringMatrix' keys //`StringMatrix' rowstripe, colstripe F = factor(var, touse, verbose) smpl = F.counts :> 50 perc = F.counts :/ colsum(F.counts) :* 100 ans = F.counts, perc, runningsum(perc) //sums = runningsum(F.counts) //perc = sums :/ sums[rows(sums)] :* 100 ans = select(ans, smpl) keys = select(isreal(F.keys) ? strofreal(F.keys) : F.keys, smpl) // Sort; recycle smpl vector smpl = order(ans, -1) ans = ans[smpl, .] keys = keys[smpl] mm_matlist(ans \ (colsum(ans[., 1..2]), 100), ("%g", "%6.2f", "%6.2f"), 3, keys \ "Total", ("Freq.", "Percent", "Cum."), F.varlist) // we could use F.varlabels //st_matrix(mat_name, (F.counts, sums, perc)) //rowstripe = J(rows(F.keys), 1, ""), (isreal(F.keys) ? strofreal(F.keys) : F.keys) //colstripe = ("", "", "" \ "Freq.", "Percent", "Cum.")' //st_matrixcolstripe(mat_name, colstripe) //st_matrixrowstripe(mat_name, rowstripe) } end exit * Tests cap ado uninstall ftools net install ftools, from("C:/git/ftools/src") clear all sysuse auto //la var turn "this is a very very VERY long label" tab turn ftab turn * Benchmark