Reputation: 39
I have these two functional (working) loops:
* Loop that creates 1/0 variables
foreach x in m1 m2 m3 m4 {
gen yn_`x' = beforedate * `x'
}
* Loop that creates four dichotomous lag variables
foreach x in 0 3 12 18 {
gen lag`x' = refdate > (date + 30 * `x')
}
And I want to combine the loops into a single double loop. Below is my attempt at this, but it is not working.
foreach x in m1 m2 m3 m4 {
foreach y in 0 3 12 18 {
gen yn_`x' = beforedate * `x'
gen lag`y' = refdate > (date + 30 * `y')
}
}
The error I get (below). This error seems to be associated with my spacing and tabs (but I'm not entirely certain about that).
variable yn_m1 already defined.
Sample of my data:
* Example generated by -dataex-. To install: ssc install dataex
clear
input float id byte(m1 m2 m3 m4) float(beforedate refdate) int date
1 . . . . 0 16594 .
2 . . . . 0 18228 .
3 . . . . 0 18238 .
4 . . . . 0 18237 .
5 0 0 0 0 1 18016 16324
6 . . . . 0 16324 .
7 . . . . 0 16914 .
8 1 0 0 0 1 18226 17333
9 . . . . 0 17096 .
10 0 0 0 0 0 17961 17962
11 . . . . 0 16978 .
12 . . . . 0 17844 .
13 . . . . 0 17207 .
14 . . . . 0 17141 .
15 . . . . 0 16338 .
16 . . . . 0 16100 .
17 . . . . 0 17498 .
18 . . . . 0 17394 .
19 . . . . 0 18207 .
20 . . . . 0 18043 .
21 . . . . 0 16851 .
22 . . . . 0 18027 .
23 . . . . 0 17723 .
24 . . . . 0 16475 .
25 1 1 0 0 1 16097 16079
26 . . . . 0 16613 .
27 . . . . 0 17350 .
28 . . . . 0 17972 .
29 . . . . 0 18009 .
30 1 0 0 0 0 18008 18184
31 . . . . 0 16840 .
32 0 1 0 0 1 18179 17370
33 . . . . 0 16224 .
34 . . . . 0 17400 .
35 . . . . 0 17015 .
36 . . . . 0 16880 .
37 . . . . 0 16637 .
38 . . . . 0 16566 .
39 . . . . 0 17056 .
40 . . . . 0 18073 .
41 . . . . 0 17076 .
42 0 1 0 0 0 16179 17447
43 . . . . 0 16422 .
44 . . . . 0 16184 .
45 . . . . 0 16495 .
46 . . . . 0 17168 .
47 1 1 0 0 0 18001 18001
48 . . . . 0 16649 .
49 . . . . 0 17150 .
50 . . . . 0 17426 .
51 . . . . 0 16237 .
52 1 0 0 0 0 17681 17841
53 0 1 0 0 1 17874 16377
54 . . . . 0 16992 .
55 0 1 0 0 1 16377 16307
56 0 1 0 0 0 18066 18149
57 . . . . 0 16428 .
58 . . . . 0 18256 .
59 . . . . 0 16845 .
60 0 1 0 0 1 17997 16631
61 . . . . 0 17899 .
62 . . . . 0 16849 .
63 . . . . 0 16687 .
64 . . . . 0 18074 .
65 . . . . 0 17428 .
66 . . . . 0 16140 .
67 0 1 0 0 0 17938 18004
68 . . . . 0 16326 .
69 . . . . 0 17362 .
70 0 1 0 0 1 16954 16079
71 0 0 0 0 1 17974 16853
72 1 0 0 0 0 17077 17892
73 1 0 1 0 0 16453 17787
74 . . . . 0 18148 .
75 . . . . 0 18042 .
76 . . . . 0 16156 .
77 . . . . 0 16509 .
78 . . . . 0 17285 .
79 . . . . 0 16348 .
80 . . . . 0 17908 .
81 1 1 0 0 0 17932 17992
82 . . . . 0 17436 .
83 . . . . 0 17900 .
84 . . . . 0 16644 .
85 0 0 0 0 0 17170 18108
86 . . . . 0 17292 .
87 . . . . 0 16874 .
end
format %td refdate
format %d date
Upvotes: 2
Views: 1415
Reputation: 1348
To do what Nick and Wouter are suggesting you need to put the two lists you're passing to foreach
into locals and then loop across them together:
* loops in parallel
local mlist "m1 m2 m3 m4"
local nlist "0 3 12 18"
local n : word count `nlist'
local m : word count `mlist'
assert `n'==`m' // require same length
forvalues i = 1/`n' {
local a : word `i' of `mlist'
local b : word `i' of `nlist'
gen yn_`a'_II = beforedate * `a'
gen lag`b'_II = refdate > (date + 30 * `b')
}
This technique is useful in many cases even though this example isn't one of them.
EDIT NJC
If you take the line that you can see plainly that there are four elements in each case, this can be slimmed down to
local nlist "0 3 12 18"
forvalues i = 1/4 {
local n : word `i' of `nlist'
gen yn_m`i'_II = beforedate * m'i'
gen lag`b'_II = refdate > (date + 30 * `n')
}
and indeed to this
tokenize "0 3 12 18"
forvalues i = 1/4 {
gen yn_m`i'_II = beforedate * m'i'
gen lag`b'_II = refdate > (date + 30 * ``i'')
}
While you can do this, I (NJC) don't think it's especially good style to merge unrelated loops like this. People reading your code might be puzzled by it, unless you add an explanatory comment, which rather undoes any neatness in coding.
END OF EDIT
Upvotes: 2