*! version 1.1.0 16mar2014 Daniel Klein /* tfv -- Transformations of variables Syntax tfv [, ] [:] [ | [ ...]] Transformations () are one of (1) t().varname (2) t.() (3) t.varname (4) t. (3) and (4) are not documented So to get the square root of varname we can code t(sqrt).varname or (2) t.(sqrt(varname)) or (3) tsqrt.varname or (4) t.sqrt(varname) Factor variable operators are specified before the t. operator tfv reg t(ln).wage c.t.(hours/100)##c.t.(hours/100) i.t.(race - 1) With syntaxes (3) and (4) even this is allowed tfv reg tln.wage c.t.hours/100##c.t.hours/100 i.t.race-1 (note no blanks in ) */ pr tfv ,sclass vers 11.2 tempname rres cap _ret hold `rres' sret loc tfvvarlist loc call : copy loc 0 // tfv command cap unabcmd `call' if !(_rc) { TfvCmd `r(cmd)' e 0 // done } // tfv options gettoken cc : call ,p(",:") if inlist(`"`cc'"', ",", ":") { if (`"`cc'"' == ",") { gettoken opts call : call ,p(":") loc 0 : copy loc opts TfvOpts `opts' } gettoken col call : call ,p(":") loc 0 : copy loc call } // set locals loc Ctfv 0 // count (new) tfv terms loc Cnam 0 // count names loc Cndt 0 // no dot in token loc exit e 0 // create transformations of variables while (`"`0'"' != "") { gettoken tok 0 : 0 ,p(" .") if (`"`tok'"' != ".") { loc bfr : copy loc tok loc ++Cndt if (`Cndt' > 1) | (`"`0'"' == "") { loc exit } continue } gettoken t bfr : bfr ,p("Tt") if (strlower(`"`t'"') != "t") continue loc Cndt 0 gettoken vn_or_xp 0 : 0 ,p(" #") m(p) if ("`p'" == "(") loc p2 ")" else loc p2 if (`"`bfr'"' != "") { // t().varname fvunab unabvarn : `vn_or_xp' gettoken fcn : bfr ,m(p) if ("`p'" == "(") loc p2 ")" loc tusr `t'`p'`fcn'`p2'.`vn_or_xp' loc expr `fcn'(`unabvarn') } else { // t.() loc tusr `t'.`p'`vn_or_xp'`p2' loc expr : copy loc vn_or_xp } // variable names loc ++Cnam loc tnam : word `Cnam' of `generate' if ("`stub'"!= "") loc tnam `stub'`Cnam' if ("`tnam'" == "") { loc tnam = strtoname(stritrim(`"`expr'"')) loc us 1 while (`us') { loc tnam : subinstr loc tnam "__" "_" /// ,all c(loc us) } loc lent : length loc tnam if (substr("`tnam'", `lent', .) == "_") { loc tnam = substr("`tnam'", 1, `lent' - 1) } } loc tusr`tnam' `"`tusr`tnam'' "`tusr'""' // substitution loc call : /// subinstr loc call `"`tusr'"' "`tnam'" ,all if (`: list tnam in tnams') continue loc ++Ctfv cap conf new v `tnam' loc dropt`Ctfv' = (_rc) if (_rc) { if (`"`: char `tnam'[_istfv]'"' != "true") /// | ("`protect'" != "") { di as err "`tnam' already defined" e 110 } } loc tnams `tnams' `tnam' // create temporary transformed variables cap _ret res `rres' tempvar tmp`Ctfv' qui g `type' `tmp`Ctfv'' = `expr' la var `tmp`Ctfv'' `"`expr'"' } // no tfvterms if !(`Ctfv') di as txt "(note: no {it:tfvterms})" // create final variables token `tnams' forv t = 1/`Ctfv' { if (`dropt`t'') drop ``t'' ren `tmp`t'' ``t'' char ``t''[_istfv] true foreach tusr of loc tusr``t'' { di as txt "`tusr'" _col(34) "``t''" } } // return variable names and set characteristics sret loc tfvvarlist `tnams' loc _dta_tfv_varlist : char _dta[_tfv_varlist] loc tfv_varlist : list _dta_tfv_varlist | tnams char _dta[_tfv_varlist] `tfv_varlist' // no command `exit' // execute cmd `call' end pr TfvCmd args cmd loc varlist : char _dta[_tfv_varlist] if ("`cmd'" == "drop") { foreach tfv of loc varlist { cap conf v `tfv' if !(_rc) { if ("`: char `tfv'[_istfv]'" == "true") { drop `tfv' } } loc dropped `dropped' `tfv' } char _dta[_tfv_varlist] `: list varlist - dropped' } else `cmd' `varlist' end pr TfvOpts syntax [ , /// Generate(namelist) STUB(name) Type(str) /// noReplace Protect DROP ] if ("`replace'" != "") loc protect protect if ("`generate'" != "") & ("`stub'" != "") { di as err "generate and stub not both allowed" e 198 } if ("`drop'" != "") { if ("`protect'" != "") { di as err "option drop not allowed" e 198 } TfvCmd drop } c_local generate : copy loc generate c_local stub : copy loc stub c_local type : copy loc type c_local protect : copy loc protect end e 1.1.0 16mar2014 hold r() results new syntax allows options version on SSC 1.0.0 05mar2014 first draft