Statalist The Stata Listserver


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

st: RE: RE: RE: does stata create an index that can be used in loops?


From   "Nick Cox" <[email protected]>
To   <[email protected]>
Subject   st: RE: RE: RE: does stata create an index that can be used in loops?
Date   Thu, 8 Feb 2007 15:56:40 -0000

In my experience problems with parallel lists
are much less common than those with Cartesian
products (met by nested loops). But manifestly
they do occur. Paradoxically, the old -for- was 
set up for parallel lists, but did not support 
Cartesian products. Years back I wrote a crude
-cp- to meet that need, long since made obsolete
by -forval- and -foreach-: 

STB-45  ip27  . . . . . . . Results for all possible combinations of arguments
        (help cp if installed)  . . . . . . . . . . . . . . . . . .  N. J. Cox
        9/98    pp.20--21; STB Reprints Vol 8, pp.81--83
        alternative to for command that relaxes the restriction that
        the number of items must be the same in each list

You are right that three or more lists look 
tricky for the -tokenize- approach. -tknz- on 
SSC offers one way out. Here is another, illustrated
by example. The key is the construct -word # of-.

Your variables are called Jan, Feb, ..., Dec. You 
would rather they were called m1, m2, ..., m12. 
But you want their variable labels to be 
January, February, ..., December. So you 
are cycling over three lists in parallel. 
I devised this example so it is nice and simple
using -c()- stuff, but that is incidental to 
the main point. 

local ms "`c(Mons)'" 
local Ms "`c(Months)'" 

forval i = 1/12 { 
	local m : word `i' of `ms' 
	local M : word `i' of `Ms' 
	rename `m' m`i' 
	label var m`i' "`M'" 
} 

It should be clear that this approach extends 
to any number of parallel lists. Nor do they need
to be set up in advance as local macros. 
This works too, for example: 

forval i = 1/12 { 
	local m : word `i' of `c(Mons)' 
	local M : word `i' of `c(Months)' 
	rename `m' m`i' 
	label var m`i' "`M'" 
} 

as would this 

forval i = 1/12 { 
	local m : word `i' of Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
	local M : word `i' of `c(Months)' 
	rename `m' m`i' 
	label var m`i' "`M'" 
} 

Nothing here depends on the "word"s literally being 
single words (in any ordinary language sense), as we 
can use " " and `" "' to bind more complicated strings. 

Note that if we had as our major loop a -foreach- 
like this 

foreach m of local ms { 
	...
} 

we need to set up any loop over
numbers ourselves 

local i = 1 
foreach m of local ms { 
	local M : word `i' of `c(Months)' 
	rename `m' m`i' 
	label var m`i' "`M'" 
	local ++i 
} 

which at this moment I like much less than a solution
with -forval-. 

Naturally, I chose an example that succumbs easily
to the charms I know, but I don't think many real problems
are really much messier, so long as you look for tricks
not among loop features but among general tools for handling
macros. 

Nick 
[email protected] 

Brent Fulton
 
> Thank you for your replies. You're right, the better way to 
> phrase my issue
> is "how to loop through two or more lists in parallel." Sebastian's
> -tokenize- recommendation was very helpful and allows me to 
> go through two
> lists in parallel, but it doesn't seem to easily generalize 
> to more than two
> lists since a subsequent -tokenize- command will overwrite 
> the local macros
> it creates. Prior to the subsequent tokenize, I could store 
> the original
> tokenized macros in another set of locals, but this may get messy.
> 
> I plan to read the "Problem with lists" article when I can 
> get a hold of it,
> but Nick, you seem to imply there is a better approach to 
> problem. Prior to
> Stata, I had programmed in R, where I would create multiple 
> lists of the
> same length (e.g., a list of dependent variables, a list of 
> independent
> variables, a list of variables indicating subpopulations, a 
> list of svyset
> features (e.g., Taylor series vs. rep. wgts.), etc.) and then 
> call each
> model sequentially from within the lists. I'd appreciate your 
> advice on the better approach.

Nick Cox
 
> The specific question has been well answered. 
> In this case, there is an easy solution. 
> 
> The more general issue I take to be how to loop through two 
> or more lists in
> parallel. This isn't really the best way to think about 
> Brent's problem, but
> he thought it was. Matters are not always quite so easy. 
> There is a fairly
> lengthy discussion in 
> 
> Cox, N.J. 2003. Problems with lists. Stata Journal 3(2): 185--202    

Brent Fulton
  
> > I am using stata 9 and want to know whether stata creates 
> an index in 
> > loops that I can use to pull from a local macro. For my end 
> result, I 
> > would like the following variables to be created:
> > var1_county, var2_county, var3_county
> > 
> > I did the following:
> > 
> > local a "var1 var2 var3"
> > foreach x of local a{
> > local b "`b' `x'"
> > }
> > *the loop above results in the following: local b "var1_zip 
> var2_zip 
> > var3_zip"
> > 
> > sort county
> > foreach x of local b{
> > by county: egen `x'_county=total(`x')
> > }
> > But this creates the variables: var1_zip_county, var2_zip_county, 
> > var3_zip_county
> > 
> > 
> > Is there a way to do this: see*
> > sort county
> > foreach x of local b{
> > by county: egen *grab the appropriate element of local
> > a*_county=total(`x')
> > }

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