*! ivreg2hdfe v1.0.0 | Dany Bahar | dbaharc@gmail.com | 15May2014 cap prog drop ivreg2hdfe program ivreg2hdfe, eclass // program reg2hdfe, eclass version 10.1 syntax [if], DEpvar(varname num) ENdog(varlist num) iv(varlist num) [EXog(varlist num)] id1(varname max=1) id2(varname max=1) [cluster(varname max=1)] [gmm2s] marksample touse tmpdir returns r(tmpdir): local tdir `r(tmpdir)' qui cd "`tdir'" local tempfiles : dir . files "*.dta" foreach f in `tempfiles' { erase `f' } preserve if "`if'"~="" { qui keep `if' } bys `id1':gen NN=_N qui drop if NN==1 drop NN tempvar clustervar ctrans if "`cluster'"~="" { capture confirm string variable `cluster' if !_rc { gen `ctrans' = `cluster' capture encode `ctrans', g(`clustervar') } else { gen double `clustervar'=`cluster' } qui reg2hdfe `depvar' `endog' `exog' `iv', id1(`id1') id2(`id2') cluster(`clustervar') out("`tdir'") noregress } else { qui reg2hdfe `depvar' `endog' `exog' `iv', id1(`id1') id2(`id2') out("`tdir'") noregress } /* From reg2hdfe.ado */ tempfile tmp1 tmp2 tmp3 readdata quietly { use _ids, clear sort __uid qui save "`tmp1'", replace if "`cluster'"!="" { merge __uid using _clustervar if r(min)<r(max) { di "Fatal Error" error 198 } drop _merge sort __uid rename __clustervar `clustervar' qui save "`tmp1'", replace } * Now read the original variables foreach var in `depvar' `endog' `exog' `iv' { merge __uid using _`var' sum _merge, meanonly if r(min)<r(max) { di "Fatal Error" error 198 } drop _merge drop __fe2* drop __t_* sort __uid qui save "`tmp2'", replace } foreach var in `depvar' `endog' `exog' `iv' { rename __o_`var' `var' } sum `depvar', meanonly tempvar yy sy gen double `yy'=(`depvar'-r(mean))^2 gen double `sy'=sum(`yy') local tss=`sy'[_N] drop `yy' `sy' qui save "`readdata'", replace use `tmp1', clear foreach var in `depvar' `endog' `exog' `iv' { merge __uid using _`var' sum _merge, meanonly if r(min)<r(max) { di "Fatal Error." error 198 } drop _merge drop __fe2* drop __o_* sort __uid qui save "`tmp3'", replace } foreach var in `depvar' `endog' `exog' `iv' { rename __t_`var' `var' } } * Create group variable tempvar group qui makegps, id1(`id1') id2(`id2') groupid(`group') * Calculate Degrees of Freedom qui count local N = r(N) local k : word count `endog' `exog' `iv' //Check whether here I need also the instruments or not sort `id1' qui count if `id1'!=`id1'[_n-1] local G1 = r(N) sort `id2' qui count if `id2'!=`id2'[_n-1] local G2 = r(N) sort `group' qui count if `group'!=`group'[_n-1] local M = r(N) local kk = `k' + `G1' + `G2' - `M' local dof = `N' - `kk' local G = `G2'-1 tempname name1 name2 if "`cluster'"=="" { //regress `depvar' `endog' `exog' `iv', nocons dof(`dof') ivreg2 `depvar' (`endog'=`iv') `exog' , `gmm2s' nocons dofminus(`G1') sdofminus(`G') //dof(`dof') estimates store `name1' local r=1-e(rss)/`tss' local KP = e(widstat) ereturn scalar df_m = `kk'-1 ereturn scalar mss=`tss'-e(rss) ereturn scalar r2=`r' ereturn scalar r2_a=1-(e(rss)/e(df_r))/(`tss'/(e(N)-1)) ereturn scalar F=(`r'/(1-`r'))*(e(df_r)/(`kk'-1)) ereturn scalar widstat = `KP' ereturn local cmdline "ivreg2hdfe `0'" ereturn local cmd "ivreg2hdfe" ereturn local predict "" ereturn local estat_cmd "" estimates store `name1' } else { sort `clustervar' qui count if `clustervar'!=`clustervar'[_n-1] local Nclust = r(N) //regress `depvar' `endog' `exog' `iv', nocons cluster(`clustervar') // mse1 ivreg2 `depvar' (`endog'=`iv') `exog' , `gmm2s' nocons dofminus(`G1') sdofminus(`G') cluster(`clustervar') estimates store `name2' tempname b V matrix `V'=e(V) matrix `b'=e(b) local rss=e(rss) local r=1-`rss'/`tss' local nobs=e(N) local KP = e(widstat) tempvar res predict double `res', residual _robust `res', v(`V') minus(`kk') cluster(`clustervar') ereturn scalar Mgroups = `M' //ereturn post `b' `V', depname(`depvar') obs(`nobs') dof(`kk') ereturn local eclustvar "`cluster'" ereturn local vce "cluster" ereturn local vcetype "Robust" ereturn local cmdline "ivreg2hdfe `0'" ereturn local depvar "y" ereturn local cmd "ivreg2hdfe" ereturn scalar N_clust=`Nclust' ereturn scalar r2=`r' ereturn scalar rss=`rss' ereturn scalar mss=`tss'-`rss' ereturn scalar widstat = `KP' estimates store `name2' } restore end /* This routine is from Amine Quazad's a2reg program */ /* It establishes the connected groups in the data */ *Find connected groups for normalization capture program drop makegps program define makegps version 9.2 syntax [if] [in], id1(varname) id2(varname) groupid(name) marksample touse markout `touse' `id1' `id2' confirm new variable `groupid' sort `id1' `id2' preserve *Work with a subset of the data consisting of all id1-id2 combinations keep if `touse' collapse (sum) `touse', by(`id1' `id2') sort `id1' `id2' *Start by assigning the first id1 value to group 1, then iterate to fill this out tempvar group newgroup1 newgroup2 gen double `group'=`id1' local finished=0 local iter=1 while `finished'==0 { quietly { bysort `id2': egen double `newgroup1'=min(`group') bysort `id1': egen double `newgroup2'=min(`newgroup1') qui count if `newgroup2'~=`group' local nchange=r(N) local finished=(`nchange'==0) replace `group'=`newgroup2' drop `newgroup1' `newgroup2' } di in yellow "On iteration `iter', changed `nchange' assignments" local iter=`iter'+1 } sort `group' `id1' `id2' tempvar nobs complement by `group': egen double `nobs'=sum(`touse') replace `nobs'= -1*`nobs' egen double `groupid'=group(`nobs' `group') keep `id1' `id2' `groupid' sort `id1' `id2' tempfile gps save `gps' restore tempvar mrg2group merge `id1' `id2' using `gps', uniqusing _merge(`mrg2group') assert `mrg2group'~=2 assert `groupid'<. if `mrg2group'==3 assert `groupid'==. if `mrg2group'==1 drop `mrg2group' end