capture program drop margintegrate program margintegrate, rclass //sortpreserve version 9 set matsize 800 *!version 1.0 cagregory 31 may 2011 syntax varlist(min=3 max=3 numeric) [if] [in] , /* */bw(numlist min=2 max=2) /* */[nograph /* */n(integer 50) /* */GENerate(namelist) /* */ ci(string) /* */ boot(integer 0) /* */ trim(real 0)] global nobs = _N tempname programid xgridpt idgrid ygridpt varhat idout local yvar: word 1 of `varlist' local xvar1: word 2 of `varlist' local xvar2: word 3 of `varlist' capture drop _merge sort `xvar1' `xvar2', stable qui g `programid'=_n qui g `idout' = `programid' tempname wc local `wc': word count `generate' if ``wc''>=1 { local rhat: word 1 of `generate' } else { local rhat } capture confirm new variable `rhat' if _rc!=0 { local tempnum = round(100*runiform()) disp as text "`rhat' already exists" disp as text "`rhat' renamed `rhat'`tempnum'" rename `rhat' `rhat'`tempnum' } if ``wc''>1 { local vhat: word 2 of `generate' } else { local vhat } capture confirm new variable `vhat' if _rc!=0 { local tempnum = round(100*runiform()) disp as text "`vhat' already exists" disp as text "`vhat' renamed `vhat'`tempnum'" rename `vhat' `vhat'`tempnum' } tempfile marginadd sort `programid' qui save `marginadd' marksample touse qui keep if `touse' /*trimming*/ if `trim'!=0 { local trub = 100-(`trim'/2) local trlb = `trim'/2 _pctile `xvar1', p(`trlb',`trub') //trimming values local xlb = round(r(r1),.01) local xub = round(r(r2),.01) disp as text "Trimming Lower Bound is `xlb'" disp as text "Trimming Upper Bound is `xub'" qui drop if `xvar1'<`xlb' | `xvar1'> `xub' } /* get estimation grid*/ getgrid_p `yvar' `xvar1' `xvar2' `programid', points(`n') tempname estgrid outmat varmat idmat matrix `estgrid' = r(estgrid) //matrix list `estgrid' /*output matrices*/ global r = rowsof(`estgrid') /*integral of squared kernel function--needed for variance*/ local bw1: word 1 of `bw' local bw2: word 2 of `bw' tempname hnopt1 hnopt2 local `hnopt1' = `bw1'/2 local `hnopt2' = `bw2'/2 gaussquadk2 `xvar1' `xvar2', hvec(``hnopt1'' ``hnopt2'') tempname intksquared global intksquared = r(intk2) //disp "integral k2="$intksquared /*main estimates*/ miestimate `yvar' `xvar1' `xvar2' `programid', h(``hnopt1'' ``hnopt2'') estmat(`estgrid') tempname outMat varMat idMat outVec varVec bootidVec boot_id matrix `outMat' = r(out_mat) matrix `varMat' = r(var_mat) matrix `idMat' = r(id_mat) matrix `outVec' = J(1,$r,0) matrix `varVec' = J(1,$r, 0) matrix `bootidVec' = J(1,$r,0) forvalues i = 1/$r { forvalues j = 1/$r { matrix `varVec'[1,`i'] = `varVec'[1,`i']+`varMat'[`j',`i'] //sample averaging=marginal expectation matrix `outVec'[1,`i'] = `outVec'[1,`i']+`outMat'[`j',`i'] matrix `bootidVec'[1,`i'] = $r*`i' } } matrix `varVec' = (`varVec'/$r)' matrix `outVec' = (`outVec'/$r)' matrix `bootidVec' = (`bootidVec'/$r)' global varhat varhat matrix colnames `varVec' = `vhat' matrix colnames `outVec' = `rhat' matrix colnames `bootidVec' = `boot_id' matrix `idMat' = `idMat',`varVec',`outVec',`bootidVec' //matrix list `idMat' qui drop _all qui svmat double `idMat', names(col) qui drop ygrid x1grid x2grid //qui drop if `rhat'==. | `rhat'==0 rename idgrid `programid' sort `programid' merge `programid' using `marginadd' cap drop _merge if `boot'==0 { if "`graph'"=="" { if "`ci'"!="" { qui sum `xvar1' tempname tail vcons ub lb local `tail' = (1-(`ci'/100))/2 local `vcons' = abs(invnormal(``tail'')) qui g `ub' = `rhat'+``vcons''*(sqrt(`vhat')) qui g `lb' = `rhat'-``vcons''*(sqrt(`vhat')) twoway rarea `ub' `lb' `xvar1' , sort color(eltblue) /* */ || line `rhat' `xvar1' , sort color(black) t1title("Marginal Integration Estimate") /* */ xtitle("`xvar1'") ytitle("`yvar'") legend(lab(1 "`ci'% CI") /* */ lab(2 "Marginal Integration Estimate")) } else { twoway line `rhat' `xvar1', sort t1title("Marginal Integration Estimate") xtitle("`xvar1'") /// ytitle("`yvar'") } } } else { sort `boot_id' qui save `marginadd', replace disp as text "Executing Bootstrap Estimation of Variance" bootmi `yvar' `xvar1' `xvar2', h(``hnopt1'' ``hnopt2'') reps(`boot') tempname bootr matrix `bootr' = r(bootsd) tempname bootmatid bootmatsd matrix colnames `bootr'=`bootmatid' `bootmatsd' svmat double `bootr', names(col) keep `bootmatid' `bootmatsd' rename `bootmatid' `boot_id' sort `boot_id' qui merge `boot_id' using `marginadd' qui replace `vhat' = `bootmatsd' if "`graph'"=="" { if "`ci'"!="" { qui sum `vhat' local bootsigma = r(mean) qui drop if `vhat'>(3*`bootsigma') tempname x1max x1min qui sum `xvar1' local `x1max'=r(max) local `x1min'=r(min) tempname tail vcons ub lb local `tail' = (1-(`ci'/100))/2 local `vcons' = abs(invnormal(``tail'')) qui g `ub' = `rhat'+``vcons''*(sqrt(`vhat')) qui g `lb' = `rhat'-``vcons''*(sqrt(`vhat')) twoway rarea `ub' `lb' `xvar1' if `xvar1'<=``x1max'', sort color(eltblue) /* */ || line `rhat' `xvar1', sort color(black) t1title("Marginal Integration Estimate") /* */ xtitle("`xvar1'") ytitle("`yvar'") legend(lab(1 "`ci'% Bootstrap CI") /* */ lab(2 "Marginal Integration Estimate")) } else { twoway line `rhat' `xvar1', sort t1title("Marginal Integration Estimate") xtitle("`xvar1'") /// ytitle("`yvar'") } } } end program define getgrid_p, rclass syntax varlist (min=4 max=4), points(integer) local y: word 1 of `varlist' local x1: word 2 of `varlist' local x2: word 3 of `varlist' local progid: word 4 of `varlist' tempname grid matrix `grid' = J(`points',4,0) local u=round(`points'+1) sort `x1' `x2', stable tempname newid pctx1 del pid ygrid xgrid2 tempid pctxvar oldpid qui g `newid'=_n pctile `pctxvar'=`x1', n(`u') forvalues i = 1/`points' { scalar `pctx1' = `pctxvar'[`i'] matrix `grid'[`i',1] = scalar(`pctx1') qui gen `del' = abs(`x1' - scalar(`pctx1')) qui sum `del' qui sum `newid' if `del'==r(min) if `i'>1 { scalar `oldpid' = scalar(`pid') //scalar list `oldpid' } else { scalar `oldpid' = -99 //scalar list `oldpid' } scalar `pid' = max(round(r(mean)),`oldpid') if scalar(`pid')==scalar(`oldpid') { scalar `pid' = scalar(`pid')+1 } qui sum `x2' if `newid'==scalar(`pid') scalar `xgrid2' = r(mean) qui sum `y' if `newid'==scalar(`pid') scalar `ygrid' = r(mean) qui sum `progid' if `newid'==scalar(`pid') scalar `tempid' = round(r(mean)) matrix `grid'[`i',2] = scalar(`xgrid2') matrix `grid'[`i',3] = scalar(`tempid') matrix `grid'[`i',4] = scalar(`ygrid') drop `del' } matrix colnames `grid'= x1grid x2grid idgrid ygrid return matrix estgrid `grid' end program define getgrid, rclass syntax varlist (min=4 max=4), points(string) local y: word 1 of `varlist' local x1: word 2 of `varlist' local x2: word 3 of `varlist' local progid: word 4 of `varlist' capture confirm new variable samplemark if _rc { rename samplemark smark_old di as text "samplemark already exists" di as text "samplemark renamed smark_old" } samplemark `x1' `x2', gridsize("`points'") gen(samplemark) qui { tempvar countid delta newid tempname grid xgrid1 xgrid2 ygrid tempid points sum samplemark local `points' = r(sum) sort `x1' `x2', stable g `countid' = sum(samplemark) g `delta' = `countid'-`countid'[_n-1] replace `countid' = `delta'*`countid' matrix `grid' = J(``points'',4,.) sort `x1', stable qui g `newid'=_n forvalues i = 1/``points'' { sum `x1' if `countid'==`i' scalar `xgrid1' = r(mean) matrix `grid'[`i',1] = scalar(`xgrid1') qui sum `x2' if `countid'==`i' scalar `xgrid2' = (r(mean)) qui sum `y' if `countid'==`i' scalar `ygrid' = r(mean) qui sum `progid' if `countid'==`i' scalar `tempid' = round(r(mean)) matrix `grid'[`i',2]= scalar(`xgrid2') matrix `grid'[`i',3]= scalar(`tempid') matrix `grid'[`i',4]= scalar(`ygrid') } } global names x1grid x2grid idgrid ygrid matrix colnames `grid'= $names //x1grid x2grid idgrid ygrid return matrix estgrid `grid' end program define samplemark syntax varlist , GRIDsize(string) [GENerate(name)] local w: word count varlist sort `varlist', stable tempvar markid g `markid'=_n local N = _N local gridobs=`gridsize' local interval = round((`N'/`gridobs'),1) if "`generate'"=="" { g samplemark = 0 forv i=1/`gridobs' { local here = `i'*`interval' qui replace samplemark=1 if `markid'==`here' } } else { g `generate' = 0 forv i=1/`gridobs' { local here = `i'*`interval' qui replace `generate'=1 if `markid'==`here' } } end program define miestimate, rclass syntax varlist (min=4 max=4), h(numlist min=2 max=2) estmat(name) local y: word 1 of `varlist' local x1: word 2 of `varlist' local x2: word 3 of `varlist' local progid: word 4 of `varlist' local h1: word 1 of `h' local h2: word 2 of `h' tempname x1gridpt gridobs1 del1 kdel1 wgt1 fz dens1 gridobs2 x2gridpt del2 kdel2 wgt2 /* */ newwgt sumwgt newwgt2 jointfx2 yhat mse wgt2_2 fx2_2 varhat outmat varmat idmat /* */ fx1 matrix `outmat' = J($r,$r,.) matrix `varmat' = J($r,$r,0) matrix `idmat' = J($r,4,.) qui { forvalues j = 1/$r { sort `x1' , stable scalar `x1gridpt' = `estmat'[`j',1] scalar `gridobs1' = `estmat'[`j',3] matrix `idmat' = (`estmat'[1..$r,4], `estmat'[1..$r,1], `estmat'[1..$r,2], `estmat'[1..$r,3]) g `del1'=`x1'-scalar(`x1gridpt') g `kdel1'= (abs(`del1')/`h1')^3 replace `kdel1' = 1 if `kdel1'>1 g `wgt1' = ((70/81)*(1-`kdel1'))^3 disp "wgt1" sum `wgt1' local sigwgt1 = r(sum) g `dens1' = `wgt1'/`sigwgt1' disp "dens" sum `dens1' if `progid'==scalar(`gridobs1') scalar `fz' = r(mean) di as text "fz="scalar(`fz') qui sum `dens1' if `progid'==scalar(`gridobs1') scalar `fx1' = r(max) forvalues k = 1/$r { sort `x2', stable scalar `x2gridpt'=`estmat'[`k',2] scalar `gridobs2'=`estmat'[`k',3] g `del2'=`x2'-scalar(`x2gridpt') disp "del2" sum `del2' g `kdel2'= (abs(`del2')/`h2')^3 disp "kdel2" sum `kdel2' replace `kdel2' = 1 if `kdel2'>1 g `wgt2' = ((70/81)*(1-`kdel2'))^3 sum `wgt2' local sigwgt2=r(sum) g `newwgt' = `wgt1'*`wgt2' qui sum `newwgt' scalar `sumwgt' = r(sum) //qui replace `newwgt' = `newwgt'/`sumwgt' //joint kernel weight qui count if `newwgt'>0 & `newwgt'!=. scalar obs = r(N) scalar list obs disp "del1" sum `del1' if `newwgt'>0 disp "y" sum `y' if `newwgt'>0 if scalar(obs) >5 { reg `y' `del1' [weight=`newwgt'] scalar `yhat' = _b[_cons] scalar `mse' = (e(rmse))^2 } else { scalar `yhat' = 0 scalar `mse' = 0 } g `newwgt2' = `newwgt'^2 sum `newwgt2' /*if `progid'==scalar(`gridobs2')*/ //joint kwgt^2: needed for variance scalar `jointfx2' = r(max) g `wgt2_2' = `wgt2'^2 sum `wgt2_2' /*if `progid'==scalar(`gridobs2')*/ scalar `fx2_2' = r(max) disp "yhat="scalar(`yhat') disp "fz="`fz' disp "k2="$intksquared disp "mse="scalar(`mse') disp "fx2_2="scalar(`fx2_2') disp "joint="scalar(`jointfx2') scalar `varhat' =scalar(`fx1')*($intksquared)*((scalar(`mse')*scalar(`fx2_2'))/scalar(`jointfx2')) disp "varhat="scalar(`varhat') matrix `varmat'[`k',`j'] = scalar(`varhat') matrix `outmat'[`k',`j'] = scalar(`yhat') drop `del2' `kdel2' `wgt2' `newwgt' `newwgt2' `wgt2_2' } drop `del1' `kdel1' `wgt1' `dens1' } } return matrix var_mat `varmat' return matrix out_mat `outmat' return matrix id_mat `idmat' end /*bootstrap estimates*/ program define bootmi, rclass syntax varlist (min=3 max=3) , h(numlist min=2 max=2) reps(integer) tempname bootMat bootid local yboot: word 1 of `varlist' local x1boot: word 2 of `varlist' local x2boot: word 3 of `varlist' local h1boot: word 1 of `h' local h2boot: word 2 of `h' capture confirm new variable bootid if _rc!=0 { local tempnum = round(100*runiform()) disp as text "bootid already exists" disp as text "bootid renamed oldid`tempnum'" rename bootid oldid`tempnum' } tempfile bootdata forvalues i = 1/`reps' { capture confirm new var bootout`i' if _rc!=0 { local rc _rc disp as error "bootout`i' already exists" error `rc' } preserve bsample $nobs tempname bootmat`i' boottempid sort `x1boot' `x2boot', stable qui g `boottempid' = _n //sum `x1boot' `x2boot' `boottempid' getgrid_p `yboot' `x1boot' `x2boot' `boottempid', points($r) tempname bootgrid matrix `bootgrid' = r(estgrid) bootestimate `yboot' `x1boot' `x2boot', h(`h1boot' `h2boot') bootest(`bootgrid') matrix `bootmat`i'' = r(bootoutvec) matrix colnames `bootmat`i'' = bootid bootout`i' svmat double `bootmat`i'', names(col) keep bootid bootout`i' qui keep if bootid!=. if `i'==1 { sort bootid qui save `bootdata', replace restore } else if (`i'>1 & `i'< `reps') { sort bootid qui merge bootid using `bootdata' capture drop _merge sort bootid qui save `bootdata', replace restore } else if `i'==`reps' { sort bootid qui merge bootid using `bootdata' capture drop _merge sort bootid egen bootsd = rowsd(bootout`reps'-bootout1) keep bootid bootsd tempname R mkmat bootid bootsd, mat(`R') //matrix list `R' restore } } return matrix bootsd `R' end program define bootestimate, rclass syntax varlist (min=3 max=3), h(numlist min=2 max=2) bootest(name) local y: word 1 of `varlist' local x1: word 2 of `varlist' local x2: word 3 of `varlist' local h1: word 1 of `h' local h2: word 2 of `h' tempname x1gridptb gridobs1b del1b kdel1b wgt1b gridobs2b x2gridptb del2b kdel2b wgt2b /* */ newwgtb sumwgtb jointfx2 yhatb outVecb outmatb kprod Ykmean ksum matrix `outmatb' = J($r,$r,.) //matrix `bootmat' = J($r,4,.) qui { forvalues j = 1/$r { sort `x1' , stable scalar `x1gridptb' = `bootest'[`j',1] scalar list `x1gridptb' scalar `gridobs1b' = `bootest'[`j',3] qui g `del1b'=`x1'-scalar(`x1gridptb') qui g `kdel1b'= (abs(`del1b')/`h1')^3 replace `kdel1b' = 1 if `kdel1b'>1 qui g `wgt1b' = ((70/81)*(1-`kdel1b'))^3 qui sum `wgt1b' local sumkern = r(sum) qui g `kprod' = `wgt1b'*`y' qui g `ksum' = sum(`kprod') qui sum `ksum' local sumprod = r(max) scalar `Ykmean' = `sumprod'/`sumkern' forvalues k = 1/$r { sort `x2', stable scalar `x2gridptb'=`bootest'[`k',2] scalar `gridobs2b'=`bootest'[`k',3] g `del2b'=`x2'-scalar(`x2gridptb') g `kdel2b'= (abs(`del2b')/`h2')^3 replace `kdel2b' = 1 if `kdel2b'>1 g `wgt2b' = ((70/81)*(1-`kdel2b'))^3 g `newwgtb' = `wgt1b'*`wgt2b' sum `newwgtb' scalar sigmawgt = r(sum) replace `newwgtb' = `newwgtb'/scalar(sigmawgt) replace `newwgtb' =0 if `newwgtb'==. tempname bootwindow bootwindcnt M unique g `bootwindow' = `newwgtb'>0 & `newwgtb'!=. g `bootwindcnt' = `bootwindow'*`del1b' sum `bootwindow' `bootwindcnt' levelsof `bootwindcnt', local(`M') local `unique': word count ``M'' di as text "unique="``unique'' if ``unique''< 10 { scalar `yhatb' = scalar(`Ykmean') scalar list `yhatb' } else { reg `y' `del1b' [weight=`newwgtb'] scalar `yhatb' = _b[_cons] scalar list `yhatb' } matrix `outmatb'[`k',`j'] = scalar(`yhatb') drop `del2b' `kdel2b' `wgt2b' `newwgtb' `bootwindow' `bootwindcnt' } drop `del1b' `kdel1b' `wgt1b' `kprod' `ksum' } } matrix `outVecb' = J(2,$r,0) forvalues i = 1/$r { forvalues j = 1/$r { matrix `outVecb'[2,`i'] = `outVecb'[2,`i']+`outmatb'[`j',`i'] matrix `outVecb'[1,`i'] = `i'*$r } } matrix `outVecb' = (`outVecb'/$r)' return matrix bootoutvec `outVecb' end capture program drop gaussquadk2 program define gaussquadk2, rclass *! version 1.0 cagregory ers 8 sept 2011 syntax varlist (min=2 max=2 numeric) [if] [in] /// , hvec(numlist min=2 max=2) //local kern: word 1 of `varlist' local xvar1: word 1 of `varlist' local xvar2: word 2 of `varlist' local b1: word 1 of `hvec' local b2: word 2 of `hvec' local bandw1 = `b1'/2 local bandw2 = `b2'/2 *************************************************************************** *This quadrature routine is from press et al. Numerical Recipes in C. *Section 4.5, Gaussian Quadratures.* It computes the integral of the squared *kernel weights for a given observation as a function of the right-hand-side *variables in an additive model. I use 10 points of integration. *************************************************************************** tempname max1 min1 max2 min2 aplusb1 bminusa1 aplusb2 bminusa2 xm1 xr1 xm2 xr2 /// intpoints intweight dx1 dx2 nodes1 nodes2 NTP s qui sum `xvar1' scalar `max1' = r(max) scalar `min1' = r(min) scalar `aplusb1' = `min1'+`max1' scalar `bminusa1' = `max1'-`min1' scalar `xm1' = .5*(`aplusb1') scalar `xr1' = .5*(`bminusa1') qui sum `xvar2' scalar `max2' = r(max) scalar `min2' = r(min) scalar `aplusb2' = `min2'+`max2' scalar `bminusa2' = `max2'-`min2' scalar `xm2' = .5*(`aplusb2') scalar `xr2' = .5*(`bminusa2') matrix `intpoints' =[0.0, 0.1488743389, 0.4333953941, 0.6794095682, 0.8650633666, 0.97390652] matrix `intweight' =[0.0, 0.2955242247, 0.2692667193, 0.2190863625, 0.1494513491, 0.06667134] matrix define `dx1' = J(1,6,0) matrix define `nodes1' = J(1,12,0) matrix define `dx2' = J(1,6,0) matrix define `nodes2' = J(1,12,0) matrix define `NTP' = J(2,6,0) forvalues j = 1/6 { matrix `dx1'[1,`j'] = `xr1'*`intpoints'[1,`j'] matrix `nodes1'[1,`j'] = `xm1' + `dx1'[1,`j'] matrix `nodes1'[1, 6+`j'] = `xm1' - `dx1'[1,`j'] matrix `dx2'[1,`j'] = `xr2'*`intpoints'[1,`j'] matrix `nodes2'[1,`j'] = `xm2' + `dx2'[1,`j'] matrix `nodes2'[1, 6+`j'] = `xm2' - `dx2'[1,`j'] } scalar `s' = 0 /*Gauss-Legendre Quadrature 10 points*/ tempname d1 d2 w1 w2 kern kern2 p1 p2 m1 m2 tPrimePlus tPrimeMinus x1plus x2plus /// x1minus x2minus g `d1' = 0 g `d2' = 0 g `w1' = 0 g `w2' = 0 g `p1' = 0 g `kern' = 0 g `kern2' = 0 g `p2' = 0 g `m1' = 0 g `m2' = 0 g `tPrimePlus' = 0 g `tPrimeMinus' = 0 forvalues j = 1/6 { qui { sort `xvar1', stable scalar `x1plus' = `nodes1'[1,`j'] scalar `x2plus' = `nodes2'[1,`j'] replace `d1' = (abs(`xvar1'-scalar(`x1plus'))/(`bandw1'))^3 /*Weights determined by distance from BMI*/ replace `d1' = 1 if abs(`xvar1'-scalar(`x1plus'))>`bandw1' replace `w1' = (70/81)*(1 - `d1')^3 sort `xvar2', stable replace `d2' = (abs(`xvar2'-scalar(`x2plus'))/(`bandw2'))^3 /*Weights determined by distance from BMI*/ replace `d2' = 1 if abs(`xvar2'-scalar(`x2plus'))>`bandw2' replace `w2' = (70/81)*(1 - `d2')^3 replace `kern' = `w1'*`w2' replace `kern2' = `kern'^2 replace `p1' = `kern2' replace `tPrimePlus' = (`p1') qui sum `tPrimePlus' scalar normtprimeplus = r(max) matrix `NTP'[1,`j'] = scalar(normtprimeplus) scalar `x1minus' = `nodes1'[1,6+`j'] scalar `x2minus' = `nodes2'[1,6+`j'] replace `d1' = (abs(`xvar1'-scalar(`x1minus'))/(`bandw1'))^3 /*Weights determined by distance from BMI*/ replace `d1' = 1 if abs(`xvar1'-scalar(`x1minus'))>`bandw1' replace `w1' = (70/81)*(1 - `d1')^3 sort `xvar2', stable replace `d2' = (abs(`xvar2'-scalar(`x2minus'))/(`bandw2'))^3 /*Weights determined by distance from BMI*/ replace `d2' = 1 if abs(`xvar2'-scalar(`x2minus'))>`bandw2' replace `w2' = (70/81)*(1 - `d2')^3 replace `kern' = `w1'*`w2' replace `kern2' = `kern'^2 disp "k2,1" replace `m1' = `kern2' replace `tPrimeMinus' = (`m1') replace `tPrimeMinus' = `tPrimeMinus'^2 sum `tPrimeMinus' scalar normtprimeminus = r(max) matrix `NTP'[2,`j'] = normtprimeminus matrix list `NTP' scalar list normtprimeplus scalar `s' = scalar(`s') + `intweight'[1,`j']*(scalar(normtprimeplus) + scalar(normtprimeminus)) scalar list `s' } } scalar `s' = scalar(`s')*(sqrt(`xr1'*`xr2')) return scalar intk2 = scalar(`s') end