-1

I defined the macros below as levels of the variables id, var1 and var2:

levelsof id, local(id_lev) sep(,)
levelsof var1, local(var1_lev) sep(,)
levelsof var2, local(var2_lev) sep(,)

I'd like to be able to reference the level values stored in these macros by their index during foreach and forval loops. I'm learning how to use macros, so I'm not sure if this is possible.

When I try to access a single element of any of the above macros, every element of the macro is displayed. For example, if I display the first element of id_lev, every element is displayed as a single element (and, the last element is listed as an invalid name which I don't understand):

. di `id_lev'[1]
0524062407240824092601260226032604 invalid name
r(198);

Furthermore, if I attempt to refer to elements of any of the macros in a loop (examples of what I've tried given below), I receive the error that the third value of the list of levels is an invalid number.

foreach i of numlist 1/10 {
    whatever `var1'[i] `var2'[i], gen(newvar)
}

forval i = 1/10 {
    local var1_ `: word `i' of `var1''
    local var2_ `: word `i' of `var2''
    whatever `var1_' `var2_', gen(newvar)
}

Is it not possible to reference elements of a macro by its index?

Or am I referencing the index values incorrectly?


Update 1:

I've gotten everything to work (thank you), save for adapting the forval loop given in William's answer to my loops above in which I am trying to access the macros of two variables at the same index value.

Specifically, I want to call on the first, second, ..., last elements of var1 and var2 simultaneously so that I can use the elements in a loop to produce a new variable. How can I adapt the forval loop suggested by William to accomplish this?


Update 2:

I was able to adapt the code given by William below to create the functioning loop:

levelsof id, clean local(id_lev)
macro list _id_lev
local nid_lev : word count `id_lev'

levelsof var1, local(var1_lev)
macro list _var1_lev
local nvar1_lev : word count `var1_lev'

levelsof var2, local(var2_lev)
macro list _var2_lev
local nvar2_lev : word count `var2_lev'

forval i = 1/`nid_lev' {

    local id : word `i' of `id_lev'
    macro list _id
    local v1 : word `i' of `var1_lev'
    macro list _v1
    local v2 : word `i' of `var2_lev'
    macro list _v2

    whatever `v1' `v2', gen(newvar)

}
kathystehl
  • 831
  • 1
  • 9
  • 26
  • Macros are single entities holding single values. They are not vectors or arrays, so index references make no sense. The `[1]` in your `display` command is what is producing the error message. The command displays the macro contents and then is puzzled by the trailing `[1]` which is not a name. – Nick Cox Mar 05 '17 at 08:35
  • We need a reproducible example, and we need to know what variable you want to create. Almost certainly there is a much more direct way to create it any use of macros or loops. Insisting on separating by commas in `levelsof` makes parsing your macro much more difficult as "words" in Stata are those items separated by spaces. This is likely to be at least part of your problem with the loops. – Nick Cox Mar 05 '17 at 08:38
  • The code will fail second time around the loop, as `newvar` already exists. -- unless the unexplained program `whatever` destroys that variable. So you are not presenting functioning code. – Nick Cox Mar 05 '17 at 15:19

1 Answers1

2

You will benefit, as I mentioned in my closing remark on your previous question, from close study of section 18.3 of the Stata User's Guide PDF.

sysuse auto, clear
tab rep78, missing
levelsof rep78, missing local(replvl)
macro list _replvl
local numlvl : word count `replvl'
macro list _numlvl
forval i = 1/`numlvl' {
    local level : word `i' of `replvl'
    macro list _level
    display `level'+1000
}

yields

. sysuse auto, clear
(1978 Automobile Data)

. tab rep78, missing

     Repair |
Record 1978 |      Freq.     Percent        Cum.
------------+-----------------------------------
          1 |          2        2.70        2.70
          2 |          8       10.81       13.51
          3 |         30       40.54       54.05
          4 |         18       24.32       78.38
          5 |         11       14.86       93.24
          . |          5        6.76      100.00
------------+-----------------------------------
      Total |         74      100.00

. levelsof rep78, missing local(replvl)
1 2 3 4 5 .

. macro list _replvl
_replvl:        1 2 3 4 5 .

. local numlvl : word count `replvl'

. macro list _numlvl
_numlvl:        6

. forval i = 1/`numlvl' {
  2.     local level : word `i' of `replvl'
  3.         macro list _level
  4.         display `level'+1000
  5. }
_level:         1
1001
_level:         2
1002
_level:         3
1003
_level:         4
1004
_level:         5
1005
_level:         .
.
  • Thanks for your help @WilliamLisowski. I got everything to work up until the `forval` loop that you've included at the bottom. It works fine in the example you gave, but I am trying to complete a loop on two of the macros simultaneously. This is why my initial thought was to treat the macros like an indexed vector that I can reference with calling the first, second, ..., elements of `var1` and `var2` at once. I've updated my attempt to do this above, but cannot get the syntax to work. – kathystehl Mar 05 '17 at 05:23
  • I can also make a new question since this specifically pertains to loops if that would be more appropriate. – kathystehl Mar 05 '17 at 05:28