I was trying to get the following:
- Line graphs of median birth interval for pairs of countries, one line per country with a legend indicating country name,
- Four of these graphs combined (so, four pairs comprising eight countries, one combined graph)
Easy, right?
Full disclosure: a lot of the cleverness here comes from my adviser, who had somewhat similar code from another project.
First, given data comprising variables country, med_2nd, med_3rd, med_all, rate, year, evaluating the relationship between a pair of variables for 2…n subsets of observations (in this case, a pair of countries) requires either using -reshape wide- to create country-variables, or you can use the handy || operator to overlay graphs, eg
scatter var1 var2 if var3=="this" || scatter var1 var2 if var3=="that"
This is great, but I wanted to specify a lot of options, making it painful to stay on one line. No matter, I’d just use #delimit:
#delimit ;
to make a semicolon the command delimiter; that way I could use as many lines as I needed without having to specify /// after every line. However, #delimit and || didn’t play nicely together. As far as I can tell, I’m stuck with the default newline delimiter and ///.
How to iterate through a list in pairs? We can -tokenize- the local macro containing the list of countries, then loop through with -while-:
tokenize `C' // `C' is my country list
while "`1'" ~= "" // as long as the current node isn't empty, keep going
How to proceed by twos?
macro shift 2
All fine and good, but I’ve got eight countries and they’re paired, so I’m making four graphs. How to name them sequentially?
*Outside, the loop, initialize a counter:
local cstep = 1
while "`1'" ~= "" {
** stuff happens inside here, including saving my graph with name "something_`cstep'"
local cstep = `cstep' + 1 // this increments my counter
}
I’ve got three variables of interest, for each of which I want to compare to some other variable. I also want to do this for my four pairs of countries. I’ll do this with a nested loop, storing my variable names in a local macro, using -foreach- to iterate over them. It’ll be handy for me to address my saved graphs with a counter when I’m using -graph combine-, though, so I want to save with something numeric rather than using my variable name. So, I’ll create a variable ‘vstep’ and save my graphs named for the ‘index’ of that variable plus my ‘country-step’ counter:
local cstep = 1
local vars var1 var2 var3
while "`1'" ~= "" { // outside loop is country-pair, but it doesn't have to be
local vstep = 1
foreach v of local vars { // inside loop iterates over my reference variables
scatter `v' othervar if country=="`1'" ///
|| ///
scatter `v' othervar if country=="`2'" ///
, saving("`v'_`cstep", replace)
local vstep = `vstep' + 1
}
}
So far so good. With eight countries across three variables, I’ve got twenty-four comparisons yielding twelve graphs. I’ll add the -name- option to my graph command, giving it the same name as in my -saving- option, so the graphs are stored in memory, too. The default legend only indicates the variable name, which isn’t very helpful — I need to indicate the country for the distinction to be relevant. The following amendment to -scatter- adds a legend inside the plot area (ring(0)) and makes the legend components my comparison countries `1′ and `2′:
legend(label(1 `1') label(2 `2') ring(0))
Now I need to combine graphs. I can use one loop to do this, counting across my three variables (sure, I could have stored my variable names in a local macro and used -foreach- rather than using -forvalues-). The numeric values for each pairing (1…4) are hardcoded, and it’s possible/likely there’s a more clever way to handle that. I want to make a subtitle indicating which comparison variable (in this case, median birth interval) is present in the graph, so I’ve got a few -if- statements):
forvalues v = 1/3 { // from values of `num': 2nd, 3rd, all, respectively
if `v'==1 {
local n "Second Birth Interval"
}
if `v'==2 {
local n "Third Birth Interval"
}
if `v'==3 {
local n "All Birth Intervals"
}
graph combine `v'_1 `v'_2 `v'_3 `v'_4, ///
iscale(*1.2) ///
imargin(l=-3) ///
ycommon ///
title("Comparing, uh, stuff I'm interested in...") ///
subtitle("`n'", margin(zero) size(medlarge)) ///
name(combined_`v', replace) ///
saving(combined_`v', replace)
window manage close graph
}
Here’s the full code:
local C ///
"Colombia Peru Ghana Kenya Bangladesh Egypt Indonesia Philippines"
local vars med_2nd med_3rd med_all //these are 2nd interval, 3rd, all intervals
local cstep = 1 // cstep is a 'file counter', one file per country-pair
tokenize `C'
while "`1'" ~= "" {
local vstep = 1
foreach v of local vars{
scatter rate `v' if country=="`1'", ///
|| ///
scatter rate `v' if country=="`2'", ///
legend(label(1 `1') label(2 `2') ring(0)) ///
name(lenvstfr_`cstep'_`vstep', replace)
window manage close graph
local vstep = `vstep' + 1
} // end of vars loop
local cstep = `cstep' + 1
mac shift 2 // move to the next pair -- `C' has to be ordered by pairs for this to work
} //end of country-pair loop
*
/* now, combine each of the graphs from 'var' */
forvalues v = 1/3 { // from values of `num': 2nd, 3rd, all, respectively
if `v'==1 {
local n "Second Birth Interval"
}
if `v'==2 {
local n "Third Birth Interval"
}
if `v'==3 {
local n "All Birth Intervals"
}
graph combine lenvstfr_1_`v' lenvstfr_2_`v' lenvstfr_3_`v' lenvstfr_4_`v', ///
iscale(*1.2) ///
imargin(l=-3) ///
ycommon ///
title("Title Here") ///
subtitle("`n'", margin(zero) size(medlarge)) ///
name(combined_`v', replace) ///
saving(combined_`v', replace)
window manage close graph
}
Recent Comments