1
votes

I have a problem creating a loop in Stata.

I have a dataset in Stata where I classified my observations into 6 categories via variable k10. So k10 takes on values 1,2,3,4,5,6. Now I want to assign each observation one value according to its class:

value 15 for k10=1
value 10 for k10=2
value 8  for k10=3
value 5  for k10=4
value 4  for k10=5
value 2  for k10=6

It is easy if I create a new variable w10 and do it like the following:

gen w10 =. 
replace w10 = 15 if k10==1
replace w10 = 10 if k10==2
replace w10 = 8 if k10==3
replace w10 = 5 if k10==4
replace w10 = 4 if k10==5
replace w10 = 2 if k10==6

Now I tried to simplify the code by using a loop, unfortunately it does not do what I want to achieve.

My loop:

gen w10=.
local A "1 2 3 4 5 6"
local B "15 10 8 5 4 2"
foreach y of local A {
foreach x of local B {
replace w10 = `x' if k10= `y'
}
}

The loop assigns value 2 to each observation though. The reason is that the if-condition k10=`y' is always true and overwrites the replaced w10s each time until the end, right?

So how can I write the loop correctly?

1

1 Answers

2
votes

It's really just one loop, not two nested loops. That's your main error, which is general programming logic. Only the last time you go through the inner loop has an effect that lasts. Try tracing the loops by hand to see this.

Specifically in Stata, looping over the integers 1/6 is much better done with forval; there is no need at all for the indirection of defining a local macro and then obliging foreach to look inside that macro. That can be coupled with assigning the other values to local macros with names 1 ... 6. Here tokenize is the dedicated command to use.

Try this:

gen w10 = .
tokenize "15 10 8 5 4 2"
quietly forval i = 1/6 {
    replace w10 = ``i'' if k10 == `i'
}

Note incidentally that you need == not = when testing for equality.

See (e.g.) this discussion.

Many users of Stata would want to do it in one line with recode. Here I concentrate on the loop technique, which is perhaps of wider interest.