*! Random Group Variance Estimator / ukohler@sowi.uni-mannheim.de / 13-Mar-01
* Version 0.2 (13-Mar-01) corrects bug in calculation of t
* Version 0.1 (11-Dez-00)

program define rgroup, rclass
	version 6
	gettoken CMD   0: 0
	gettoken stats 0: 0

	if `"`CMD'"'==`""' { error 198 }
	if `"`stats'"'==`""' {
		di in red `"list of statistics not found"'
		exit 111
	}
	tokenize `"`stats'"'

/* List of statistics. */

	local stats /* erase macro */
	local i 1
	while `"``i''"'!=`""' {
		local vl     `"`vl' stat`i'"'
		local labs   `"`labs' ``i''"'
		local stats  `"`stats' (``i'')"'
		local i = `i' + 1
	}

 /* Calculate and Store Point-Estimator */

	estimates clear
	capture `CMD'
	if _rc {
		if _rc==1 { error 1 }
		di in red `"error when command executed on entire dataset"'
		error _rc
	}
	if "`e(cmd)'" == ""  {
		local N = r(N)
	}
	else {
		local N = e(N)
	}
	tokenize `labs'
	tempname val
	matrix `val' = `1'
	while "`2'" ~= "" {
		matrix `val' = `val', `2'
		mac shift
	}


/* Stuff in `0', if anything, should be options. */

	syntax , RGroups(varname max=1)

	quietly {
		tempvar groups index
		gen `index' = _n
		sort `rgroups'
		by `rgroups': gen `groups' = 1 if _n == 1
		replace `groups' = sum(`groups')
		local k = `groups'[_N]
		sort `index'


/* Catch if and Options of cmd */

		gettoken cmd 0: CMD
		syntax [varlist(default=none)][aweight fweight pweight iweight]  /*
		*/ [using] [if/] [in] [, *]
		if "`if'" ~= "" {local if "& `if'"}

/* loop for each random group */

		tempname rgroups
		tempfile resfile
		postfile `rgroups' `vl' n using `resfile'
		local i 1
		while `i' <= `k' {
			estimates clear
			`cmd' `varlist' [`weight' `exp'] `using' `in' /*
			*/ if `groups'  == `i' `if', `options'
			if "`e(cmd)'" == ""  {
				local n = r(N)
			}
			else {
				local n = e(N)
			}
			post `rgroups' `stats'  (`n')
			local i = `i'+1
		}
		postclose `rgroups'
		preserve

		use `resfile', clear


/* Print header */
		summarize n
		local n = r(mean)
		local nmin = r(min)
		noi di _n in gr `"Random Group Variance Estimator"'       /*
		*/ _col(55) in gr "number of obs = " in ye %8.0g `N' _n /*
		*/ _col(52) in gr "number of groups = " in ye %8.0g `k'  _n /*
		*/ _col(59) in gr "mean nobs = " in ye %8.0g `n' _n /*
		*/ _col(60) in gr "min nobs = " in ye %8.0g `nmin' _n(2) /*
		*/ in gr  _dup(78) `"-"'  _n  /*
		*/ `"Statistic    |"' _col(19) `"`Val'ue"' _col(26) `"Std. Err."' /*
		*/ _col(42)`"t"' _col(50) `"P>|t|"' _col(58) `" [95% Conf. Interval]"'
		noi di in gr `"-------------+"' _dup(64) `"-"'

/* Calculate and Store results */

		tempname se SE t T lb p P LB ub UB
		tokenize `labs'
		local i 1
		while `"``i''"'!=`""' {
			replace stat`i' = sum((stat`i' - `val'[1,`i'])^2)

			scalar `se' = sqrt(1/(`k'*(`k'-1)) *  stat`i'[_N])
			if `i' == 1 {capture matrix `SE' = `se'}
			else {capture matrix `SE' = `SE',`se'}

			scalar `t' = `val'[1,`i']/`se'
			if `i' == 1 {capture matrix `T' = `t'}
			else {capture matrix `T' = `T',`t'}

			scalar `p' = tprob(`k'-1,`t')
			if `i' == 1 {capture matrix `P' = `p'}
			else {capture matrix `P' = `P',`p'}

			scalar `lb' = `val'[1,`i'] - 1.96 * `se'
			if `i' == 1 {capture matrix `LB' = `lb'}
			else {capture matrix `LB' = `LB',`lb'}

			scalar `ub' = `val'[1,`i'] + 1.96 * `se'
			if `i' == 1 {capture matrix `UB' = `ub'}
			else {capture matrix `UB' = `UB',`ub'}

/* Print results */

		    local c = 13 - length(`"``i''"')
       		capture noi di in gr _col(`c') `"``i''"' `" |"' in ye /*
			*/ _s(1) %9.0g `val'[1,`i']  _s(1) %9.0g `se' /*
			*/ _s(2) %9.0g `t' _s(4) %4.3f `p'  /*
			*/ _s(3) %9.0g `lb' _s(3) %9.0g `ub'
			local i = `i' + 1
		}
	}
/* Print footer */

	di in gr  _dup(78) `"-"'
	di in gr "command was: `CMD'"

/* Return  */

	matrix rownames `val' = `val'ues
	matrix rownames `SE' = se
	matrix rownames `LB' = lower
	matrix rownames `UB' = upper

	matrix colnames `val' = `vl'
	matrix colnames `SE' = `vl'
	matrix colnames `LB' = `vl'
	matrix colnames `UB' = `vl'

	return matrix val `val'
	return matrix se `SE'
	return matrix t `T'
	return matrix p `P'
	return matrix lb `LB'
	return matrix ub `UB'

	return scalar N = `N'
	return scalar Nmean = `n'
	return scalar Nmin = `nmin'
	return scalar k = `k'
	return scalar dof = `k'-1
	tokenize `labs'
	local i 1
	while `"``i''"'!=`""' {
		return local stat`i' `"``i''"'
		local i = `i' + 1
	}
	return local cmd "`CMD'"

end
exit