Stata The Stata listserver
[Date Prev][Date Next][Thread Prev][Thread Next][Date index][Thread index]

st: -foreach- and -for-, nested and parallel


From   "Nick Cox" <[email protected]>
To   <[email protected]>
Subject   st: -foreach- and -for-, nested and parallel
Date   Wed, 16 Oct 2002 19:15:38 +0100

Buzz Burhans started a thread on problems with
code including nested -foreach- structures,
resolved to his satisfaction by Scott Merryman's
suggestion.

This is a postscript to that thread making
some general and some specific points.

Nested and parallel structures
==============================

1. If you nest two or more -foreach-
loops, the total number of steps
is the _product_ of the number of
steps in the loop, so

foreach i of num 1/2 {
	foreach j of num 1/3 {
		di "i is `i' and j is `j'"
	}
}

entails 2 * 3 steps in total:

i is 1 and j is 1
i is 1 and j is 2
i is 1 and j is 3
i is 2 and j is 1
i is 2 and j is 2
i is 2 and j is 3

2. You can try doing this with nested -for-, but
success is not guaranteed, for the kind of
reasons discussed in another recent thread.

It works in this case:

for X in num 1/2 , noheader : for Y in num 1/3, noheader: di "i is X
and j is Y"

i is 1 and j is 1
i is 1 and j is 2
i is 1 and j is 3
i is 2 and j is 1
i is 2 and j is 2
i is 2 and j is 3

3. -for- by contrast is optimised for stepping
through parallel structures. The total number
of steps is just the number in any of the lists,
as all must have the same length:

for X in any i j k  \  Y in num 1/3, noheader: di "X  is Y"

i  is 1
j  is 2
k  is 3

4. How do you this with -foreach-?
Sometimes one list is just a transformation
of the other, so you can do the mapping on the fly.
Suppose variables v3-v14 are to be renumbered v1-v12:

foreach n of num 3/14 {
	local new = `v' - 2
	rename v`n' v`new'
}

(Note here that -v3- has already been -rename-d -v1-
when we try to -rename- -v5- as -v3-.)

Perhaps more commonly, some such trick cannot
be used, or cannot be identified. In essence then,
-foreach- will step through one list and you have to
ensure that it steps through any other list(s) at the same time.

Buzz's example was a nice little illustration
of a nasty little problem. To recap, he
wanted to -rename-

v3-v14

as

preday18 preday15 preday12 preday9 preday7
preday6 preday5 preday4 preday3 preday2 preday1 preday0

for good reasons.

One fairly transparent way to do that is

local i = 0
local suffixes "18 15 12 9 7 6 5 4 3 2 1 0"

foreach v of var v3-v14 {
	local i = `i' + 1
	local new : word `i' of `suffixes'
	rename `v' preday`new'
}

But the same idea can be expressed more
briefly, at the cost of introducing more
programming stuff:

tokenize "18 15 12 9 7 6 5 4 3 2 1 0"

foreach v of var v3-v14 {
	rename `v'  preday`1'
	mac shift
}

To understand the underlying machinery, you
need to know or learn about local macros,
-macro shift- and -tokenize-. The main
idea is that -tokenize- puts the elements
of 18 ... 0 in macros `1', `2', ... We
use the first value and then shift them
all up one, and loop around repeating that.

Nick
[email protected]

*
*   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/



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