Announcement

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

  • How to setting local macro as result of expression and then use it to rename variables concatenated with strings

    Hello,

    I have some variables of a certain format (x_AAUU - where AA = 2 digit year, UU = 2 digit week), which I need to perform some expressions on in order to rename them. Here is the code:


    input x_9801 x_9925 x_0050 x_0351 x1311
    1 2 3 4 5
    end

    foreach var of varlist x_* {
    local aa=substr(string(`var'),3,2)
    local uu=substr(string(`var'),5,2)
    ren `var' "x_19"+"`aa'"+"`uu'" if `aa' > 90 & `aa' <= 99
    ren `var' "x_20"+"`aa'"+"`uu'" if `aa' < 90
    }

    when i set trace on, Stata reveals that the above code basically does not properly set the aa or uu macro, so when it renames the vars, they just show as blank.

    how can I get it to properly set the macro value so it can be used to rename the variables?

    Edit: I have tried additional code and I really can't see why i keep getting rename syntax errors:



    input x_9801 x_9925 x_0050 x_0351 x1311
    1 2 3 4 5
    end


    foreach var of varlist x_* {
    local aa=substr(string(`var'),3,2)
    local uu=substr(string(`var'),5,2)
    local aan "x_19"+"`aa'"+"`uu'"
    local aat "x_20"+"`aa'"+"`uu'"
    ren `var' `aan' if `aa' > 90 & `aa' <= 99
    ren `var' `aat' if `aa' < 90
    }

    The traceback then gives me syntax error for rename, but it says exactly:

    = rename x_9801 x_199801 if 98 > 90 & 98 <= 99

    syntax error
    Syntax is
    rename old name new name ...
    ....


    EDIT2: Fixed, i messed up the format of renaming conditional:



    foreach var of varlist x_* {
    local aa=substr(string(`var'),3,2)
    local uu=substr(string(`var'),5,2)
    local aan "x_19"+"`aa'"+"`uu'"
    local aat "x_20"+"`aa'"+"`uu'"
    if `aa' > 90 & `aa' <= 99 ren `var' `aan'
    if `aa' < 90 ren `var' `aat'
    }

    works fine.
    Last edited by Chris Engel; 19 May 2016, 02:49.

  • #2
    You don't need a loop for this example, although it seems that a loop is easier. Let's first fix your code, as there are several problems.

    I am guessing that x1311 is a typo for x_1311. If not, then your code won't work for that variable even with the fixes below.

    Code:
    clear 
    
    input x_9801 x_9925 x_0050 x_0351 x_1311
    1 2 3 4 5
    end
    
    foreach var of varlist x_* {
        local aa = substr("`var'",3,2)
        local uu = substr("`var'",5,2)
        if `aa' > 90 rename `var' x_19`aa'`uu' 
        if `aa' < 90 rename `var' x_20`aa'`uu' 
    }
    
    describe
    1. You are working on the variable name and so must specify "`var'" In contrast, string(`var'),3,2)would work on the string equivalent of the values of each variable in the first observation. Here that string is just one character long, namely something like "1", so that substring is empty. There is a similar problem with string(`var'),5,2) Neither is what you want, any way

    2. The if qualifier is illegal here as it would imply renaming only some observations. You need the if command.

    3. String manipulations using addition to concatenate are illegal here without a different syntax. But the explicit addition using + is unnecessary any way. The local macros can just be juxtaposed.

    There is a further simplification possible here.

    Code:
    clear 
    
    input x_9801 x_9925 x_0050 x_0351 x_1311
    1 2 3 4 5
    end
    
    foreach var of varlist x_* {
        local suffix = substr("`var'",3,.)
        if `suffix' > 9000 rename `var' x_19`suffix' 
        else rename `var' x_20`suffix' 
    }
    
    describe


    Without a loop? It's tricky, but it's possible. With renvars (SJ) you can do this

    Code:
    clear 
    
    input x_9801 x_9925 x_0050 x_0351 x_1311
    1 2 3 4 5
    end
    
    renvars x_* , map(substr("@",1,2) + cond(substr("@",3,2) > "90", "19", "20") + substr("@", 3, .)) 
    
    describe


    I didn't get as far as working out how to use rename without a loop.

    Know that the results are the same with all these code solutions:


    Code:
    . describe 
    
    Contains data
      obs:             1                          
     vars:             5                          
     size:            20                          
    --------------------------------------------------------------------------------------------
                  storage   display    value
    variable name   type    format     label      variable label
    --------------------------------------------------------------------------------------------
    x_199801        float   %9.0g                 
    x_199925        float   %9.0g                 
    x_200050        float   %9.0g                 
    x_200351        float   %9.0g                 
    x_201311        float   %9.0g                 
    --------------------------------------------------------------------------------------------








    Comment


    • #3
      Originally posted by Nick Cox View Post
      You don't need a loop for this example, although it seems that a loop is easier. Let's first fix your code, as there are several problems.

      I am guessing that x1311 is a typo for x_1311. If not, then your code won't work for that variable even with the fixes below.

      ....


      Thanks very much Nick for your response and assistance. You added some good points that help me to better understand the mistakes I made.

      Comment


      • #4
        Fitting somewhere between Nick's second and third examples is this example that doesn't explicitly loop, at the cost of a little more typing than using renvars, which makes use of Stata's ability to rename groups of variables, documented in help rename groups. I'm not suggesting it is in any way an improvement to Nick's solution, but as long as we're discussing renaming groups of variables I think it's worth mentioning the built-in command (in Stata since at least version 13.1) for the benefit of anyone who finds this thread while looking for advice on renaming variables.
        Code:
        . ds
        x_9801  x_9925  x_0050  x_0351  x_1311
        
        . rename x_9??? x_199???
        
        . rename x_0??? x_200???
        
        . rename x_1??? x_201???
        
        . ds
        x_199801  x_199925  x_200050  x_200351  x_201311

        Comment


        • #5
          This helpfully fills the gap mentioned in

          I didn't get as far as working out how to use rename without a loop.
          Somewhat like Chris with his loops, I tried more complicated rename solutions than that but gave up.

          Comment


          • #6
            Sorry, just realized I replied to the wrong post.. This should be the reply of another post.

            Thank you, Nick! This is super helpful!

            In my case, I'll need to rename the variables before reshape.

            The following code will do the work:
            Code:
            unab stubs : Y2000*
            local stubs : subinstr local stubs "Y2000" "", all
            
            foreach stub of local stubs{
                rename Y*`stub' `stub'*
                }
                
            reshape long `stubs', i(CountryCode) j(Year)
            Last edited by Craig Yang; 26 Aug 2020, 09:57.

            Comment

            Working...
            X