*! psmatch version 2.0.3Ê Barbara Sianesi August 29, 2001 * added option logit in bs * first version Februay 10, 2001 program define psmatch, rclass version 7.0 # delimit ; syntax varname , [ON(varlist numeric min=1 max=3) ESTimate(varlist) LOGit INDex ID(varname numeric) CALiper(real 1000) OUTcome(varname numeric) KERnel(varname) EPan SPline(varname) NKnots(integer 0) MEan(varname) NEIghbour(integer 0) NEIGHBOR(integer 0) TRicube(varname) LOWess(varname) LIne(varname) BWidth(real 0) BOth noCOMMON QUAlity(varlist numeric) SAving(str) noCount BOOTstrap Reps(int 50) SIze(int -9) Dots Level(real $S_level) DOUBle EVery(integer 1) REPLACE ]; # delimit cr *** CHECKS if `"`id'"' != `""' { sort `id' qui count if `id'==`id'[_n-1] if r(N)!=0 { di in red "more than one obs per `id'" exit } } if (`"`on'"' == `""' & `"`estimate'"' == `""') | (`"`on'"' != `""' & `"`estimate'"' != `""') { di in red "either ON or ESTIMATE has to be specified" exit } if `"`kernel'"' != `""' & `bwidth' == 0 { local bwidth = 0.06 } if `"`kernel'"' == `""' & (`bwidth'>1 | `bwidth'<0) { di in red "bandwidth here between 0 and 1 only" exit } if `"`kernel'"' != `""' & (`"`spline'"' != `""' | `"`tricube'"' != `""' | `"`mean'"' != `""' | `"`line'"' != `""' | `"`lowess'"' != `""') { di in red "only one smoothing method may be specified" exit } if `"`spline'"' != `""' & (`"`kernel'"' != `""' | `"`tricube'"' != `""' | `"`mean'"' != `""' | `"`line'"' != `""' | `"`lowess'"' != `""') { di in red "only one smoothing method may be specified" exit } if `"`mean'"' != `""' & (`"`spline'"' != `""' | `"`tricube'"' != `""' | `"`kernel'"' != `""' | `"`line'"' != `""' | `"`lowess'"' != `""') { di in red "only one smoothing method may be specified" exit } if `"`lowess'"' != `""' & (`"`spline'"' != `""' | `"`tricube'"' != `""' | `"`mean'"' != `""' | `"`line'"' != `""' | `"`kernel'"' != `""') { di in red "only one smoothing method may be specified" exit } if `"`tricube'"' != `""' & (`"`spline'"' != `""' | `"`lowess'"' != `""' | `"`mean'"' != `""' | `"`line'"' != `""' | `"`kernel'"' != `""') { di in red "only one smoothing method may be specified" exit } if `"`line'"' != `""' & (`"`spline'"' != `""' | `"`tricube'"' != `""' | `"`mean'"' != `""' | `"`lowess'"' != `""' | `"`kernel'"' != `""') { di in red "only one smoothing method may be specified" exit } if `"`quality'"' != `""' & (`"`spline'"' != `""' | `"`kernel'"' != `""' | `"`tricube'"' != `""' | `"`mean'"' != `""' | `"`line'"' != `""' | `"`lowess'"' != `""') { di in red "quality cannot be specified" exit } if `"`quality'"' != `""' & `"`saving'"' == `""' { di in red "need to specify the filename" exit } if `"`bootstrap'"' != `""' & `"`estimate'"' == `""' { di in red "to bootstrap, need to specify the regressors in estimate()" exit } if `"`bootstrap'"' != `""' & `"`outcome'"' == `""' & `"`spline'"' == `""' & `"`kernel'"' == `""' & `"`tricube'"' == `""' & `"`mean'"' == `""' & `"`line'"' == `""' & `"`lowess'"' == `""' { di in red "to bootstrap, need to specify the outcome variable either via outcome()" di in red "or by specifying a smoothing type of matching" exit } if `"`bootstrap'"' != `""' & `"`quality'"' != `""' { di in red "cannot specify quality() when bootstrapping" exit } set more off local treated `varlist' if `neighbor' != 0 { local neighbour `neighbor' } if `"`bootstrap'"' != `""' { if `"`outcome'"' != `""' { local type "outcome" local outcvar `outcome' } if `"`kernel'"' != `""' { local type "kernel" local outcvar `kernel' } if `"`spline'"' != `""' { local type "spline" local outcvar `spline' } if `"`mean'"' != `""' { local type "mean" local outcvar `mean' } if `"`line'"' != `""' { local type "line" local outcvar `line' } if `"`lowess'"' != `""' { local type "lowess" local outcvar `lowess' } if `"`tricube'"' != `""' { local type "tricube" local outcvar `tricube' } # delimit ; if `"`saving'"' != `""' { ; bs "psmatch `treated', estimate(`estimate') `index' `logit' caliper(`caliper') bwidth(`bwidth') `epan' `both' nknots(`nknots') neighbour(`neighbour') `nocommon' `type'(`outcvar') noc" "r(effect)", reps(`reps') level(`level') `dots' size(`size') saving(`"`saving'"') `replace' every(`every') `double' ; } ; else if `"`saving'"' == `""' { ; bs "psmatch `treated', estimate(`estimate') `index' `logit' caliper(`caliper') bwidth(`bwidth') `epan' `both' nknots(`nknots') neighbour(`neighbour') `nocommon' `type'(`outcvar') noc" "r(effect)", reps(`reps') level(`level') `dots' size(`size') `double' ; } ; # delimit cr } else if `"`bootstrap'"' == `""' { *** GETTING the PROPENSITY SCORE(S) if `"`estimate'"' != `""' { tempvar score if `"`logit'"' != `""' { logit `treated' `estimate', nolog } else { probit `treated' `estimate', nolog } if `"`index'"' != `""' { qui predict double `score', index } else { qui predict double `score' } } if `"`on'"' != `""' { tokenize `on' local score `1' local score2 `2' local score3 `3' } if `"`score2'"' != `""' & `"`score3'"' == `""' { if `"`spline'"' != `""' | `"`mean'"' != `""' | `"`tricube'"' != `""' | `"`line'"' != `""'| `"`lowess'"' != `""' { n di in red "only one matchvar may be specified" exit } qui { preserve drop if `score'==. | `score2'==. tempname N1 N0 sigma1 sigma2 sigma12 mat ac A0=`score' `score2' if `treated'==0 mat XX0=A0[1..2, 1..2] mat ac A1=`score' `score2' if `treated'==1 mat XX1=A1[1..2, 1..2] qui tabstat `score' `score2', by(`treated') save mat xx0=r(Stat1)'*r(Stat1) mat xx1=r(Stat2)'*r(Stat2) qui count if `treated'==1 scalar `N1'=r(N) qui count if `treated'==0 scalar `N0'=r(N) mat Sinv=(`N1'+`N0'-2)*syminv(XX1-`N1'*xx1+XX0-`N0'*xx0) scalar `sigma1' =Sinv[1,1] scalar `sigma2' =Sinv[2,2] scalar `sigma12'=Sinv[2,1] restore } } if `"`score3'"' != `""' { if `"`spline'"' != `""' | `"`mean'"' != `""' | `"`tricube'"' != `""' | `"`line'"' != `""'| `"`lowess'"' != `""' { n di in red "only one matchvar may be specified" exit } qui { preserve drop if `score'==. | `score2'==. | `score3'==. tempname N1 N0 sigma1 sigma2 sigma3 sigma12 sigma13 sigma23 mat ac A0=`score' `score2' `score3' if `treated'==0 mat XX0=A0[1..3, 1..3] mat ac A1=`score' `score2' `score3' if `treated'==1 mat XX1=A1[1..3, 1..3] qui tabstat `score' `score2' `score3', by(`treated') save mat xx0=r(Stat1)'*r(Stat1) mat xx1=r(Stat2)'*r(Stat2) qui count if `treated'==1 scalar `N1'=r(N) qui count if `treated'==0 scalar `N0'=r(N) mat Sinv=(`N1'+`N0'-2)*syminv(XX1-`N1'*xx1+XX0-`N0'*xx0) scalar `sigma1'=Sinv[1,1] scalar `sigma2'=Sinv[2,2] scalar `sigma3'=Sinv[3,3] scalar `sigma12'=Sinv[1,2] scalar `sigma13'=Sinv[1,3] scalar `sigma23'=Sinv[2,3] restore } } *** ONE-TO-ONE MATCHING if `"`kernel'"'== `""' & `"`lowess'"' == `""' & `"`tricube'"' == `""' & `"`line'"' == `""' & `"`spline'"' == `""' & `"`mean'"' == `""' { quietly { cap drop _times cap drop _matchdif tempvar newid gsort -`treated' gen `newid'=_n local identifier `"`id'"' if `"`score2'"' == `""' { tempvar fdif bdif fym bym fid bid sort `score' `treated' `id' `newid' local i = 1 local fstop = 0 local fcount = 0 gen `fdif' =. gen `fym' =. gen `fid' =. while `fstop' == 0 { local lastfcount = `fcount' count if `fdif'==. & `treated'==1 local fcount = r(N) if `fcount' == `lastfcount' { local fstop = 1 } else { if r(N) != 0 { replace `fdif' = `score' - `score'[_n+`i'] if `treated'==1 & `treated'[_n+`i']==0 & `fdif'==. if `"`outcome'"' != `""' { replace `fym' = `outcome'[_n+`i'] if `treated'==1 & `treated'[_n+`i']==0 & `fym'==. } if `"`id'"' != `""' { replace `fid' = `id'[_n+`i'] if `treated'==1 & `treated'[_n+`i']==0 & `fid'==. } else if `"`id'"' == `""' { replace `fid' = `newid'[_n+`i'] if `treated'==1 & `treated'[_n+`i']==0 & `fid'==. } local i = `i' + 1 } else if r(N)== 0 { local fstop = 1 } } } local i = 1 local bstop = 0 local bcount = 0 gen `bdif' =. gen `bym' =. gen `bid' =. while `bstop' == 0 { local lastbcount = `bcount' count if `bdif'==. & `treated'==1 local bcount = r(N) if `bcount' == `lastbcount' { local bstop = 1 } else { if r(N) != 0 { replace `bdif' = `score' - `score'[_n-`i'] if `treated'==1 & `treated'[_n-`i']==0 & `bdif'==. if `"`outcome'"' != `""' { replace `bym' = `outcome'[_n-`i'] if `treated'==1 & `treated'[_n-`i']==0 & `bym'==. } if `"`id'"' != `""' { replace `bid' = `id'[_n-`i'] if `treated'==1 & `treated'[_n-`i']==0 & `bid'==. } else if `"`id'"' == `""' { replace `bid' = `newid'[_n-`i'] if `treated'==1 & `treated'[_n-`i']==0 & `bid'==. } local i = `i' + 1 } else if r(N)== 0 { local bstop = 1 } } } gen _matchdif = min(abs(`fdif'), abs(`bdif')) if min(abs(`fdif'), abs(`bdif'))<`caliper' & `treated'==1 if `"`outcome'"' != `""' { cap drop _m`outcome' gen _m`outcome' = `fym' if abs(`fdif')=abs(`bdif') & abs(`bdif')<`caliper' & `treated'==1 } tempvar tmid t1 t2 t3 gen `tmid' = `fid' if abs(`fdif')=abs(`bdif') & abs(`bdif')<`caliper' & `treated'==1 sort `tmid' gen byte `t1'=1 if `tmid'!=`tmid'[_n-1] & `treated'==1 egen `t2'=count(`tmid'), by(`tmid') replace `t2'=. if `t1'!=1 if `"`id'"' == `""' { gen `t3'=`newid' if `treated'==0 } if `"`id'"' != `""' { gen `t3'=`id' if `treated'==0 } replace `t3'=`tmid' if `treated'==1 & `tmid'!=. sort `t3' `treated' `t1' cap drop _times gen _times=1 if `treated'==1 & `tmid'!=. replace _times=`t2'[_n+1] if `treated'==0 & `t1'[_n+1]==1 if `"`id'"' != `""' { cap drop _matchedid gen _matchedid = `tmid' } } else if `"`score2'"' != `""' { cap log off tempvar indic dif mid tempname maxid count if `treated'==1 scalar `maxid'=r(N) gen byte _times=0 gen _matchdif=0 if `treated'==1 gen `mid'=. if `"`id'"' != `""' { cap drop _matchedid gen _matchedid=0 if `treated'==1 } local i = 1 while `i'<= `maxid' { cap drop `indic' gen byte `indic' = 1 if `newid'==`i' sort `indic' cap drop `dif' if `"`score2'"' != `""' & `"`score3'"' == `""' { gen `dif'=`sigma1'*(`score'[1]-`score')^2+`sigma2'*(`score2'[1]-`score2')^2+2*`sigma12'*(`score'[1]-`score')*(`score2'[1]-`score2') if `treated'==0 } if `"`score2'"' != `""' & `"`score3'"' != `""' { # delimit ; gen `dif'=`sigma1'*(`score'[1]-`score')^2+`sigma2'*(`score2'[1]-`score2')^2+ `sigma3'*(`score3'[1]-`score3')^2+ 2*`sigma12'*(`score'[1]-`score')*(`score2'[1]-`score2')+ 2*`sigma13'*(`score'[1]-`score')*(`score3'[1]-`score3')+ 2*`sigma23'*(`score2'[1]-`score2')*(`score3'[1]-`score3') if `treated'==0; # delimit cr } sort `dif' `id' replace _times=_times+1 if `dif'[1]<`caliper' & (`indic'==1 | _n==1) replace _matchdif=`dif'[1] if _times==1 & `indic'==1 replace `mid'=`newid'[1] if _times==1 & `indic'==1 if `"`id'"' != `""' { replace _matchedid=`id'[1] if _times==1 & `indic'==1 } if `"`count'"' == `""' { n di _skip(6) `maxid'-`i' } local i = `i'+1 } replace _times=. if _times==0 replace _matchdif=. if _times==. replace _times=1 if `treated'==1 & _matchdif!=. if `"`outcome'"' != `""' { cap drop _m`outcome' sort `newid' gen _m`outcome' = `outcome'[`mid'] if `treated'==1 } } lab var _times "no. of times used" lab var _matchdif "difference in score" cap lab var _matchedid "`identifier' of matched control" cap lab var _m`outcome' "`outcome' of the matched control" if `"`count'"' == `""' { n di _newline(3) _skip(3) in w "Now use _times~=. to identify the matched treated and matched controls" n di _skip(3) in w "Use [fw=_times] in later analyses, or else type: expand _times" } cap log on if `"`outcome'"' != `""' { tempname mean1 mean0 number weight var1 var0 stderr sum `outcome' if `treated' == 1 [fw=_times] scalar `mean1' = r(mean) scalar `number' = r(N) scalar `var1' = r(Var) sum `outcome' if `treated' == 0 [fw=_times] scalar `mean0' = r(mean) sum `outcome' if `treated' == 0 & _times!=. scalar `var0' = r(Var) tempvar we gen `we'=_times^2 if `treated'==0 sum `we' scalar `weight' = r(sum) scalar `stderr' = sqrt( (`var1')/`number' + (`weight'/(`number'^2))*`var0' ) n di _newline(3) _skip(3) in g "Mean " in w "`outcome'" in g " of matched treated = " in y `mean1' n di _newline(1) _skip(3) in g "Mean " in w "`outcome'" in g " of matched controls = " in y `mean0' n di _newline(1) _skip(3) in g "Effect = " in y `mean1'-`mean0' n di _newline(1) _skip(3) in g "Std err = " in y `stderr' n di _newline(1) _skip(3) in w "Note: takes account of possibly repeated use of control observations" n di _skip(3) in w " but NOT of estimation of propensity score." n di _newline(1) _skip(3) in g "T-statistics for " in w "H0: effect=0" in g " is " in y (`mean1'-`mean0')/`stderr' return scalar mean1 = `mean1' return scalar mean0 = `mean0' return scalar effect= `mean1'-`mean0' } if `"`quality'"' != `""' { preserve tempfile user save `user' drop _all gen byte temp=1 cap save `"`saving'"', replace foreach bit of local quality { use `user' gen str15 regressor=substr("`bit'", 1, 15) sum `bit' if `treated'==1 gen mean1 = r(mean) gen var1 = r(Var) sum `bit' if `treated'==1 [fw=_times] gen mean1m = r(mean) gen var1m = r(Var) sum `bit' if `treated'==0 gen mean0 = r(mean) gen var0 = r(Var) sum `bit' if `treated'==0 [fw=_times] gen mean0m = r(mean) gen var0m = r(Var) keep in 1 keep regressor mean* var* append using `"`saving'"' save `"`saving'"', replace } drop if temp==1 drop temp gen biasbef=100*(mean1-mean0)/sqrt((var1+var0)/2) gen biasaft=100*(mean1m-mean0m)/sqrt((var1+var0)/2) gen abiasbef=abs(biasbef) gen abiasaft=abs(biasaft) gen absreduc=-100*(abiasaft-abiasbef)/abiasbef drop var* lab var mean1 "mean in full treated group" lab var mean0 "mean in full non-treated group" lab var mean1m "mean in matched treated group" lab var mean0m "mean in matched control group" lab var biasbef "standardised % bias before matching" lab var biasaft "standardised % bias after matching" lab var abiasbef "absolute std % bias before matching" lab var abiasaft "absolute std % bias after matching" lab var absreduc "% reduction in absolute bias" save, replace restore n di _newline(1) _skip(3) in w "Dataset with match quality information " in g "`saving'.dta" in w " has been created!" } } } *** SMOOTHING * KERNEL MATCHING if `"`kernel'"' != `""' { quietly { local outcome `"`kernel'"' cap drop _m`outcome' cap drop _s`outcome' tempvar newid gsort -`treated' gen `newid'=_n if `treated'==1 tempvar dif weight tempname min max min2 max2 maxid count if `treated'==1 scalar `maxid'=r(N) gen _m`outcome'=. if `"`both'"' != `""' { gen _s`outcome'=. } cap log off local i=1 while `i'<=`maxid' { cap drop `dif' if `"`score2'"' != `""' & `"`score3'"' == `""' { if `"`both'"' != `""' { gen `dif'=`sigma1'*(`score'[`i']-`score')^2+`sigma2'*(`score2'[`i']-`score2')^2+2*`sigma12'*(`score'[`i']-`score')*(`score2'[`i']-`score2') } else { gen `dif'=`sigma1'*(`score'[`i']-`score')^2+`sigma2'*(`score2'[`i']-`score2')^2+2*`sigma12'*(`score'[`i']-`score')*(`score2'[`i']-`score2') if `treated'==0 } } if `"`score2'"' != `""' & `"`score3'"' != `""' { if `"`both'"' != `""' { # delimit ; gen `dif'=`sigma1'*(`score'[`i']-`score')^2+`sigma2'*(`score2'[`i']-`score2')^2+ `sigma3'*(`score3'[`i']-`score3')^2+ 2*`sigma12'*(`score'[`i']-`score')*(`score2'[`i']-`score2')+ 2*`sigma13'*(`score'[`i']-`score')*(`score3'[`i']-`score3')+ 2*`sigma23'*(`score2'[`i']-`score2')*(`score3'[`i']-`score3'); # delimit cr } else { # delimit ; gen `dif'=`sigma1'*(`score'[`i']-`score')^2+`sigma2'*(`score2'[`i']-`score2')^2+ `sigma3'*(`score3'[`i']-`score3')^2+ 2*`sigma12'*(`score'[`i']-`score')*(`score2'[`i']-`score2')+ 2*`sigma13'*(`score'[`i']-`score')*(`score3'[`i']-`score3')+ 2*`sigma23'*(`score2'[`i']-`score2')*(`score3'[`i']-`score3') if `treated'==0; # delimit cr } } if `"`score2'"' == `""' & `"`score3'"' == `""' { gen `dif'=abs(`score'-`score'[`i']) } if `"`epan'"'!= `""' { gen `weight' = 1-(`dif'/ `bwidth')^2 if abs(`dif'/`bwidth')<=1 } else { gen `weight' = normden(`dif'/ `bwidth') } su `kernel' [aw=`weight'] if `treated'==0, meanonly replace _m`outcome' = r(mean) in `i' if `"`both'"' != `""' { su `kernel' [aw=`weight'] if `treated'==1, meanonly replace _s`outcome' = r(mean) in `i' } drop `weight' if `"`count'"' == `""' { n di _skip(6) `maxid'-`i' } local i = `i'+1 } if `"`common'"' == `""' { **** imposing COMMON SUPPORT -- on the treated only sum `score' if `treated'==0 scalar `min'=r(min) sum `score' if `treated'==0 scalar `max'=r(max) replace _m`outcome' = . if (`score'>`max' | `score'<`min') & `treated'==1 if `"`both'"' != `""' { replace _s`outcome'=. if (`score'>`max' | `score'<`min') & `treated'==1 } if `"`score2'"' != `""' { sum `score2' if `treated'==0 scalar `min'=r(min) sum `score2' if `treated'==0 scalar `max'=r(max) replace _m`outcome' = . if (`score2'>`max' | `score2'<`min') & `treated'==1 if `"`both'"' != `""' { replace _s`outcome'=. if (`score2'>`max' | `score2'<`min') & `treated'==1 } } if `"`score3'"' != `""' { sum `score3' if `treated'==0 scalar `min'=r(min) sum `score3' if `treated'==0 scalar `max'=r(max) replace _m`outcome' = . if (`score3'>`max' | `score3'<`min') & `treated'==1 if `"`both'"' != `""' { replace _s`outcome'=. if (`score3'>`max' | `score3'<`min') & `treated'==1 } } count if `treated'==1 if r(N)==0 { n di in red "none of the treated lies within the common support" exit } } lab var _m`outcome' "matched smoothed `outcome'" cap lab var _s`outcome' "treated smoothed `outcome'" } if `"`count'"' == `""' { n di _newline(3) _skip(3) in g "_m`outcome'" in w " is defined only for treated (and within the common support);" n di _skip(3) in w "It should be compared to the " in g `"`kernel'"' in w " (or" in g "_s`outcome'" in w ") for those treated only," n di _skip(3) in w "i.e. with _m`outcome'~=. } tempname mean1 mean0 if `"`both'"' != `""' { qui sum _s`outcome' if _m`outcome'!=. scalar `mean1' = r(mean) } else { qui sum `kernel' if `treated'==1 & _m`outcome'!=. scalar `mean1' = r(mean) } cap log on qui sum _m`outcome' scalar `mean0' = r(mean) n di _newline(3) _skip(3) in g "Mean " in w "`outcome'" in g " of matched treated = " in y `mean1' n di _newline(1) _skip(3) in g "Mean " in w "`outcome'" in g " of matched controls = " in y `mean0' n di _newline(1) _skip(3) in g "Effect = " in y `mean1'-`mean0' return scalar mean1 = `mean1' return scalar mean0 = `mean0' return scalar effect= `mean1'-`mean0' } * OTHER quietly { if `"`lowess'"' != `""' | `"`tricube'"' != `""' | `"`spline'"' != `""' | `"`line'"' != `""'| `"`mean'"' != `""' { * SPLINE if `"`spline'"' != `""' { local outcome `"`spline'"' cap drop _m`outcome' cap drop _s`outcome' spline `outcome' `score' if `treated'==0, gen(_m`outcome') nknots(`nknots') nograph if `"`both'"' != `""' { spline `outcome' `score' if `treated'==1, gen(_s`outcome') nknots(`nknots') nograph } } * MEAN if `"`mean'"' != `""' { local outcome `"`mean'"' cap drop _m`outcome' cap drop _s`outcome' if `neighbour' != 0 { qui count if `treated' == 0 local bwidth = `neighbour'/r(N) } ksm `outcome' `score' if `treated'==0, gen(_m`outcome') bwidth(`bwidth') nograph if `"`both'"' != `""' { ksm `outcome' `score' if `treated'==1, gen(_s`outcome') bwidth(`bwidth') nograph } } * TRICUBE KERNEL if `"`tricube'"' != `""' { local outcome `"`tricube'"' cap drop _m`outcome' cap drop _s`outcome' ksm `outcome' `score' if `treated'==0, weight gen(_m`outcome') bwidth(`bwidth') nograph if `"`both'"' != `""' { ksm `outcome' `score' if `treated'==1, weight gen(_s`outcome') bwidth(`bwidth') nograph } } * LINE if `"`line'"' != `""' { local outcome `"`line'"' cap drop _m`outcome' cap drop _s`outcome' ksm `outcome' `score' if `treated'==0, line gen(_m`outcome') bwidth(`bwidth') nograph if `"`both'"' != `""' { ksm `outcome' `score' if `treated'==1, line gen(_s`outcome') bwidth(`bwidth') nograph } } * LOWESS if `"`lowess'"' != `""' { local outcome `"`lowess'"' cap drop _m`outcome' cap drop _s`outcome' ksm `outcome' `score' if `treated'==0, lowess gen(_m`outcome') bwidth(`bwidth') nograph if `"`both'"' != `""' { ksm `outcome' `score' if `treated'==1, lowess gen(_s`outcome') bwidth(`bwidth') nograph } } tempvar fdif bdif fym bym sort `score' `treated' `id' local i = 1 local fstop = 0 local fcount = 0 gen `fdif' =. gen `fym' =. while `fstop' == 0 { local lastfcount = `fcount' count if `fdif'==. & `treated'==1 local fcount = r(N) if `fcount' == `lastfcount' { local fstop = 1 } else { if r(N) != 0 { replace `fdif' = `score' - `score'[_n+`i'] if `treated'==1 & `treated'[_n+`i']==0 & `fdif'==. replace `fym' = _m`outcome'[_n+`i'] if `treated'==1 & `treated'[_n+`i']==0 & `fym'==. local i = `i' + 1 } else if r(N)== 0 { local fstop = 1 } } } local i = 1 local bstop = 0 local bcount = 0 gen `bdif' =. gen `bym' =. while `bstop' == 0 { local lastbcount = `bcount' count if `bdif'==. & `treated'==1 local bcount = r(N) if `bcount' == `lastbcount' { local bstop = 1 } else { if r(N) != 0 { replace `bdif' = `score' - `score'[_n-`i'] if `treated'==1 & `treated'[_n-`i']==0 & `bdif'==. replace `bym' = _m`outcome'[_n-`i'] if `treated'==1 & `treated'[_n-`i']==0 & `bym'==. local i = `i' + 1 } else if r(N)== 0 { local bstop = 1 } } } replace _m`outcome' = `fym' if abs(`fdif')=abs(`bdif') & `treated'==1 replace _m`outcome' =. if `treated'==0 cap replace _s`outcome'=. if _m`outcome'==. lab var _m`outcome' "matched smoothed `outcome'" cap lab var _s`outcome' "treated smoothed `outcome'" if `"`common'"' == `""' { **** imposing COMMON SUPPORT -- on the treated only tempname min max sum `score' if `treated'==0 scalar `min'=r(min) sum `score' if `treated'==0 scalar `max'=r(max) replace _m`outcome'=. if (`score'>`max' | `score'<`min') & `treated'==1 cap replace _s`outcome'=. if (`score'>`max' | `score'<`min') & `treated'==1 count if _m`outcome'!=. if r(N)==0 { n di in red "none of the treated lies within the common support" exit } } if `"`count'"' == `""' { n di _newline(3) _skip(3) in g "_m`outcome'" in w " is defined only for treated (and within the common support);" n di _skip(3) in w "It should be compared to the " in g `"`kernel'"' in w " (or" in g "_s`outcome'" in w ") for those treated only," n di _skip(3) in w "i.e. with _m`outcome'~=. } tempname mean1 mean0 if `"`both'"' != `""' { qui sum _s`outcome' scalar `mean1' = r(mean) } else { qui sum `outcome' if `treated'==1 & _m`outcome'!=. scalar `mean1' = r(mean) } cap log on qui sum _m`outcome' scalar `mean0' = r(mean) n di _newline(3) _skip(3) in g "Mean " in w "`outcome'" in g " of matched treated = " in y `mean1' n di _newline(1) _skip(3) in g "Mean " in w "`outcome'" in g " of matched controls = " in y `mean0' n di _newline(1) _skip(3) in g "Effect = " in y `mean1'-`mean0' return scalar mean1 = `mean1' return scalar mean0 = `mean0' return scalar effect= `mean1'-`mean0' } set more on } } end