Title | Stata 6: Using while loops when the by command is not an option | |
Author | Jeremy B. Wernow, StataCorp |
There are several commands in Stata that will not allow the by command as an option. Two examples are the tab1 command and the graph commands with the saving() option. One way to get around this feature is to put the command you want to execute in a while loop:
. sysuse auto, clear . sort rep78 . by rep78: tab1 mpg price -> rep78= 1 request may not be combined with by (error occurred while loading tab1.ado) r(190);
That does not work. We know, however, that rep78 has values between 1 and 5, so let us try a while loop in a do-file:
local i = 1 while `i' <=5 { tab1 mpg price if rep78 == `i' local i = `i' + 1 }
Here is the output from executing this file:
. local i = 1 . while `i' <=5 { 2. tab1 mpg price if rep78 == `i' 3. local i = `i' + 1 4. } -> tabulation of mpg if rep78 == 1 Mileage | (mpg) | Freq. Percent Cum. ------------+----------------------------------- 18 | 1 50.00 50.00 24 | 1 50.00 100.00 ------------+----------------------------------- Total | 2 100.00 -> tabulation of price if rep78 == 1 Price | Freq. Percent Cum. ------------+----------------------------------- 4,195 | 1 50.00 50.00 4,934 | 1 50.00 100.00 ------------+----------------------------------- Total | 2 100.00 -> tabulation of mpg if rep78 == 2 Mileage | (mpg) | Freq. Percent Cum. ------------+----------------------------------- 14 | 1 12.50 12.50 16 | 1 12.50 25.00 ...
What if rep78 has missing values? In this case, you can use the egen command to create a new variable that categorizes each value in rep78.
Here is the modified do-file:
local i = 1 egen y = group(rep78), missing while `i' <=6 { tab1 mpg price if y == `i' local i = `i' + 1 }
By using the missing option with the egen command, the missing values of rep78 will be coded with a value of 6 (remembering that rep78 has values of 1 to 5). Note that the output from this do-file will now contain tabulations for mpg and price for the missing values of rep78 as well.
...output omitted... -> tabulation of mpg if y == 6 Mileage | (mpg) | Freq. Percent Cum. ------------+----------------------------------- 14 | 1 20.00 20.00 19 | 1 20.00 40.00 22 | 1 20.00 60.00 26 | 2 40.00 100.00 ------------+----------------------------------- Total | 5 100.00 -> tabulation of price if y == 6 Price | Freq. Percent Cum. ------------+----------------------------------- 3,799 | 1 20.00 20.00 4,424 | 1 20.00 40.00 4,453 | 1 20.00 60.00 6,486 | 1 20.00 80.00 12,990 | 1 20.00 100.00 ------------+----------------------------------- Total | 5 100.00
Now let us move on to a more difficult example. A user recently wanted to use the by command with the graph command and the saving() option.
. by rep78: graph mpg price -> rep78= 1 -> rep78= 2 -> rep78= 3 -> rep78= 4 -> rep78= 5 -> rep78= . . by rep78: graph mpg price, saving(graph.wmf) -> rep78= 1 request may not be combined with by r(190);
by cannot be used with the graph, saving() option because of naming issues (how would you name each individual graph?). This can be solved with another do-file:
local i = 1 egen y = group(rep78), missing while `i' <=6 { graph mpg price if y == `i', saving(graph`i',replace) local i = `i' + 1 }
The output of this do-file is
. local i = 1 . egen y = group(rep78), missing . while `i' <=6 { 2. graph mpg price if y == `i', saving(graph`i',replace) 3. local i = `i' + 1 4. } (Note: file graph1.gph not found) (Note: file graph2.gph not found) (Note: file graph3.gph not found) (Note: file graph4.gph not found) (Note: file graph5.gph not found) (Note: file graph6.gph not found) . end of do-file
That worked just as we wanted.
There is a lot that you can do with this concept. As a final and even more complex example, the same user also said he wanted to use the by() option with the saving() option, graphing those against another variable, and he needed this done for a list of variables. This probably sounds confusing at first (and it was). Essentially, we needed to
by var1: graph var2 var3, saving(graph) by(var4)
Several different variables were to be used in place of var3.
The solution is to use a for command inside a while loop. Here is an example using the auto dataset:
local i = 1 egen y = group(rep78), missing while `i' <=6 { sort y foreign for var mpg length weight: graph price X if y == `i', /* */ by(foreign) \ gphprint, saving("priceX`i'.wmf",replace) local i = `i' + 1 }
This results in
. local i = 1 . egen y = group(rep78), missing . while `i' <=6 { 2. sort y foreign 3. for var mpg length weight: graph price X if y == `i', /* */ by(foreign) \ gphprint, saving("priceX`i'.wmf",replace) 4. local i = `i' + 1 5. } -> graph price mpg if y == 1, by(foreign) -> gphprint, saving("pricempg1.wmf",replace) -> graph price length if y == 1, by(foreign) -> gphprint, saving("pricelength1.wmf",replace) -> graph price weight if y == 1, by(foreign) -> gphprint, saving("priceweight1.wmf",replace) -> graph price mpg if y == 2, by(foreign) -> gphprint, saving("pricempg2.wmf",replace) -> graph price length if y == 2, by(foreign) -> gphprint, saving("pricelength2.wmf",replace) -> graph price weight if y == 2, by(foreign) -> gphprint, saving("priceweight2.wmf",replace) ... end of do-file