I think you just don't quite have a full grasp of working in Stata's
vectorized way of thinking. Stata can access the values of a variable at
any time. If you want to loop over observations you can use explicit
subscripting when working with a variable, but this almost always a slower
way of doing things. Instead, you can count if a condition is satisfied for
all observations and repeat the loop until it is. This latter approach
isn't a "trick", but a programming method. Nick's example used assert and
then checked the return code, but an equivalent approach is to use the count
command and then check r(N). You still haven't been able to provide an
example that Stata can't do.
A classic algorithm (See Numerical Recipes...) for
generating values from Normal(0,1) would look
something like this in Stata, if -while- could
access the run-time value of a variable:
tempvar v1 v2 done
gen `done' = 0
while not `done' {
gen `v1' = 2.0 * uniform() - 1.0
gen `v2' = 2.0 * uniform() - 1.0
gen r = `v1' * `v2'
gen `done' = (r < 1.0 ) & (r > 0.0) /*
}
etc. more stuff
Here's one approach to replicate the above loop
tempvar v1 v2 done
gen `v1'=.
gen `v2'=.
gen r=.
count if !((r < 1.0 ) & (r > 0.0) )
while r(N)>0 {
replace `v1' = 2.0 * uniform() - 1.0
replace `v2' = 2.0 * uniform() - 1.0
replace r = `v1' * `v2'
count if !((r < 1.0 ) & (r > 0.0) )
}
Another example occurs when one wants to do what
I think of a "rippling" through from 1 to N, using
the run-time value of a previous case.
For example, to consecutively groups of cases
based on some kind of shared value of a key,
a natural approach in other languages would
be something that would not fit with Stata:
* More Code that wouldn't work in Stata
sort SomeKey
generate GroupID = 1 if _n ==1
replace GroupID = GroupID[_n-1] ///
if (_n > 1) & !(SomeKey == SomeKey[_n-1])
I know there are ways to accomplish this goal in
Stata, but I'm trying to adapting my existing bag
of algorithmic tricks :-}.
Again, this just requires you to think in Stata's vectorized way.
sort SomeKey
bysort SomeKey: gen GroupID=_n==1
replace GroupID=sum(GroupID)
I like the suggested approach in a later posting of doing the following:
gen x = uniform()
gen byte OK = x >= 0.8
capture assert OK == 1
while _rc {
replace x = cond(x < 0.8, uniform(), x)
replace OK = x >= 0.8
capture assert OK == 1
}
However, it does seem odd that one needs to use what looks like a trick to
get make a value of a variable something that -while- can access at run
time. I wouldn't have thought of this.
As I said, this is not a true, but a programming method that takes advantage
of Stata's approach. Instead of the while _rc and capture assert commands,
it would just be like the first example I give -- using a while r(N) and
count if...
If your point is that Stata's ado programming is different than what you're
used to with another language, in part due to Stata's vectorized apporoach
to operation, then that's true.
Michael Blasnik
[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/