capture program drop kwstat *! version 1.0 23jul14 F. Chavez Juarez program define kwstat , rclass version 9.2 syntax varlist(min=2 max=2) [if] [in], [ Bw(real 0.0) Kernel(str) Stats(str) PREfix(str) AT SAVE GRID(integer 100) LPolybw NOgraph GRAPHTYPE(str) GRAPHOptions(str)] marksample touse // Define the dependent and the independent variable tokenize `varlist' local depvar `1' local xvar `2' capture drop _kwstat_* qui{ // Define temporary variables tempvar group X // Define statistics if("`stats'"==""){ local stats="mean" } // Define graph type if(!inlist("`graphtype'","","connected","line","scatter")){ noisily display as error "Only the following graph types are allowed: " as result "line, scatter, connected" noisily display as text "See {stata help kwstat##graphtype:help kwstat} for more help" exit 198 } if("`graphtype'"==""){ local graphtype="line" } // Define the different values gen `X'=. if("`at'"==""){ sum `xvar' if `touse' local step = (r(max)-r(min))/(`grid'-1) forvalues i=1/`grid'{ replace `X'=r(min)+(`i'-1)*`step' if _n==`i' } } else{ replace `X' = `xvar' } egen `group' = group(`X') if `touse' & `X'!=. sum `group' if `touse' local maxgroup=r(max) // Define bandwidth if("`lpolybw'"=="lpolybw"){ if("`kernel'"=="normal"){ lpoly `depvar' `xvar', nograph kernel(gaussian) } else{ lpoly `depvar' `xvar', nograph kernel(`kernel') } local bw=r(bwidth) } if(`bw'==0){ noisily di as text "I will define the bandwith automatically." _n as error "Note that the automatically generated bandwith is not necessarily optimal" sum `xvar' if `touse' local bw=1.06*r(sd)*r(N)^(-1/5) noisily di "The chosen bandwith is: `bw'" } //prepare the output vars local graph "" foreach stat of local stats{ gen _kwstat_`stat'=. la var _kwstat_`stat' "`stat'" local graph "`graph' (`graphtype' _kwstat_`stat' `X')" } // [MAIN BLOC] Loop through all possible values (or grid points) and compute the statistics forvalues i=1/`maxgroup'{ sum `X' if `group'==`i' qui: kwstat_kernel `xvar' if `touse', bw(`bw') type(`kernel') value(`r(mean)') out(_kwstat_kernel) local kerneltype=r(kernel) tabstat `depvar' [aweight=_kwstat_kernel] if `touse', stats(`stats') save drop _kwstat_kernel local runner=1 matrix result=r(StatTotal) foreach stat of local stats{ replace _kwstat_`stat' = result[`runner',1] if `touse' & `group'==`i' local runner= `runner'+1 } } // PREPARE THE GRAPH sort `X' local bw_round=string(round(`bw',0.00001)) if("`nograph'"==""){ local xlabel:variable label `xvar' local ylabel:variable label `depvar' if("`xlabel'"==""){ local xlabel="`xvar'" } if("`ylabel'"==""){ local ylabel="`depvar'" } twoway `graph' , title("Kernel weighted statistics") subtitle("In function of {it:`xlabel'}") /// note("Bandwidth: `bw_round', Kernel: `kerneltype'") ytitle("`ylabel'") xtitle("`xlabel'") `graphoptions' } // STORE VARIABLES if("`save'"!="save"){ drop _kwstat_* } else{ gen _kwstat_X=`X' if("`prefix'"!=""){ renpfix _kwstat_ `prefix' } } } // Return key values return scalar bw=`bw' return local kernel="`kerneltype'" end // KERNEL SUBROUTINE (also issued as independent routince called 'kernel' (type ssc install kernel) capture program drop kwstat_kernel program define kwstat_kernel , rclass version 9.2 syntax varlist(min=1 max=1) [if] [in], Value(real) Bw(real) [Out(string) Type(string)] marksample touse tempvar z kernel // COMPUTE THE VALUE OF Z gen `z' = (`varlist'-`value')/`bw' // Compute the kernel itself gen `kernel' = 0 if `touse' quietly{ if(inlist("`type'","normal","gaussian")){ local kname="Normal" replace `kernel' = normalden(`z') if `touse' } else if("`type'"=="triangle"){ local kname="Triangle" replace `kernel' = 1-abs(`z') if abs(`z')<=1 & `touse' local max = 1 } else if("`type'"=="beta"){ local kname="Beta" replace `kernel' = 0.75*(1-`z')*(1+`z') if abs(`z')<=1 & `touse' local max = 1 } else if("`type'"=="logit"){ local kname="Logit" tempvar logit gen `logit' = exp(`z')/(1+exp(`z')) if `touse' replace `kernel' = `logit'*(1-`logit') if `touse' } else if("`type'"=="uniform"){ local kname="Uniform" replace `kernel' = 0.5 if abs(`z')<=1 & `touse' local max = 1 } else if("`type'"=="cosine"){ local kname="Cosine" replace `kernel' = 1+cos(2*_pi*`z') if abs(`z')<=0.5 & `touse' local max = 0.5 } else if("`type'"=="parzen"){ local kname="Parzen" replace `kernel' = 4/3-8*`z'^2+8*abs(`z')^3 if abs(`z')<=0.5 & `touse' replace `kernel' = 8/3*(1-abs(`z'))^3 if inrange(abs(`z'),0.5,1) & `touse' local max = 1 } else{ if("`type'"!=""){ noisily di as error "Kernel type '`type'' is not supported. I used the epanechnikov kernel instead" } local type = "epanechnikov" local kname="Epanechnikov" replace `kernel' = 0.75*(1-0.2*`z'^2)/sqrt(5) if abs(`z')<=sqrt(5) & `touse' // epanechnikov local max = sqrt(5) } } if("`out'"==""){ local out = "_kernel_`type'" } gen `out' = `kernel' la var `out' "`kname' kernel of `varlist' around `value'" // Observations with positive kernel count if `touse' local N=r(N) count if `touse' & `out'>0 local Npos=r(N) // Return values return local kernel `type' return scalar bw = `bw' end // VERSION HISTORY *! Version 1.0 First release