Search code examples
for-loopindexingforeachstatastata-macros

Referencing macro values by index


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)

}

Solution

  • 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:         .
    .