program define sumadj, rclass sortpreserve
*!	version 1.6    by Mead Over 5Jul2021
*   This program enhances the detail option of the -summarize- command by adding
*   the calculation of the adjacent values used in STATA's box-and-whisker plots

*   If the -graph- option is added, the box & whisker plot is displayed.
*   Note that the values of the adjacent values from the output match
*   the lines constructed by the graph box command.

    version 9.2
    syntax varname [if] [in] [, Detail Graph YLog Alpha saving(passthru) TItle(passthru) SUbtitle(passthru) YAlternate Horizontal name(passthru) *]
    tempvar xL xU xsumL xsumU

	marksample touse
	if "`if'"~="" | "`in'"~="" | "`ylog'"~="" {
        preserve
		tempvar logexists
		gen byte `logexists' = (ln(`varlist')~=.)
		markout `logexists'
        qui keep if `touse'
   }

    if "`alpha'`ylog'`title'`subtitle'`yalternate'`horizontal'"~="" {
        if "`graph'"=="" {
            di _n in re "Option(s) " in ye"-`alpha' `ylog' `title' `subtitle' `yalternate' `horizontal'-" in re " require(s) option -graph-"
            exit 198
        }
        if "`horizontal'"~="" {
            local h h
        }
    }

	if "`ylog'"== "" {
		sort `varlist'
	}
	else {
		tempvar lnvlist
		gen double `lnvlist' = ln(`varlist')
		sort `lnvlist'
		local iflog if `logexists'
	}

	summarize `varlist' `iflog' , detail
		local rmin = `r(min)'
		local rp25 = `r(p25)'
		local rp50 = `r(p50)'
		local rp75 = `r(p75)'
		local rmax = `r(max)'
		local iqr = r(p75) - r(p25)
	if "`ylog'"== "" {
		local capsize = .025 * (`rmax'-`rmin')
		local L = r(p25) - (3/2)*`iqr'
		local U = r(p75) + (3/2)*`iqr'
		qui gen byte `xL'  = `varlist'< `L'
		qui gen byte `xU' = `varlist'<=`U'
	}
	else {
		local capsize = .025 * (ln(`rmax')-ln(`rmin'))
		local ln_iqr = ln(r(p75)) - ln(r(p25))
		local L = ln(r(p25)) - (3/2)*`ln_iqr'
		local U = ln(r(p75)) + (3/2)*`ln_iqr'
		qui gen byte `xL'  = ln(`varlist')< `L'
		qui gen byte `xU' = ln(`varlist')<=`U'
	}

    qui gen long `xsumL'  = sum(`xL')
    local Li = `xsumL'[_N] + 1
    if `Li'==0 {
        local Li = 1
    }

    local Ladj = `varlist'[`Li']

    qui gen long `xsumU' = sum(`xU')
    local Ui = `xsumU'[_N]
    local Uadj = `varlist'[`Ui']

	di _n in gr "Interquartile range (iqr) is: " in ye `iqr'
		di in gr "(The -iqr- is the difference between the 75th and 25th percentiles)"
		local iqrtxt iqr
	if "`ylog'"~="" {
		di in gr "Interlogquartile range (ilqr) is: " in ye `ln_iqr'
		di in gr "(The -ilqr- is the difference between the logs of the 75th and 25th percentiles)"
		local iqrtxt ilqr
	}
    di _n in gr "Adjacent Values"
    di    in gr "  Closest values to 1.5 `iqrtxt''s outside the 25th & 75th percentiles:"
    di    in gr "  Lower adjacent value: " in ye `Ladj'
    di    in gr "  Upper adjacent value: " in ye `Uadj'

    return scalar Ladj = `Ladj'
    return scalar Uadj = `Uadj'

    if "`graph'"~="" {
        tempname myr
        capture _return drop `myr'
        _return hold `myr'

        tempvar gr_var
        local varlbl :  variable label `varlist'
        if "`varlbl'"=="" {
            local varlbl "`varlist'"
        }
        if "`ylog'"=="" {
            qui gen double `gr_var' = `varlist'
                lab var `gr_var' "`varlbl'"
            local ylblfrmt ylabel(#3 `rmin' `Ladj'  `rp25' `rp50' `rp75' `Uadj'  `rmax', angle(horizontal) format(%10.3g))
        }
        else {
            qui gen double `gr_var' = log(`varlist')
                lab var `gr_var' "log( `varlbl' )"

            local rminlbl= string(`rmin',"%10.2g")
            local rmin = log(`rmin')

            local rmaxlbl= string(`rmax',"%10.2g")
            local rmax = log(`rmax')

            local Ladjlbl= string(`Ladj',"%10.2g")
            local Ladj = cond(log(`Ladj')~=.,log(`Ladj'),log(`rp50'))

            local Uadjlbl= string(`Uadj',"%10.2g")
            local Uadj = cond(log(`Uadj')~=.,log(`Uadj'),log(`rp50'))

            local rp50lbl= string(`rp50',"%10.2g")
            local rp50 = log(`rp50')

            local rp25lbl= string(`rp25',"%10.2g")
            local rp25 = log(`rp25')

            local rp75lbl= string(`rp75',"%10.2g")
            local rp75 = log(`rp75')

            local ylblfrmt ylabel(`rmin' "`rminlbl'" `Ladj' "`Ladjlbl'" `rp25'  "`rp25lbl'" `rp50'  "`rp50lbl'" `rp75'  "`rp75lbl'" `Uadj'  "`Uadjlbl'" `rmax' "`rmaxlbl'", angle(horizontal) format(%10.2g))

            di _n in gr "Execute -sumadj- on the log of " in ye "`varlist'" in gr " "
            di    in gr "to obtain & plot the adjacent values of its log distribution."
        }

        if "`alpha'"~="" {
            local ylblfrmt ylabel(`rmin' "Min" `Ladj' "Lower Adj" `rp25'  "Quartile" `rp50'  "Median" `rp75'  "Quartile" `Uadj'  "Upper Adj" `rmax' "Max", angle(horizontal) format(%10.2g))
        }

		if `"`title'"'=="" {
			local title title("`varlbl'")
		}

		if `"`subtitle'"'=="" {
			local subtitle subtitle("Box & Whisker Plot")
		}

        graph `h'box `gr_var' `if', medtype(line) capsize(`capsize') cwhiskers  lines(lwidth(thick)) ///
            `ylblfrmt' yline(`Ladj' `Uadj') ///
            `title' `subtitle' `saving' `yalternate' `name' `options'

        _return restore `myr'
    }

    if "`if'"~="" | "`in'"~="" | "`ylog'"~="" {
        restore
    }

end
*   Version 1.2 adds the -ylog- option.  It is applied only if the -graph- option is specified.
*   This option transforms the argument variable by taking its logarithm before constructing the graph.

*   Version 1.3 adds the -alpha- option.  If specified, it labels the box-and-whiskers graph with
*   alphanumeric labels for all its parts.  Only relevant with the -graph- option.

*   Version 1.4 adds the -yalternate- & -horizontal- options from -graph box- & -graph hbox-

*	Version 1.5 modifies the -ylog- option to compute the IQR on the logged variables
*	rather than on the unlogged variables.  Fixes labelling problem for option -ylog-.

*	Ver. 1.6 5Jul2021 Add the option -name()-