*! tgmixed 1.0.2 cfb A705 capt prog drop tgmixed prog tgmixed, eclass byable(recall) version 11.2 local cmd tgmixed if replay() { if `"`e(cmd)'"' != "tgmixed" { error 301 } di as res _n "Theil-Goldberger mixed estimates" di _col(55) "Number of obs = " %8.0f e(N) di _col(55) "R-squared = " %8.4f e(r2) di _col(55) "Root MSE = " %8.5g e(rmse) ereturn display di "Theil compatibility statistic = " %7.4f e(compat) _col(55) " Pr > Chi2(" %3.0f e(vrank) ") = " /// %6.4f e(pvalue) } else { // should handle ts and fv varlists syntax varlist(numeric min=2) [if] [in], PRIor(string) [COV(string) QUIetly] tempname s2 bols Vols Vprior mixb mixV rmsemix r2mix gamma Vrank frac_sample tempvar esmpl esmpl2 mixhat mixeps loc cmdline `0' loc depvar: word 1 of `varlist' loc rhs: list varlist - depvar marksample touse su `depvar' if `touse', mean if r(N) == 0 { error 2000 } // regress to get estimate of sigma^2 `quietly' di as res _n "Unconstrained OLS estimates" `quietly' reg `varlist' if `touse' loc nols = e(N) loc dfr = e(df_r) loc tss = e(mss) + e(rss) mat `bols' = e(b) loc bcol: colnames `bols' mat `Vols' = e(V) scalar `s2' = e(rmse)^2 g byte `esmpl' = e(sample) g byte `esmpl2' = `esmpl' mat `Vprior' = J(rowsof(`Vols'), rowsof(`Vols'), .) mata: parse_prior("`depvar'", "`rhs'", "`s2'", "`esmpl'", "`prior'","`cov'", /// "`Vprior'","`bols'", "`gamma'", "`Vrank'", "`frac_sample'", /// "`mixb'", "`mixV'") mat rownames `mixb' = `depvar' mat colnames `mixb' = `bcol' mat rownames `mixV' = `bcol' mat colnames `mixV' = `bcol' mat rownames `Vprior' = `bcol' mat colnames `Vprior' = `bcol' di as res _n "Theil-Goldberger mixed estimates" ereturn post `mixb' `mixV', depname(`depvar') esample(`esmpl') obs(`nols') dof(`dfr') qui predict double `mixhat' if `esmpl2', xb qui g double `mixeps' = (`depvar' - `mixhat')^2 su `mixeps', mean scalar `rmsemix' = sqrt( r(sum) / `dfr' ) scalar `r2mix' = 1 - (r(sum) / `tss') ereturn scalar rmse = `rmsemix' ereturn scalar r2 = `r2mix' ereturn scalar N = `nols' ereturn scalar df_r = `dfr' ereturn local prior "`prior'" ereturn matrix Vprior = `Vprior' ereturn local cmdline "tgmixed `cmdline'" ereturn local marginsok "XB default" ereturn local depvar "`depvar'" // predict options xb and stdp available ereturn local predict "regres_p" di _col(55) "Number of obs = " %8.0f `nols' di _col(55) "R-squared = " %8.4f `r2mix' di _col(55) "Root MSE = " %8.5g `rmsemix' ereturn loc cmd "tgmixed" ereturn display di "Theil compatibility statistic = " %7.4f `gamma' _col(55) " Pr > Chi2(" %3.0f `Vrank' ") = " /// %6.4f chi2tail(`Vrank', `gamma') di _n "Shares of posterior precision: sample info = " %5.3f `frac_sample' /// " prior info = " %5.3f (1-`frac_sample') ereturn scalar compat = `gamma' ereturn scalar vrank = `Vrank' ereturn scalar pvalue = chi2tail(`Vrank', `gamma') ereturn scalar frac_sample = `frac_sample' ereturn scalar frac_prior = 1 - `frac_sample' } end mata: mata clear version 11.2 mata: // parse prior into triples of varname value s.e. void parse_prior( string scalar depvar, string scalar rhs, string scalar s2, string scalar esmpl, string scalar prior, string scalar cov, string scalar Vprior, string scalar bols, string scalar gammastr, string scalar Vrankstr, string scalar fsstr, string scalar mixb, string scalar mixV) { real matrix R, r, Vinv rhsv = tokens(rhs) // assume constant is last element nrhs = cols(rhsv) + 1 prstr = tokens(prior) npr = cols(prstr) if (mod(npr , 3) != 0) { "Error: prior() must be specified as triples (varname, value, s.e.)" exit(error(198)) } // check whether cov was provided cvstr = tokens(cov) ncv = cols(cvstr) if (mod(ncv , 3) != 0) { "Error: cov() must be specified as triples (varname1, varname2, value)" exit(error(198)) } // parse prior elements R = J(nrhs, nrhs, 0) r = J(nrhs, 1, 0) V = J(nrhs, nrhs, 0) Vinv = J(nrhs, nrhs, 0) // locate regressors named in prior in rhslist // uses mm_posof() from Ben Jann's moremata, included below prstm = rowshape(prstr, npr/3)' for(i=1; i<=cols(prstm); i++) { nreg = mm_posof(rhsv, prstm[1, i]) if (nreg == 0) { "Error: regressor listed in prior() not in model:" prstm[1, i] exit(error(198)) } else { // regressor located; fill in R, r, V elements R[nreg, nreg] = 1 r[nreg] = strtoreal(prstm[2, i]) V[nreg, nreg] = strtoreal(prstm[3, i]) ^2 } } // end prior parsing loop if (ncv) { // cov parsing loop cvstm = rowshape(cvstr, ncv/3)' for(i=1; i<=cols(cvstm); i++) { nreg1 = mm_posof(rhsv, cvstm[1, i]) nreg2 = mm_posof(rhsv, cvstm[2, i]) if (nreg1 == 0 ) { "Error: regressor listed in cov() not in model" cvstm[1, i] exit(error(198)) } if (nreg2 == 0 ) { "Error: regressor listed in cov() not in model" cvstm[2, i] exit(error(198)) } if (nreg1 == nreg2) { "Error: regressor listed twice in cov()" cvstm[1,i] exit(error(198)) } V[nreg1, nreg2] = strtoreal(cvstm[3, i]) V[nreg2, nreg1] = strtoreal(cvstm[3, i]) } } // end cov parsing loop " " "Prior coefficient values and standard errors" prstm if (ncv) { " " "Prior covariances" cvstm } // create views of y, X using e(sample) st_view(y=., ., depvar, esmpl) st_view(X=., ., rhsv, esmpl) X = X, J(rows(X), 1, 1) // get OLS s2 for variance estimates sigma2 = st_numscalar(s2) // tgmixed solution for b and VCE from Theil-Goldberger, 1961, (2.8)-(2.9) // for now only allow scalar identity errors; easy extension to robust st_matrix(Vprior, V) Vinv = invsym(V) w = J(rows(X), 1, 1/sigma2) Vb = invsym(quadcross(X, w, X) + R' * Vinv * R) b = Vb * (quadcross(X, w, y) + R' * Vinv * r) st_matrix(mixb, b') st_matrix(mixV, Vb) // Theil compatibility statistic, JASA 1963, (3.3) betaols = st_matrix(bols)' discrep = (r - R * betaols) gamma = discrep' * invsym( sigma2 * R * invsym(quadcross(X, X)) * R' + V) * discrep st_numscalar(gammastr, gamma) st_numscalar(Vrankstr, rank(V)) // implement fraction of variance from prior info statistic from Theil 1963? frac_sample = 1/nrhs * trace(quadcross(X, w, X) * Vb) st_numscalar(fsstr, frac_sample) } end *! *! mm_posof.mata *! version 1.0.0, Ben Jann, 24mar2006 version 9.0 mata: real scalar mm_posof(transmorphic vector haystack, transmorphic scalar needle) { real scalar i for (i=1; i<=length(haystack); i++) { if (haystack[i]==needle) return(i) } return(0) } end