Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • How to evaluate a string stored in a macro as a variable name?

    Hello,

    In a program, I'm trying to get a variable name, modify it using `regexr(oldvarname, "some_regex", "replacement")`, store it in a new local "newvarname", and use that modified variable name in a `replace ... if [newvarname] == 1` statement. Below is a minimal example of what I would like to achieve.

    Code:
    program define testprog
      syntax varlist
     
    
      foreach var of varlist `varlist' {
        local bin_check regexm("`var'", "bin(bot|mid|top)$")
    
        if `bin_check' {
            local varfreq regexr("`var'", "bin(bot|mid|top)$", "freq")
        }
        else {
            local varfreq `var'freq
        }
        
        gen `var'_wk = .
        replace `var'_wk = 1 if `varfreq' == 1
      }
    end
    
    gen joboffers_earn = 0
    gen joboffers_earnbinbot = 0
    gen joboffers_earnfreq = 1
    
    testprog joboffers_earn joboffers_earnbinbot
    In this example, `varfreq' is interpreted correctly for the first variable (which involves appending "freq" to the end of the variable), but not the second variable (which involves a slightly more complex replacing of substrings in the variable name).

    In short, how do I get Stata to evaluate the result of `regexr()` as a variable name instead of a string?

  • #2
    The problem arises with the command
    Code:
    local varfreq  regexr("`var'", "bin(bot|mid|top)$", "freq")
    The result of that is to store in local macro varfreq `"regexr("`var'", "bin(bot|mid|top)$", "freq")"', which is a string expression. When you refer to that later in -replace `var'_wk = 1 if `varfreq' == 1-, that becomes, after macro expansion -replace joboffers_earnbinbot_wk = 1 if replace `var'_wk = 1 if `"regexr("`var'", "bin(bot|mid|top)$", "freq")"'== 1, which is a type mismatch error: you can't compare a string to a number. What you want to do is have local varfreq contain, not "regexr("`var'", "bin(bot|mid|top)$", "freq")", but the actual return value of regexr() when evaluated. To force evaluation of an expression for inclusion in a macro, we use the = operator:

    Code:
    program define testprog
      syntax varlist
     
    
      foreach var of varlist `varlist' {
        local bin_check regexm("`var'", "bin(bot|mid|top)$")
    
        if `bin_check' {
            local varfreq = regexr("`var'", "bin(bot|mid|top)$", "freq")
        }
        else {
            local varfreq `var'freq
        }
        display `"`varfreq'"'
        
        gen `var'_wk = .
        replace `var'_wk = 1 if `varfreq' == 1
      }
    end
    does what you seek.

    By the way, unless you are using a very old version of Stata, you might want to switch from -regexr()- to -ustrregexrf(). This will give you greater generality of application, in case you end up wanting to apply this to variables whose names contain unicode characters. Additionally, it will allow you to use more modern regular expression syntax instead of the POSIX 2 standard that the old -regex*()- functions worked with.
    Last edited by Clyde Schechter; 23 Mar 2024, 13:38.

    Comment


    • #3
      Thank you Clyde — I actually had a look at the macro chapter of the manual earlier today but read the macro assignment section too fast. I now understand the importance of the assignment operator in this specific case. Thanks for pointing it out!

      Comment

      Working...
      X