Fredrik Wallenberg
> Essentially I
> want a matrix scatterplot with the weights. That is not an option
> since the weight would be different for each graph. Instead I decided
> to create each graph separately and then use combine. I now run into
> one major issue... how do I control aspect ratio? xscale() yscale()
> scales the whole graph, but I only have axes and labels on the outside
> graphs (to try to recreate the look of the matrix graph). What I need
> is a way to control the size of the plotarea (to ensure that all
> graphs have the same plot area and that they are square. How do I do
> this? If I can't, can anyone suggest an alternative visualization.
The -aspect()- option was added a while ago. So far as I aware
the only documentation is in Stata Journal 4(3). Here it is, more
or less. By the way, -aspect()- is still a little wobbly.
Stata tip 12: Tuning the plot region aspect ratio
Sometimes you want a graph to be a particular shape. Graph shape
is customarily quantified by the aspect ratio, height/width. One
standard way of controling the aspect ratio is setting the graph
height and width by the -ysize()- and -xsize()- options of
-graph display-. See also [G] graph display and
[G] region_options. But these options control the size, and
thus the shape, of the entire available graph area, including
titles and other stuff beyond the plot region. At best, this is
an indirect way of controling the plot region shape, which is
likely to be your main concern.
In the 23 July 2004 update, Stata 8 added an -aspect()- option
to -graph- to meet this need. For example, -aspect(1)-
specifies equal height and width, so that the rectangular plot
region becomes a square. (A rectangle which is not a square is,
strictly, an oblong.) You might want a square plot as a matter
either of logic or of taste. Suppose that you are contemplating
uniform random numbers falling like raindrops on the unit square
within the real plane (or the plain, or as the old song has it):
. clear
. set obs 100
. gen y = uniform()
. gen x = uniform()
. scatter y x, aspect(1) xla(0(0.1)1, grid) yla(0(0.1)1, ang(h) grid)
yti(, orient(horiz)) plotregion(margin(none))
In effect you have drawn a map, and maps customarily have equal
vertical and horizontal distance scales, or, more simply put, a
single distance scale. Hence the aspect ratio is set as 1 whenever
the plot region has equal extent on both axes. The same
preference applies also to various special graphs on the unit
square, such as Lorenz curves.
In other circumstances, the aspect ratio sought might differ from
1. Fisher (1925, p.31) recommended plotting data so that lines
make approximately equal angles with both axes; the same advice of
banking to 45 degrees is discussed in much more detail by
Cleveland (1993). Avoiding roller-coaster plots of time series is
one application. In practice, a little trial and error will be
needed to balance a desire for equal angles with other
considerations. For example, try variations on the following:
. use http://www.stata-press.com/data/r8/htourism.dta
. tsline mvdays, aspect(0.15) yla(, ang(h))
Cleveland, W.S. 1993. Visualizing Data. Summit, NJ: Hobart Press.
Fisher, R.A. 1925. Statistical Methods for Research Workers.
Edinburgh: Oliver and Boyd.
> My second question ... in my code I'm looping over a set of variables
> twice (to create the matrix. With 6 variables I would like to loop
> over the first set from 1-5 and second from 2-6. The latter is easily
> accomplished by using `ferest()' as the varlist. However that assumes
> that my first set is 1-6 and I then have to hardcode an "escape" when
> I reach the last element. Would there be a way to test if I've reached
> the last element? For example, can I test if `ferest()' is empty? What
> I would like to do is to create a more generic solution that I could
> just pass a set of variables as an argument.
>
> For the curious I'm including my code (where each variable is a
> question answered on a 1-6 Likert scale).
>
> global likert 1 "Disgaree Strongly" 2 "Disagree" 3 "Neutral" ///
> 4 "Agree" 5 "Agree Strongly" 6 "Don't Know"
Typo ???
> foreach var1 of varlist q3_3_1 q3_3_2 q3_3_3 q3_3_4 q3_3_5 q3_3_6 {
> if "`var1'" == "q3_3_1" {
> global xaxis "xlabel($likert, alternate) xscale(alt)"
> }
> else {
> global xaxis "xscale(off)"
> }
> if "`var1'" != "q3_3_6" {
> foreach var2 of varlist `ferest()' {
> preserve
> collapse (count) q3_4_1, by(`var1' `var2')
> if "`var2'" == "q3_3_6" {
> global yaxis "ylabel($likert,
> angle(horizontal)) yscale(alt)"
> }
> else {
> global yaxis "yscale(off)"
> display "$yaxis"
> }
> twoway (scatter `var1' `var2' , ///
> msymbol(circle_hollow)
> msize(vsmall)[w= q3_4_1 ]), ///
> ysize(4) xsize(4)
> plotregion(margin(large)) ///
> $yaxis ///
> $xaxis ///
> yline(3, lwidth(vthin)) ///
> xline(3, lwidth(vvvthin))
> name("`var1'x`var2'", replace) ///
> graphregion(lwidth(vvthin))
> restore
> }
> }
> }
>
> graph combine ///
> q3_3_1xq3_3_2 q3_3_1xq3_3_3 q3_3_1xq3_3_4 q3_3_1xq3_3_5
> q3_3_1xq3_3_6 ///
> q3_3_2xq3_3_3 q3_3_2xq3_3_4 q3_3_2xq3_3_5 q3_3_2xq3_3_6 ///
> q3_3_3xq3_3_4 q3_3_3xq3_3_5 q3_3_3xq3_3_6 ///
> q3_3_4xq3_3_5 q3_3_4xq3_3_6 ///
> q3_3_5xq3_3_6 ///
> , cols(5) holes (6 11 12 16 17 18 21 22 23 24) ///
> ycommon xcommon imargin(0 0 0 0)
>
One way to do this is to loop over numbers not variables.
The code is not much shorter but it's more general. Do
the weights really go in that position. Rough sketch
only, with no testing.
unab varlist : q3_3_?
local y q3_4_1
local nvars : word count `varlist'
tokenize `varlist'
forval i = 1/`nvars' {
if `i' == 1 global xaxis "xlabel($likert, alternate) xscale(alt)"
else global xaxis "xscale(off)"
global yaxis "yscale(off)"
forval j = `=`i'+1'/`nvars' {
preserve
collapse (count) `y', by(``i'' ``j'')
if `j' == `nvars' ///
global yaxis "ylabel($likert, angle(horizontal)) yscale(alt)"
twoway (scatter ``i'' ``j'', msymbol(circle_hollow) ///
msize(vsmall) [w=`y']), ysize(4) xsize(4) //
plotregion(margin(large)) $yaxis $xaxis ///
yline(3, lwidth(vthin)) ///
xline(3, lwidth(vvvthin)) name("``i''x``j''", replace) ///
graphregion(lwidth(vvthin))
local names "`names' `name'"
restore
}
}
local ncols = `nvars' - 1
forval i = 2/`ncols' {
local J = `i' - 1
forval j = 1/`J' {
local h = (`i' - 1) * `ncols' + `j'
local holes "`holes' `h'"
}
}
graph combine `names', cols(`ncols') ///
holes (`holes') ycommon xcommon imargin(0 0 0 0)
*
* 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/