Statalist


[Date Prev][Date Next][Thread Prev][Thread Next][Date index][Thread index]

Re: RE: Re: st: programming graphs in stata


From   n j cox <n.j.cox@durham.ac.uk>
To   statalist@hsphsun2.harvard.edu
Subject   Re: RE: Re: st: programming graphs in stata
Date   Sun, 21 Oct 2007 21:42:09 +0100

Thanks for the positive comments.

On 1), given -spineplot yvar xvar-, the
order on the y axis is that of yvar and
the order on x axis is that of xvar. An
option to use some other sort order
would be possible but in my view not
especially good style. I have to agree
with Maarten Buis, who commented

MB> The way a user can do that is first install the -egenmore-
MB> package from -ssc- (type -ssc install egenmore-), and
MB> follow the instructions in -help egenmore- under
MB> the heading -axis()-.

In other words, a fairly general tool exists
to do this already. The user should get the variable
wanted in the sort order wanted before calling -spineplot-.
(-vreverse-, as already mentioned, may also be useful.)

> 2) When some categories are small or labels are longer the labels for
> axis 2 (at the bottom) overlap. One way around that is to optionally
> allow the user to specify an angle `myangle':
> 	xla(`XLA', axis(2) ang(`myangle') noticks)

The user can do this already without the artifice of
an extra option.

splineplot yvar xvar, xla(, axis(2) angle(<myangle>))

will tune the angle away from the default. All that
is necessary here is that the user know that the lower
of two x axes is -axis(2)-. You worked that out from
the code, but I'll document it in the help. The -xla()-
option of the program and the -xla()- option of the
user are merged.

A later version of the code is here. I changed my
mind on some points and fixed a bug.

Nick
n.j.cox@durham.ac.uk

*! NJC 1.0.1 19 Oct 2007
*! NJC 1.0.0 17 Oct 2007
program spineplot
	version 9
	forval i = 1/20 {
		local baropts `baropts' bar`i'(str asis)
	}
	syntax varlist(min=2 max=2 numeric) [fweight/] [if] [in] ///
	[, MISSing PERCent `baropts' barall(str asis) * ]

	quietly {
		if "`missing'" != "" {
			marksample touse, novarlist zeroweight
		}
		else marksample touse, zeroweight
		count if `touse'
		if r(N) == 0 error 2000

		tokenize "`varlist'"
		args y x

		preserve
		tempvar f xf xF xmid tag yF xshow
		if "`exp'" == "" local exp 1
		contract `x' `y' if `touse' [fw=`exp'], zero f(`f')

		if "`percent'" != "" {
			local factor = 100
			local la 0 25 50 75 100
			local what "percent"
		}
		else {
			local factor 1
			local la 0 0.25 0.5 0.75 1
			local what "fraction"
		}

		bysort `x' (`y'): gen `xf' = sum(`f')
		by `x' : replace `xf' = `xf'[_N]
		by `x' : gen byte `tag' = _n == 1
		gen `xF' = sum(`xf' * `tag')
		by `x': gen `xmid' = `xF'[_N] - 0.5 * `xf'[_N]
		local total = `xF'[_N]

		by `x' : gen `yF' = sum(`f')
		by `x' : replace `yF' = `factor' * `yF'/ `yF'[_N]

		local first = _N + 1
		expand 2 if `x' == `x'[_N]
		replace `yF' = . in `first'/l
		sort `y' `x' `yF'
		by `y' : gen `xshow' = cond(_n == 1, 0, `xF'[_n - 1])

		tokenize "`la'"
		forval i = 1/5 {
			local xla1 = (`i' - 1) * `total'/4
			local xla `" `xla' `xla1' "``i''" "'
		}

		local xtitle : var label `x'
		if `"`xtitle'"' == "" local xtitle `x'
		label var `xshow' `"`what' by `xtitle'"'
		local ytitle : var label `y'
		if `"`ytitle'"' == "" local ytitle `y'
		label var `yF' `"`what' by `ytitle'"'

		levelsof `x', local(levels)
		foreach l of local levels {
			su `xmid' if `x' == `l', meanonly
			local l : label (`x') `l'
			local XLA `" `XLA' `r(min)' "`l'" "'
		}

		drop `f' `xf' `xF' `xmid' `tag'

		levelsof `y', local(levels)
		local ny : word count `levels'
		tokenize `levels'
		forval i = `ny'(-1)1 {
			local pipe = cond(`i' > 1, "||", "")
			local I = `ny' - `i' + 1

			local call `call' ///
			bar `yF' `xshow' if `y' == ``i'' ///
			, bartype(spanning) blcolor(bg) blw(medium) ///
			`barall' `bar`I'' `pipe'

			local which : label (`y') ``i''
			local lgnd `lgnd' `I' `"`which'"'
		}
	}

	twoway `call'                             ///
	xaxis(1 2)                                ///
        xsc(r(0, `total') axis(1))                ///
        xsc(r(0, `total') axis(2))                ///
	xla(`XLA', axis(2) noticks)               ///
	xla(`xla', axis(1))                       ///
	xtitle(`"`xtitle'"', axis(2))             ///
	yla(`la', ang(h) nogrid)                  ///
	legend(order(`lgnd') col(1) pos(3))       ///
	`options'
end
	

Schonlau, Matthias

Great spineplot program Nick.

I have two comments:

1) I wonder how easy it is to let the user specify the sort order along
the x-axis.  I think the sort order is currently a result of the
"contract" statement and the following "bysort" statement, I am not sure
whether this is elegant, but may be one could just pass an optional sort
variable down from the main spine plot.

(If the first variable in "spineplot var1 var2" is a two-level variable
for highlighting, users will likely want to sort bars in order of the
proportion of highlighted observations).

2) When some categories are small or labels are longer the labels for
axis 2 (at the bottom) overlap. One way around that is to optionally
allow the user to specify an angle `myangle':
	xla(`XLA', axis(2) ang(`myangle') noticks)
Another option, presumably much harder to program, might be to allow for
the "horizontal" option in graph twoway bar. This would result into
labels on horizontal labels the y-axis which are much less likely to
overlap.

*
*   For searches and help try:
*   http://www.stata.com/support/faqs/res/findit.html
*   http://www.stata.com/support/statalist/faq
*   http://www.ats.ucla.edu/stat/stata/



© Copyright 1996–2014 StataCorp LP   |   Terms of use   |   Privacy   |   Contact us   |   What's new   |   Site index