Creating Loops (specifically for graphing)

I have been using STATA for a couple months, but not very intensely, and I've never had a STATA manual or introductory book to read. I have tried using loops a couple times but have never been successful; I have been able to get by without them so far. In the project I'm currently working on, I could continue to get by without looping, but I would like to learn how to do this.

In this project, I need to create scatter plots with a line tracking the plots. On the x-axis is age, and on the y-axis is an average test score for three different exams given (will refer to these as "average1", "average2", and "average3"). I also need to split these up by gender and by country (there are approximately 30 countries, with a country ID assigned to each. Each graph should both males and females, but should be for only one country (so with around 30 countries, there should be 30 graphs). Here is my first attempt at creating something anywhere close to what I need in this loop:

foreach var of average1 average2 average3 {
twoway scatter `var' age

As you can tell, my knowledge of STATA is very limited. I have tried incorporating gender and country ID into this, but I just don't know where they fit in, or if I am simply trying to do too much in a loop. I would be very thankful if someone could explain what is wrong with my loop to help me figure out what I might be doing wrong. Thanks!


TS Contributor
I would suggest using the forvalues command instead of foreach. Anyway, something like the code below might get you a bit on the way

forvalues j=1(1)3 {
forvalues i=1(1)30 {
forvalues k=1(1)2 {
twoway scatter average age if average==`j' & country==`i' & sex==`k'

Unfortunately, the code above gives you 3*30*2=180 graphs. But I hope it gives you some ideas of how to use loops :)
Thanks Englund! Using forvalues makes a lot more sense. Quick question: what does the "(1)" in the three forvalues tell STATA to do? I attempted to do something similar to this on my own, with just one of my three test score averages, but I imagine I did something wrong because it took an extremely long time and after a couple minutes I just broke the command. I tried running it again with a much smaller set of countries, and it still took a while but gave me a result. However, it only gave me one graph, whereas I need one graph for each country with males and females on the same graph. Here's the code I ran:

forvalues i=8(1)200 {
forvalues j=1(1)2 {
twoway scatter "y-axis variable" "x-axis variable" if country==`i' & gender==`j'

The countries were originally in string form but I converted them to real. They run a pretty long range, though there are only around 30 countries total. Also, gender is coded with female==1 and male==2. Would greatly appreciate any extra advice, this has been very helpful so far in helping me better understand loops. Would it be easier to write in a command to save each graph, rather than have STATA try and open them all?

And @bukharin, I am using Stata 12. Thanks!


TS Contributor
Quick question: what does the "(1)" in the three forvalues tell STATA to do?
It says that "jumps" equals one, 1-2-3-4. If you instead have (2), the following will occur: 1-3-5-7.
However, it only gave me one graph
That's because when a new graph opens, the one before closes. You'll have to use some kind of save command. I'm sure someone around here can help you with that. If you don't want to open a new graph all the time, just write the 'quietly' command before the rest of the code:

quietly twoway scatter x y


qui twoway scatter x y


Since you're using Stata 12 all of the user manuals (and help files) are already installed. See -help- and try the Help menu -> PDF Documentation. I would suggest reading the Getting Started manual and the User's Guide - doing this will be well worth your time in the long run. There are also stacks of online tutorials, with the most comprehensive collection coming from UCLA.

Your graphs are overwriting one another because you haven't named them. You can name them using the name() option for twoway graphs. Here's an example:
sysuse auto, clear
levelsof rep78, local(reps)
foreach rep of local reps {
    scatter price mpg if rep78==`rep', title("rep78 = `rep'") name(rep78_`rep')