* VERSION 1.29 (SJ2-4: st0026) * OCTOBER 8, 2002 * LAST REVISOR: SOB * * program define attr, rclass version 7.0 syntax varlist [if] [in] [fweight iweight pweight], [ pscore(varname) logit index radius(real 0.1) comsup DETail BOOTstrap Reps(int 50) NOIsily Dots ] tokenize `varlist' local Y `1' local T `2' preserve if `"`if'"'!="" | "`in'"!="" { qui keep `if' `in' } if `"`detail'"' != `""' { di in ye _newline(2) "***************************************************** " di in ye "Estimation of the ATT with the radius matching method " di in ye "***************************************************** " } macro shift local rest `*' /* if pscore is not user-provided, it has to be estimated */ if `"`pscore'"' == `""' { if `"`detail'"' != `""' { di in ye _newline(2) " Estimation of the propensity score" } tempvar PSCORE if `"`detail'"' != `""' { if `"`logit'"' != `""' { logit `rest' [`weight'`exp'], nolog } else { probit `rest' [`weight'`exp'], nolog } } else { if `"`logit'"' != `""' { qui logit `rest' [`weight'`exp'], nolog } else { qui probit `rest' [`weight'`exp'], nolog } } if `"`index'"' != `""' { qui predict double `PSCORE', index } else { qui predict double `PSCORE' } } else { local PSCORE `pscore' } /* REGION OF COMMON SUPPORT */ if `"`comsup'"' != `""' { qui sum `PSCORE' if `T'==1 tempname mintreat maxtreat tempvar COMSUP scalar `mintreat' = r(min) scalar `maxtreat' = r(max) if `"`detail'"' != `""' { di _newline(2) in ye " Note: the common support option has been selected" di in ye " The region of common support is [" `mintreat' ", " `maxtreat' "]" } qui g `COMSUP'=(`PSCORE'>=`mintreat' & `PSCORE'<=`maxtreat') qui drop if `COMSUP'!=1 } if `"`detail'"' != `""' { di in ye _newline(2) " The outcome is `Y'" sum `Y' di in ye _newline(2) " The treatment is `T'" tab `T' di in ye _newline(2) " The distribution of the pscore is" sum `PSCORE', detail di in ye _newline(2) " The radius is " `radius' } di in ye _newline(2) " The program is searching for matches of treated units within radius. " di in ye " This operation may take a while." qui count if `Y' != . local ntot = r(N) tempvar psdifi psdif_i YCRi MCRi YCR_i MCR_i numYCR denYCR WCRi WCR_i WCR SWCR YCR sort `PSCORE' local i = 1 local stopi = 0 local stop_i = 0 gen `psdifi' = 0 gen `psdif_i' = 0 gen `YCRi' = 0 gen `MCRi' = 0 gen `YCR_i' = 0 gen `MCR_i' = 0 gen `WCRi' = 0 gen `WCR_i' = 0 gen `WCR' = 0 gen `numYCR' = 0 gen `denYCR' = 0 while `stopi' == 0 | `stop_i' == 0 { qui replace `psdifi' = abs(`PSCORE' - `PSCORE'[_n + `i']) qui replace `psdif_i' = abs(`PSCORE' - `PSCORE'[_n - `i']) qui replace `YCRi' = 0 qui replace `MCRi' = 0 qui replace `YCR_i' = 0 qui replace `MCR_i' = 0 qui replace `WCRi' = 0 qui replace `WCR_i' = 0 qui replace `YCRi' = `Y'[_n + `i'] if `T'==1 & `T'[_n + `i']==0 & `psdifi' < `radius' qui replace `MCRi' = `T'==1 & `T'[_n + `i']==0 & `psdifi' < `radius' * weight WCR is mirror image of the rest qui replace `WCRi' = `T'==0 & `T'[_n - `i']==1 & `psdifi'[_n-`i'] < `radius' qui count if `MCRi'== 0 if r(N) == `ntot' { local stopi = 1 } qui replace `YCR_i' = `Y'[_n - `i'] if `T'==1 & `T'[_n - `i']==0 & `psdif_i' < `radius' qui replace `MCR_i' = `T'==1 & `T'[_n - `i']==0 & `psdif_i' < `radius' * weight WCR is mirror image of the rest qui replace `WCR_i' = `T'==0 & `T'[_n + `i']==1 & `psdif_i'[_n+`i'] < `radius' qui count if `MCR_i'== 0 if r(N) == `ntot' { local stop_i = 1 } qui replace `numYCR' = `numYCR' + `YCRi' + `YCR_i' qui replace `denYCR' = `denYCR' + `MCRi' + `MCR_i' qui replace `WCR' = `WCR' + `WCRi' + `WCR_i' local i = `i' + 1 * di " i = " `i' * di " stopi is " `stopi' * di " stop_i is " `stop_i' } if `"`detail'"' != `""' { di in ye _newline(2) "**************************************************** " di in ye "Display of final results " di in ye "**************************************************** " } if `"`detail'"' != `""' { di _newline(2) "The number of treated is" count if `T'==1 qui gen `YCR' = `numYCR' / `denYCR' if `T==1' di _newline(2) "The number of treated which have been matched is " count if `YCR' != . local nttot = r(N) qui egen `SWCR' = sum(`WCR') qui replace `WCR' = `nttot'*(`WCR'/`SWCR') di _newline(2) "Average outcome of the matched treated" sum `Y' if `T'==1 & `YCR' != . local myt = r(mean) local varyt = r(Var) di _newline(2) "Average outcome of the matched controls" sum `Y' [aweight=`WCR'] if `T'==0 local myc = r(mean) local nc = r(N) qui sum `Y' if `T'==0 & `WCR'!=0 local varyc = r(Var) tempvar sqweight nweight qui gen `sqweight'=`WCR'^2 if `T'==0 qui sum `sqweight' scalar `nweight' = r(sum) return scalar seattr = sqrt( `varyt'/`nttot' + (`nweight'/(`nttot'^2))*`varyc' ) return scalar attr = `myt'-`myc' return scalar tsattr = return(attr)/return(seattr) return scalar ntr = `nttot' return scalar ncr = `nc' } else { qui gen `YCR' = `numYCR' / `denYCR' if `T==1' qui count if `YCR' != . local nttot = r(N) qui egen `SWCR' = sum(`WCR') qui replace `WCR' = `nttot'*(`WCR'/`SWCR') qui sum `Y' if `T'==1 & `YCR' != . local myt = r(mean) local varyt = r(Var) qui sum `Y' [aweight=`WCR'] if `T'==0 local myc = r(mean) local nc = r(N) qui sum `Y' if `T'==0 & `WCR'!=0 local varyc = r(Var) tempvar sqweight nweight qui gen `sqweight'=`WCR'^2 if `T'==0 qui sum `sqweight' scalar `nweight' = r(sum) return scalar seattr = sqrt( `varyt'/`nttot' + (`nweight'/(`nttot'^2))*`varyc' ) return scalar attr = `myt'-`myc' return scalar tsattr = return(attr)/return(seattr) return scalar ntr = `nttot' return scalar ncr = `nc' } di _newline(3) _column(1) in gr "ATT estimation with the Radius Matching method" di _column(1) in gr "Analytical standard errors" di in gr _newline(1) in text "{hline 57}" di _column(1) in gr "n. treat." /* */ _column(13) in gr "n. contr." /* */ _column(25) in gr " ATT" /* */ _column(37) in gr "Std. Err." /* */ _column(49) in gr " t" di in gr in text "{hline 57}" di _newline(1) _column(1) in ye %9.0f return(ntr) /* */ _column(13) in ye %9.0f return(ncr) /* */ _column(25) in ye %9.3f return(attr) /* */ _column(37) in ye %9.3f return(seattr) /* */ _column(49) in ye %9.3f return(tsattr) di in gr _newline(1) in text "{hline 57}" di in gr "Note: the numbers of treated and controls refer to actual" di in gr "matches within radius" restore if `"`bootstrap'"' != `""' { di _newline(5) in gr "Bootstrapping of standard errors " bs "attr `varlist' `if' `in' `fweight' `iweight' `pweight', pscore(`pscore') `logit' `index' `comsup' radius(`radius')" "r(attr)", nowarn reps(`reps') `noisily' `dots' } if `"`bootstrap'"' != `""' { return scalar attr = r(stat) return scalar bseattr = r(se) return scalar btsattr = return(attr) / return(bseattr) di _newline(3) _column(1) in gr "ATT estimation with the Radius Matching method" di _column(1) in gr "Bootstrapped standard errors" di in gr _newline(1) in text "{hline 57}" di _column(1) in gr "n. treat." /* */ _column(13) in gr "n. contr." /* */ _column(25) in gr " ATT" /* */ _column(37) in gr "Std. Err." /* */ _column(49) in gr " t" di in gr in text "{hline 57}" di _newline(1) _column(1) in ye %9.0f return(ntr) /* */ _column(13) in ye %9.0f return(ncr) /* */ _column(25) in ye %9.3f return(attr) /* */ _column(37) in ye %9.3f return(bseattr) /* */ _column(49) in ye %9.3f return(btsattr) di in gr _newline(1) in text "{hline 57}" di in gr "Note: the numbers of treated and controls refer to actual" di in gr "matches within radius" if `"`detail'"' != `""' { di _newline(3) " Saving results in r()" } qui attr `varlist' `if' `in' `fweight' `iweight' `pweight', pscore(`pscore') `logit' `index' radius(`radius') `comsup' } if `"`detail'"' != `""' { di in ye _newline (3) "***************************************************** " di in ye "End of the estimation with the radius matching method " di in ye "***************************************************** " } end