*! byhist graphs side by side "interlaced" histograms *! or a single histogram, allowing weights *! byhist 1.3 19 Apr 2010 Austin Nichols added options tw1 tw2 etc. * byhist 1.2 12 Feb 2009 Austin Nichols added "asis" to tw option * byhist 1.1 3 Dec 2008 Austin Nichols added options * byhist 1.0 26 Nov 2008 Austin Nichols prog byhist, rclass version 8.2 syntax varname [fw aw pw] [if] [in], [ by(string) FREQuency FRACtion DENSity percent name(passthru) tw(string asis) tw1(string asis) tw2(string asis) tw3(string asis) tw4(string asis) tw5(string asis) tw6(string asis) tw7(string asis) otol(int 2) SUPpress * ] * note undocumented otol sets tolerance for order (power of ten) above which to convert units to integers * and option tw passes options to the final twoway graph--all other options * are passed to twoway__histogram_gen gettoken by byopt: by if substr("`by'",1,1)=="," | "`by'"=="" { loc by: subinstr local by "," "", all loc byopt `"`by' `byopt'"' tempvar by g byte `by'=1 loc noby "no by var" } else loc by: subinstr local by "," "", all marksample touse cap conf numeric var `by' if _rc { tempvar b encode `by', gen(`b') unab byvar: `by' loc by "`b'" di as err "Variable " as res "`by'" as err " not numeric;" di as smcl as err "using {help encode} to make a numeric variable" di as smcl as err "which may change the ordering of categories." _n } else unab byvar: `by' markout `touse' `by' tempvar nvals qui bys `touse' `by' : gen byte `nvals' =(_n == 1)*`touse'*(`by'<.) su `nvals' if `touse', meanonly loc nval=r(sum) if `nval'>7 { di as err "Variable `byvar' has " as res r(sum) as err " distinct values" di as err "are you sure you want that many interlaced histograms?" _n di as res "Break to abort, or any other key to continue" loc wasmore=c(more) set more on more set more `wasmore' } loc v `varlist' tempvar x y wt sum wtvar loc u = 1 qui if "`weight'"!="" { loc wtvar: subinstr local exp "=" "", all capture assert float(`wtvar') == float(round(`wtvar',1)) if `touse' if _rc == 0 { while _rc == 0 { loc u = `u'*10 capture assert float(`wtvar') == float(round(`wtvar',`u')) if `touse' } loc u = `u'/10 } else { while _rc { loc u = `u'/10 capture assert float(`wtvar') == float(round(`wtvar',`u')) if `touse' } } qui g `wt'`exp'/`u' loc tempwt "fw=`wt'" markout `touse' `wt' } else g `wtvar'=1 if "`percent'"!="" loc fraction="fraction" if "`frequency'`fraction'`density'"=="" loc frequency "frequency" twoway__histogram_gen `v' if `touse' [`tempwt'],gen(`x' `y') `frequency' `fraction' `density' `options' loc s=r(min) loc w=r(width) loc b=r(bin) return local min=`s' return local width=`w' return local bin=`b' qui { replace `x'=. replace `x'=`s'+`w'/2 if (`v'>=`s')&(`v'<=`s'+`w') forv i=2/`b' { replace `x'=`s'+(2*`i'-1)*`w'/2 if (`v'>=`s'+(`i'-1)*`w')&(`v'<`s'+(`i')*`w') } replace `x'=`s'+(2*`b'-1)*`w'/2 if float(`v')==float(`s'+(`b')*`w') } loc xl=cond(`"`:var lab `v''"'=="","`v'",`"`:var lab `v''"') preserve qui keep if `touse' cap drop `y' la val `x' `: value label `v'' qui egen double `y'=sum(`wtvar'), by(`by' `x') collapse `y', by(`by' `x') fast bys `by': g double `sum'=sum(`y') if "`fraction'"!="" qui by `by': replace `y'=`y'/`sum'[_N] if "`percent'"!="" qui by `by': replace `y'=`y'*100 if "`density'"!="" qui by `by': replace `y'=`y'/`sum'[_N]/`w' qui levelsof `by', loc(bl) loc iwidth=`w'/(`:word count `bl''+1) loc lowlim=`w'/2 loc ilev 1 qui foreach lev of local bl { replace `x'=`x'-(`lowlim')+`ilev'*`iwidth' if `by'==`lev' loc ilev=`ilev'+1 } su `y', meanonly loc m=r(max) tempname matrix mat forv ni=1/`=_N' { matrix `mat'=(`=`by'[`ni']',`=`x'[`ni']',`=`y'[`ni']') matrix `matrix'=nullmat(`matrix')\ `mat' } loc frac=cond("`percent'"=="","`fraction'","`percent'") matrix colnames `matrix'=`byvar' `v' `frequency'`frac'`density' return matrix b=`matrix' loc o: di int(log10(`m'))-1 if abs(`o')>`otol' { loc M=ceil(`m'/10^`o') qui replace `y'=`y'/10^`o' } else loc M=ceil(`m'/10^`o')*10^`o' loc p=cond(length("`:di `M'/3'")`otol' loc l `"`l'in `=trim("`: di %20.0gc `:di 10^(`o')''")'s")"' if `o'<-`otol' loc l `"`l'in `=trim("`: di %20.0gc `:di 10^-(`o')''")'ths")"' if abs(`o')<=`otol' loc l `"`l'")"' if `"`xl'"'!="" loc l `"`l' xti(`xl')"' loc l `"`l' leg("' loc bli=1 tokenize `bl' while "`1'"!="" { loc l `"`l' label(`bli' "`=cond("`:var lab `by''"=="","","`:var lab `by'' = ")'`:label (`by') `1''")"' loc bli=`bli'+1 mac shift } loc l `"`l')"' loc byopt `"barw(`iwidth') `byopt'"' loc cmd loc bli=1 tokenize `bl' while "`1'"!="" { loc cmd `"`cmd' (bar `y' `x' if `by'==`1', `byopt' `tw`bli'')"' loc bli=`bli'+1 mac shift } tw `cmd', `l' `tw' `name' end