*! version 3.2.5 JGarrett 26Mar16 /* Graphs observed proportion of D or means of Y for groupings */ /* of a continuous X variable */ /* Form:lintrend y x,[groups(#),round(#),integer] graph */ /* Options Required: groups, round, or int (only 1); */ /* Options Allowed: graph, noline, xlabel, ylabel, titles */ /* Automatically print logodds graph; graph for prop optional */ program define lintrend version 8.0 #delimit ; syntax varlist(min=2 max=2)[if] [in][, Groups(int 0) Round(real 0) Integer GRaph PROPortion LOGodds Title(string) NOLine *] ; #delimit cr marksample touse tokenize "`varlist'" local choice 0 if `groups'>0 { local choice=`choice'+1 } if `round'>0 { local choice=`choice'+1 } if "`integer'"=="integer" { local choice=`choice'+1 } if `choice'==0 { disp " " #delimit ; disp as err "You must chose one:" as result " groups(#)" as erro "," as result " round(#)" as err "," as result " or integer"; #delimit cr exit } if `choice'>1 { disp " " #delimit ; disp as erro "You must chose only one:" as result " groups(#)" as err "," as result " round(#)" as err "," as result " or integer"; #delimit cr exit } preserve quietly keep if `touse' keep `varlist' capture assert `1'==1 | `1'==0 if _rc==0 { local ytype=1 } if _rc~=0 { local ytype=2 } local varlblx : variable label `2' local vallblx : value label `2' if `ytype'==1 { quietly logistic `1' `2' local chi2=e(chi2) local p=chiprob(1,e(chi2)) } if `ytype'==2 { quietly reg `1' `2' local f=e(F) local df2=e(df_r) local p=fprob(1,`df2',e(F)) } sort `2' * If groups chosen, divide X into categories of equal size if `groups'>0 { quietly gen numgrps=group(`groups') quietly egen max=max(`2'), by(numgrps) quietly replace max=max[_n-1] if `2'==`2'[_n-1] #delimit ; quietly collapse (min) min=`2' (mean) mean=`2' (sum) y=`1' (count) total=`2', by(max); #delimit cr quietly gen group=mean label var group "Mean of `2' categories" } * If round chosen, round x to nearest specified value if `round'>0 { quietly gen group=round(`2',`round') #delimit ; quietly collapse (sum) y=`1' (count) total=`1' (max) max=`2' (min) min=`2', by(group) ; #delimit cr quietly replace group=max if group>max label var group "`2' rounded to nearest `round'" } * If integer chosen, treat categories of x as original integers if "`integer'"=="integer" { local intval: value label `2' quietly gen group=`2' collapse (sum) y=`1' (count) total=`1', by(group) label var group "Grouped by values of `2'" label val group `intval' } * Calculate means, proportions, and log odds by groups of x quietly gen meany=y/total if `ytype'==1 { quietly gen ln_odds=ln(meany/(1-meany)) if y>0 label var meany "Proportion of `1'" label var ln_odds "Ln(odds) of `1'" if "`graph'"~="" { quietly reg ln_odds group quietly predict hat } } if `ytype'==2 { label var meany "Category Mean of `1'" if "`graph'"~="" { quietly reg meany group quietly predict hat } } * Set up formats for output quietly compress format y %5.0f format total %7.0f if `groups'>0 { if _n==1 { local range=abs(max-min) } if `range'>=1000000 { format group % 8.2e } else if `range'>=1 { format group %10.1f } else if `range'>=.1 { format group %10.2f } else if `range'>=.01 { format group %10.3f } else if `range'>=.001 { format group %10.4f } } if `ytype'==1 { format ln_odds %7.2f format meany %6.2f } if `ytype'==2 { egen miny=min(meany) if _n==1 { local ymin=miny } if `ymin'>=10000000 { format meany %8.2e } else if `ymin'>=1 { format meany %10.2f } else if `ymin'>=.1 { format meany %10.3f } else if `ymin'>=.01 { format meany %10.4f } else if `ymin'>=.001 { format meany %10.5f } else if `ymin'>=.0001 { format meany %10.6f } } * List results sort group display _n(1) rename group `2' rename meany `1' rename y d if `ytype'==1 /* outcome is binary */ { #delimit ; display as text "The proportion and ln(odds) of" as result " `1' " as text "by categories of" as result " `2'" ; display " "; #delimit cr if `groups'>0 { display as text " (Note:" as result " `groups'" as text /// " `2' categories of " as result "equal sample size" as text ";" display as text " Uses mean `2' value for each category)" list `2' min max d total `1' ln_odds, nod noob separator(0) } if `round'>0 { display as text " (Note: `2' in categories" as result " rounded" /// in text " to nearest" as result " `round'" as text ")" list `2' min max d total `1' ln_odds, nod noob separator(0) } if "`integer'"=="integer" { display as text " (Note: `2' in categories using" /// as result " original values" as text ")" label val `2' `vallblx' list `2' d total `1' ln_odds, nod noob separator(0) } } if `ytype'==2 /* outcome is continuous */ { #delimit ; display as text "The mean of" as result " `1' " as text "by categories of" as result " `2' " ; display " "; #delimit cr if `groups'>0 { display as text " (Note:" as result " `groups'" as text /// " `2' categories of " as result "equal sample size" as text ";" display as text " Uses mean `2' value for each category)" list `2' min max total `1', nod noob separator(0) } if `round'>0 { display as text " (Note: `2' in categories" as result " rounded" /// in text " to nearest" as result " `round'" as text ")" list `2' min max total `1', nod noob separator(0) } if "`integer'"=="integer" { display as text " (Note: `2' in categories using" /// as result " original values" as text ")" label val `2' `vallblx' list `2' total `1', nod noob separator(0) } } display " " if `ytype'==1 { #delimit ; disp as text " Test for linear trend: " " Chi2(1) = " as result %6.2f `chi2'; disp as text " Prob > chi2 = " as result %7.4f `p'; #delimit cr } if `ytype'==2 { #delimit ; disp as text " Test for linear trend: " " F(1,`df2') = " as result %6.2f `f'; disp as text " Prob > F = " as result %7.4f `p'; #delimit cr } * Graph results if "`graph'"=="graph" { more rename `2' grp rename `1' meany if `ytype'==1 & "`proportion'"=="proportion" { twoway (scatter meany grp, sort), ylabel(, angle(horizontal)) `options' more } if `ytype'==1 { if "`noline'"=="" { twoway (scatter ln_odds grp, sort) (line hat grp, sort), /// ylabel(, angle(horizontal)) `options' } if "`noline'"=="noline" { twoway (scatter ln_odds grp, sort), ylabel(, angle(horizontal)) /// `options' } } if `ytype'==2 { if "`noline'"=="" { twoway (scatter meany grp, sort) (line hat grp, sort), /// ylabel(, angle(horizontal)) `options' } if "`noline'"=="noline" { twoway (scatter meany grp, sort), /// ylabel(, angle(horizontal)) `options' } } } end