*! version 1.02 by David Roodman, Center for Global Development 7/27/04. *! Based almost entirely on collapse version 6.0.0 14apr2003 program define collapse2 if _caller() < 5 { collaps4 `0' exit } version 8 syntax anything(name=clist id=clist equalok) /// [if] [in] [aw fw iw pw] /// [, BY(varlist) CW FAST CLABEL ] if ("`fast'"=="") preserve cap tsset qui if _rc == 0 { tempvar tvar gen `tvar' = `r(timevar)' if "`r(panelvar)'" != "" { tempvar ivar qui gen `ivar' = `r(panelvar)' } tsset `ivar' `tvar' local keep `ivar' `tvar' } local n 0 local stat = "mean" while `"`clist'"' != "" { GetOpStat stat clist : "`stat'" `"`clist'"' /* now we get */ /* is it name = ... */ gettoken tok1 rest : clist , parse(" =.") bind gettoken tok2 rest2: rest, parse(" =.") bind if "`tok2'" == "=" { // newname = ... GetNewnameEq lhs rhs clist : `"`clist'"' local ++n tsrevar `rhs' local tname `r(varlist)' local keep `"`keep' `tname'"' local tar `"`tar' `lhs'"' local old`n' `"`tname'"' local lab`n' `"`rhs'"' local fcn`n' `"`stat'"' local new`n' `"`lhs'"' local fmt`n' : format `tname' } else { // varname(ts) or varlist(ts) GetVarlist vl clist : `"`clist'"' local i 0 tsrevar `vl' foreach el in `r(varlist)' { local ++n gettoken realname vl : vl local ++i local keep `"`keep' `el'"' local tar `"`tar' `el'"' local old`n' `el' local lab`n' "`realname'" local fcn`n' `"`stat'"' Setnf new`n' fmt`n' : `realname' `el' } } } if (`n'==0) error 198 if `"`by'"'!="" { bynottar `"`by'"' `"`tar'"' } if `"`weight'"' != "" { tempvar w qui gen double `w' `exp' `if' `in' local wgt `"[`weight'=`w']"' } tempvar touse mark `touse' `if' `in' `wgt' if `"`cw'"'!="" { markout `touse' `keep' } qui count if `touse' if r(N)==0 { error 2000 } qui keep if `touse' qui keep `keep' `by' `w' /* check uniqueness */ /* Table: old`i' (original) name of source variable x use`i' renamed old`i' new`i' target variable x drp`i' =use`i' if may be dropped, else `" "' fcn`i' function to call x fmt`i' %format of original variable */ local i 1 while `i' <= `n' { if `"`drp`i''"'=="" { tempname use local use`i' `"`use'"' rename `old`i'' `use' local lasti `i' } local j=`i'+1 while `j'<=`n' { if `"`new`i''"' == `"`new`j''"' { di as err "error:" _n /* */ _col(8) `"`new`i'' = (`fcn`i'') `lab`i''"' /* */ _n /* */ _col(8) `"`new`j'' = (`fcn`j'') `lab`j''"' /* */ _n "name conflict" exit 198 } if `"`drp`i''"'=="" & `"`old`i''"' == `"`old`j''"' { local lasti `j' local use`j' `"`use'"' local drp`j' `" "' } local ++j } if `"`drp`i''"'=="" { local drp`lasti' `"`use'"' } local ++i } quietly { tempvar new local i 1 while `i'<=`n' { _`fcn`i'' `new`i'' `use`i'' `"`weight'"' `"`w'"' /* */ `"`by'"' capture drop `drp`i'' if "`clabel'"=="" { label var `new`i'' `"(`fcn`i'') `lab`i''"' } else label var `new`i'' `"`fcn`i'' of `lab`i''"' format `new`i'' `fmt`i'' local ++i } } if `"`by'"' != "" { sort `by' quietly by `by': keep if _n==_N } else quietly keep in 1 global S_FN global S_FNDATE if ("`fast'" == "") restore, not end program Setnf args mname mfmt colon realname el if "`realname'" == "`el'" { c_local `mname' "`el'" c_local `mfmt' : format `el' } else { local op : tsnorm `realname' , varname gettoken op var : op , parse(".") gettoken dot var : var, parse(".") c_local `mname' `op'`var' c_local `mfmt' : format `var' } end program GetNewnameEq args mlhs mrhs mrest colon rest gettoken lhs rest : rest, parse(" =") gettoken equal rest : rest, parse(" =") gettoken 0 rest : rest, parse(" ") confirm name `lhs' c_local `mlhs' `lhs' syntax varname(ts) c_local `mrhs' `varlist' c_local `mrest' `rest' end program GetVarlist args mvl mrest colon rest while (1) { gettoken tok rest1 : rest, parse(" =") local c = substr(trim(`"`rest1'"'),1,1) if "`c'"=="=" | "`c'"=="(" | "`c'"=="" { if "`c'" == "=" { local 0 `"`vl'"' c_local `mrest' `"`rest'"' } else if "`c'"=="(" { local 0 `vl' `tok' c_local `mrest' `"`rest1'"' } else { local 0 `vl' `tok' c_local `mrest' } syntax varlist(ts) c_local `mvl' "`varlist'" exit } local vl `vl' `tok' local rest `"`rest1'"' } end program GetOpStat args mstat mrest colon stat line gettoken thing nline : line, parse("() ") match(parens) if "`parens'"=="" { c_local `mstat' "`stat'" c_local `mrest' `"`line'"' exit } if `:word count `thing'' == 1 { local 0 `", `thing'"' capture syntax [, mean median sd sum rawsum count max min iqr first firstnm last lastnm] if _rc == 0 { c_local `mstat' `thing' c_local `mrest' `"`nline'"' if ("`median'"!="") c_local `mstat' "p 50" exit } if "`first'`last'`firstnm'`lastnm'" == "" { tsset } local thing = trim("`thing'") if (substr("`thing'",1,1) == "p") { local thing = substr("`thing'",2,.) capture confirm integer number `thing' if _rc==0 { if 1<=`thing' & `thing'<=99 { c_local `mstat' "p `thing'" c_local `mrest' `"`nline'"' exit } } } } di as err "(`thing') invalid statistic" exit 198 end program bynottar /* `"byvars"' `"targetvars"' */ local byvars `"`1'"' tokenize `"`2'"' local i 1 local byv : word `i' of `byvars' while `"`byv'"' != "" { local j 1 while `"``j''"' != "" { if `"`byv'"'==`"``j''"' { di as err /* */ `"``j'' may not be both target and by()"' exit 198 } local ++j } local ++i local byv : word `i' of `byvars' } end /* routines for calculating statistics */ program _mean /* newvar oldvar wtype wvar byvars */ args y x wt w by if (`"`w'"'=="") local w 1 if `"`by'"' != "" { sort `by' local by `"by `by':"' } local ty : type `x' if (`"`ty'"'=="double" | `"`ty'"'=="long") local ty "double" else local ty /* erase macro */ quietly { `by' gen `ty' `y' = sum(`w'*`x')/sum(cond(`x'<.,`w',0)) `by' replace `y' = `y'[_N] } end program _sd /* newvar oldvar wtype wvar byvars */ args y x wt w by if (`"`w'"'=="") local w 1 else { if `"`wt'"'=="pweight" { di as err "sd not allowed with pweights" exit 135 } } if `"`by'"' != "" { sort `by' local by `"by `by':"' } quietly { if `"`wt'"'=="aweight" { tempvar new remakew `x' `w' `new' `"`by'"' local w `"`new'"' } local ty : type `x' if (`"`ty'"'=="double" | `"`ty'"'=="long") local ty "double" else local ty /* erase macro */ tempvar m `by' gen double `m' = sum(`w'*`x')/sum(cond(`x'<.,`w',0)) `by' gen `ty' `y' = sqrt( /* */ sum(`w'*((`x'-`m'[_N])^2)) / /* */ (sum(cond(`x'<.,`w',0))-1) /* */ ) `by' replace `y' = cond(`m'[_N]==., ., `y'[_N]) } end program _sum args y x wt w by if (`"`w'"'=="") local w 1 if `"`by'"' != "" { sort `by' local by `"by `by':"' } quietly { if `"`wt'"'=="aweight" { tempvar new remakew `x' `w' `new' `"`by'"' local w `"`new'"' } `by' gen double `y' = sum(`w'*`x') `by' replace `y' = `y'[_N] } end program _rawsum args y x wt w by if `"`by'"' != "" { sort `by' local by `"by `by':"' } quietly { `by' gen double `y' = sum(`x') `by' replace `y' = `y'[_N] } end program _count args y x wt w by if `"`by'"' != "" { sort `by' local by `"by `by':"' } quietly { if `"`wt'"'=="fweight" | `"`wt'"'=="iweight" /* */ | `"`wt'"'=="pweight" { `by' gen double `y' = sum(cond(`x'<.,`w',0)) } else `by' gen long `y' = sum(`x'<.) `by' replace `y' = `y'[_N] } end program _max args y x wt w by tempvar touse quietly { local ty : type `x' gen byte `touse' = (`x' < .) sort `by' `touse' `x' if `"`by'"' != "" { by `by': gen `ty' `y' = `x'[_N] } else gen `ty' `y' = `x'[_N] } end program _last args y x wt w by quietly { tsset local t `r(timevar)' local ty : type `x' sort `by' `t' if `"`by'"' != "" { by `by': gen `ty' `y' = `x'[_N] } else gen `ty' `y' = `x'[_N] } end program _lastnm args y x wt w by tempvar touse quietly { tsset local t `r(timevar)' local ty : type `x' gen byte `touse' = (`x' < .) sort `by' `touse' `t' if `"`by'"' != "" { by `by': gen `ty' `y' = `x'[_N] } else gen `ty' `y' = `x'[_N] } end program _first args y x wt w by quietly { tsset local t `r(timevar)' local ty : type `x' gsort `by' -`t' if `"`by'"' != "" { by `by': gen `ty' `y' = `x'[_N] } else gen `ty' `y' = `x'[_N] } end program _firstnm args y x wt w by tempvar touse quietly { tsset local t `r(timevar)' local ty : type `x' gen byte `touse' = (`x' < .) gsort `by' `touse' -`t', mfirst if `"`by'"' != "" { by `by': gen `ty' `y' = `x'[_N] } else gen `ty' `y' = `x'[_N] } end program _min args y x wt w by tempvar touse revx quietly { local ty : type `x' gen byte `touse' = (`x'<.) gen double `revx' = -`x' sort `by' `touse' `revx' if `"`by'"' != "" { by `by': gen `ty' `y' = `x'[_N] } else gen `ty' `y' = `x'[_N] } end program _p args p y x wt w by tempvar touse i n g local ty : type `x' if (`"`ty'"'=="double" | `"`ty'"'=="long") local ty "double" else local ty /* erase macro */ quietly { gen byte `touse' = `x'<. sort `by' `touse' `x' if `"`w'"'=="" { local w 1 } else { tempvar new if `"`by'"' != "" { remakew `x' `w' `new' `"by `by':"' } else remakew `x' `w' `new' local w `"`new'"' } by `by' `touse': gen double `n' = sum(`w') if `touse' by `by' `touse': /* */ gen double `g' = `n'*`p'/100 if `touse' & _n==_N gen long `i' = . by `by' `touse': /* */ replace `i'=cond(`i'[_n-1]<.,`i'[_n-1], /* */ cond(`n'-`g'[_N]>.01,_n,.)) if `touse' by `by' `touse': /* */ gen `ty' `y' = cond(`g'- `n'[`i'-1] >.01, /* */ `x'[`i'], (`x'[`i'-1]+`x'[`i'])/2) /* */ if `touse' & _n==_N if `"`by'"' != "" { by `by': replace `y' = `y'[_N] } else replace `y' = `y'[_N] } end program _iqr args y x wt w by tempvar p75 p25 _p 75 `p75' `x' `"`wt'"' `"`w'"' `"`by'"' _p 25 `p25' `x' `"`wt'"' `"`w'"' `"`by'"' local ty : type `p75' quietly gen `ty' `y' = `p75' - `p25' end /* utilities used by _* routines */ program remakew /* xvar oldw neww by-prefix */ args x w new by /* by is either "" or "by vn vn ...:" */ tempvar sum obs `by' gen long `obs' = sum(`x'<.) `by' gen double `sum' = sum(cond(`x'<.,`w',0)) `by' gen double `new' = cond(`x'<., `w'*`obs'[_N]/`sum'[_N], .) end exit /* := [] [] := () := mean | sd | sum | rawsum | count | max | min | iqr | first | last p# (1 <= # <= 99, # an int) := varname varlist name[ ]=[ ] name[ ]=[ ] op.varname op.(varname [varname ...]) op(numlist).varname op(numlist).(varname [varname...]) ------------------------------------------------------------------------- */