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

From |
"Nick Cox" <n.j.cox@durham.ac.uk> |

To |
<statalist@hsphsun2.harvard.edu> |

Subject |
st: RE: a fancier loop |

Date |
Fri, 11 Apr 2003 10:25:53 +0100 |

Radu Ban > i have a set of variables gop1-gop9 greval1-greval9 gadd1-gadd9 and > several more like these, all postfixed from 1 to 9. each postfix has > a distinct meaning which i want to incorporate in a label. > > i wrote this nested loop with paralel lists, but it doesn't run. can > anyone point the way out? > > for X in any gop greval gadd gdeda gcl dyrb dyrd dsd dyre > nop ncl \ > Y in any "gross opening" "gross addition by reval." > "gross actual addition" "gross deduc. & adj." "gross closing" > "depr. up to year beg." "depr. during year" > "depr. adj. for sold/discarded" "depr. up to year close" > "net opening" "net closing": > > for Z in num 1/9 \ > T in any "land" "building" "P&M" "transp. equip." > "computers" "others" "subtot" > "cap. work in prog." "total": > label var XZ "fix. ass. T: Y"; > > or is not possible to accomplish this in one step? The problem =========== Several threads over the last few months have touched on this issue. -for- is now, in Stata 8, undocumented. My take is that -for- is now regarded as having more disadvantages than advantages, including (1) it is slow, as -for- is ado code and thus interpreted; (2) it fits poorly with the rest of Stata, having an idiosyncratic syntax, and being difficult to coordinate with local macros, etc.; (3) it grows badly, as users try to load more and more on to it; etc. As it happens, the likely problem with Radu's code is already explained at Why do some nested for commands produce an error? http://www.stata.com/support/faqs/lang/nestfor.html Moral: do look at the FAQs (-for- anguish questions). More generally, nested -for- loops on average do work with a probability which averages mysteriously close to 1 / e. There is a probabilistic explanation in Feller's third volume. That's not high enough for this to be an attractive technique. Nevertheless, as Radu says, -for- is a command which offers a structure for problems involving parallel lists. So how is this done using either -foreach- or -forvalues-? My answer ========= My answer is to use -foreach- or -forvalues- to go through ONE list, and to use some other technique to go through ANY OTHER lists at the same time. Example solution: (1) the code ============================== Here is one way of attacking Radu's problem. There are four lists in the problems, which come in pairs. 1. the stubs of several groups of variable names local X "gop greval gadd gdeda gcl dyrb dyrd dsd dyre nop ncl" 2. longer explanations of each group local Y "gross opening" "gross addition by reval." "gross actual addition" "gross deduc. & adj." "gross closing" "depr. up to year beg." "depr. during year" "depr. adj. for sold/discarded" "depr. up to year close" "net opening" "net closing" 3. explanations of each variable within each group: local T "land" "building" "P&M" "transp. equip." "computers" "others" "subtot" "cap. work in prog." "total" 4. and the numbers 1 to 9. With those initial definitions, I conjecture that Radu needs something like this. Stata 8 ------- local i = 1 foreach x of local X { local y : word `i++' of `Y' forval j = 1/9 { local t : word `j' of `T' label var `x'`j' `"fix. ass. `t': `y'"' } } Stata 7 ------- local i = 1 foreach x of local X { local y : word `i' of `Y' forval j = 1/9 { local t : word `j' of `T' label var `x'`j' `"fix. ass. `t': `y'"' } local i = `i' + 1 } Example solution: (2) the main idea =================================== The architecture of this is * A -foreach- loop cycling through the stubs in X. As we step through X automatically, we have to arrange that we pull out each successive bit which we also need from Y. The way we did it here was through -word # of-. * Nested within that, a -forval- loop cycles through the integers 1/9. As we step through that list automatically, we have to arrange that we pull out each successive bit which we also need from T. Same device used. In short, neither -foreach- nor -forval- offers inbuilt, explicit machinery for stepping through other lists at the same time. But that's not necessary: you can get that by using other devices alongside. Example solution: (3) optional extras ===================================== Another tool relevant here, but which you can use only once in a given problem, is -tokenize-. -tokenize- takes its argument and emits the pieces ("words", wide sense) as local macros 1, 2, 3, etc., depending on how many pieces there are. Words are separated by spaces, unless bound by double quotes or compound double quotes, so if I . tokenize a b c "a" is now the contents of local macro 1, "b" of 2 and "c" of 3, whereas if I . tokenize a "b c" d "a" is now the contents of local macro 1, "b c" of 2 and "d" of 3. Applying this to Radu's problem, we could for example tokenize `T' local i = 1 foreach x of local X { local y : word `i++' of `Y' forval j = 1/9 { label var `x'``j'' `"fix. ass. `t': `y'"' } } but in this case we gain nothing from that. More generally, it is not essential for these problems. A further note is that in Stata 8, you can pick up a -word # of- some stuff on the fly: local i = 1 foreach x of local X { forval j = 1/9 { label var `x'`j' /// `"fix. ass. `: word `j' of `T'': `: word `i++' of `Y''"' } } The key rule for evaluating macros within macros is analogous to that in elementary mathematics for evaluating parenthesised expressions: evaluate the innermost macro first. That's a neat technique, but again an optional extra. P.S. is this programming? ========================= We are here in an interesting grey area: is this Stata programming or not? The literal answer is "No"; a Stata program is defined (without circularity!) by the fact that it begins with a -program- statement. Nevertheless, in order to make progress, users do need to understand something about local macros and how to manipulate them. For this, you don't need [P]; I think all you need is in [U]. Nick n.j.cox@durham.ac.uk * * 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/

**Follow-Ups**:**st: RE: RE: a fancier loop (correction)***From:*"Nick Cox" <n.j.cox@durham.ac.uk>

**References**:**st: a fancier loop***From:*Radu Ban <rban@nber.org>

- Prev by Date:
**st: constraint question** - Next by Date:
**st: Making symmetry** - Previous by thread:
**st: a fancier loop** - Next by thread:
**st: RE: RE: a fancier loop (correction)** - Index(es):

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