program def mvsumm7, rclass *! CFB 1.0.10 15 Oct 2005 *! NJC 1.0.9 23 Sept 2004 *! CFB 1.0.8 30 June 2004 *! NJC 1.0.7 23 June 2004 *! CFB 1.0.6 10 April 2003 *! NJC 1.0.5 23 July 2002 *! CFB 1.0.4 23 July 2002 *! NJC 1.0.3 23 July 2002 *! CFB 1.0.2 22 July 2002 *! CFB 1.0.1 17 July 2002 from statsmat.ado * NJC 2.1.0 6 February 2002 * NJC/CFB 2.0.0 3 October 2001 * CFB 1.0.0 1 October 2001 * 1.0.1 : deal with missing values properly * 1.0.2 : disallow gaps within timeseries * 1.0.3 : NJC clean-up * 1.0.4 : even window: end, odd window: middle, override with end * 1.0.5 : NJC obsessive tidy; check for multiple statistics call * 1.0.6 : change levels to levels7 so will work under v8 * 1.0.7 : cut out levels use to allow large # panels * 1.0.8 : remove extraneous use of if clause in panel code * 1.0.9 : correction to properly align results after if or in * 1.0.10: add force option to produce result when window not full version 7.0 syntax varname [if] [in] [aweight fweight] /* */ , Generate(str) Stat(str) [ /* BY(varname) */ Window(int 3) /* */ /* MISSing Mid */ End FORCE] * check -generate()- local gen "`generate'" if "`gen'" != "" { confirm new variable `gen' qui gen `gen' = . } else { di as err "generate() not specified" exit 198 } * what data to use marksample touse, novarlist * ensure that we have a calendar; check for panel var qui tsset * if panelvar is defined, call that the by option local by `r(panelvar)' local timevar `r(timevar)' markout `touse' `timevar' tsreport if `touse', report panel if r(N_gaps) { di as err "sample may not contain gaps" exit 198 } * from movsumm if `window' < 2 { di as err "window length must be at least 2" exit 198 } * from movsumm local jaybase = `window' local jlast = _N * check for odd-length window if mod(`window',2) != 0 & "`end'" != "end" { local shift = int(`window'/2) } * di as txt "shift is " as res "`shift'" if "`by'" != "" { markout `touse' `by', strok } qui count if `touse' if r(N) == 0 { error 2000 } return local N = r(N) local nstats : word count `stat' * must assure that only one stat is selected here, * unless generate() can be made into a list of new vars if `nstats' > 1 { di as txt "sorry: multiple statistics not (yet) supported" exit 0 } * which statistic? local monly "meanonly" foreach st of local stat { if "`st'" == "n" | "`st'" == "N" | "`st'" == "count" { local s "N" } else if "`st'" == "sum" | "`st'" == "sum_w" { local s "`st'" } else if "`st'" == "mean" { local s "mean" } else if "`st'" == "min" | "`st'" == "max" { local s "`st'" } else if "`st'" == "range" { local s "range" } else if "`st'" == "var" | "`st'" == "Var" { local monly local s "Var" } else if "`st'" == "SD" | "`st'" == "sd" { local monly local s "sd" } /* do not allow mult stats at this point (would require a stub option to generate multiple result vars) else if "`st'" == "p" { local monly local detail "detail" local s "p1 p5 p10 p25 p50 p75 p90 p95 p99" local st "`s'" } else if "`st'" == "q" { local monly local detail "detail" local s "p25 p50 p75" local st "`s'" } */ else if "`st'" == "p1" | "`st'" == "p5" { local monly local detail "detail" local s "`st'" } else if "`st'" == "p10" | "`st'" == "p25" { local monly local detail "detail" local s "`st'" } else if "`st'" == "p50" /* */ | "`st'" == "med" | "`st'" == "median" { local monly local detail "detail" local s "p50" } else if "`st'" == "p75" | "`st'" == "p90" { local monly local detail "detail" local s "`st'" } else if "`st'" == "p95" | "`st'" == "p99" { local monly local detail "detail" local s "`st'" } else if "`st'" == "skewness" | "`st'" == "skew" { local monly local detail "detail" local s "skewness" } else if "`st'" == "kurtosis" | "`st'" == "kurt" { local monly local detail "detail" local s "kurtosis" } else if "`st'" == "se" | "`st'" == "SE" | "`st'" == "semean" { local monly local detail "detail" local s "se" } else if "`st'" == "iqr" | "`st'" == "IQR" { local monly local detail "detail" local s "iqr" } else if "`st'" == "zero" | "`st'" == "0" { local s "0" } else { di as err "stat() option invalid" exit 198 } local cnames "`cnames' `st'" local stats "`stats' `s'" } /* end of -foreach st of local stat */ tempname result * in panel context, get distinct values of panelvar * and hit with -foreach- qui if "`by'" != "" { tempvar group egen `group' = group(`by') /* if `touse' */ su `group', meanonly local max = `r(max)' local start 0 local fin 0 forval i = 1 / `max' { local jay = `jaybase' count if `group' == `i' local enn = r(N) local jlast = `enn' + `fin' * logic from movsumm local eye = 1 + `start' local kay = `window' + `start' while `jay' <= `jlast' { * correction su `varlist' in `eye'/`kay' /* * */ if `group' == `i' [`weight' `exp'], `detail' `monly' su `varlist' in `eye'/`kay' [`weight' `exp'], `detail' `monly' local na = r(N) foreach s of local stats { if "`s'" == "0" { scalar `result' = 0 } else if "`s'" == "se" { scalar `result' = r(sd) / sqrt(r(N)) } else if "`s'" == "iqr" { scalar `result' = r(p75) - r(p25) } else if "`s'" == "range" { scalar `result' = r(max) - r(min) } else scalar `result' = r(`s') } if "`force'" == "" { replace `gen' = `result' in `jay' if `na' == `window' } else { replace `gen' = `result' in `jay' } local eye = `eye' + 1 local jay = `jay' + 1 local kay = `kay' + 1 } local start = `start' + `enn' local fin = `fin' + `enn' local jaybase = `jaybase' + `enn' } } /* end of code for panels */ * single timeseries, no loop over panel var else { * logic from movsumm local eye = 1 local kay = `window' local jay = `jaybase' qui while `jay' <= `jlast' { su `varlist' in `eye'/`kay' /* if `touse' */ /* */ [`weight' `exp'], `detail' `monly' local na = r(N) foreach s of local stats { if "`s'" == "0" { scalar `result' = 0 } else if "`s'" == "se" { scalar `result' = r(sd) / sqrt(r(N)) } else if "`s'" == "iqr" { scalar `result' = r(p75) - r(p25) } else if "`s'" == "range" { scalar `result' = r(max) - r(min) } else scalar `result' = r(`s') } if "`force'" == "" { replace `gen' = `result' in `jay' if `na' == `window' } else { replace `gen' = `result' in `jay' } local eye = `eye' + 1 local jay = `jay' + 1 local kay = `kay' + 1 } } /* end of code for no panels */ qui if "`shift'" != "" { replace `gen' = F`shift'.`gen' } qui replace `gen' = . if !`touse' end