Announcement

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

  • Creating a local in a loop

    Hi,

    I have a loop that goes over different values, and inside the loop I create a variable with a specific suffix for each value. My problem is that I have negative numbers in the loop, and Stata does not allow negative numbers to be part of a variable name. What I am trying to do is to create another local inside the loop, which would have a conditional value based on whether the original value is negative or not. Here is what I've done so far, but it does not work.

    Code:
    forvalues i = -10(1)10 {
    di `i'
    local k cond(`i'<0,"minus_"substr("`i'",-1,.),`i')
    gen var_`k' = .
    }
    Any help is highly appreciated. Best,

    Albert
    Last edited by Albert Sfredo; 22 Oct 2016, 15:34.

  • #2
    Without being able to work this out with your data (ideally you could share some using dataex [ssc install dataex]) i think the problem might lie in the fact you have a function you want to evaluate within the local k. I would think the substr() needs to be encapsulated by `=`'', but i'm not 100% on that. Have a go, and if that doesn't week do share some data and I will likely be able to help

    Comment


    • #3
      You need three things:
      1) an "=" after the local to force evaluation of the function and assign something to the local
      2) a "+" to indicate concatenation of two strings. Concatenating two strings by putting them together without a "+" sign won't work except within a quote. Your code will execute without an error if done as follows:
      3) "" around the last `i' because you are assigning a string. Apparently the cond() function does not allow different types of data (numeric vs. string) to be used within it.


      Code:
      forvalues i = -10(1)10 {
      di `i'
      local k  = cond(`i'<0,"minus_" + substr("`i'",-1,.),"`i'")
      gen var_`k' = .
      }
      Whether this produces the result you want, I don't know.

      Comment


      • #4
        Mike, that is exactly what I needed. Thank you very much! Is there a place where I can l learn more about locals and globals, like adding strings and numbers to macros, and changing them? My skills are very limited on this matter.

        Thank you Chris for the suggestion, but Mike got it.

        Albert

        Comment


        • #5
          To learn the basics, start with the Programming Stata chapter in the [U] manual, with particular attention to the sub-chapter on Macros. (This is part of the online documentation that comes with your Stata installation, at least since version 11.) The -macro- chapter of the [P] manual s quite good for more advanced usage. In particular, there is a lengthy section on Remarks and examples that covers the basics, and some of the esoterica, very well.

          Comment


          • #6
            Thank you for the advice, Clyde. I'll start from the user's manual. Best,

            Albert

            Comment


            • #7
              Code:
               substr("`i'",-1,.)
              Here the variable for i = -10 would be labelled var_minus_0.

              Comment


              • #8
                Hi Nick. You are right, the solution was not the most elegant, but it worked for what I needed. I was trying to do a more elegant solution using the abs function, but it was not working, probably because, as Mike pointed out, the cond function forces you to use only string or only numeric values. Here is a more elegant solution I was able to come up with:

                Code:
                forvalues i = -10(1)10 {
                    local k = cond(`i'<0,"minus_" + regexr("`i'","-",""),"`i'")
                    di "`i'"
                    gen var_`k' = .
                }
                Thanks to all of you,

                Albert

                Comment


                • #9

                  Many different ways of tackling this. Here's one. Set a suffix element and then remove it when it's wrong.

                  Code:
                  * sandbox scaffolding  
                  clear  
                  set obs 1  
                  
                  local minus minus_  
                  forvalues i = -10/10 {    
                       local k = abs(`i')      
                       if (`i' > 0) local minus      
                       gen var_`minus'`k' = .  
                  }

                  Comment


                  • #10
                    Nick, using
                    Code:
                    if (`i' >= 0) local minus
                    is a clever way to do it. I did not realize if can be used as a function. Thank you.

                    Comment


                    • #11
                      Strictly, it can't. But we know what you mean.

                      The difference is between if as a command and if as a qualifier. In Stata, function is not another name for command.

                      Code:
                      help ifcmd
                      help if
                      Here is another way:

                      Code:
                      forvalues i = -10/-1 {  
                            local k = abs(`i')            
                            gen var_minus_`k' = .  
                      }  
                      
                      forvalues i = 0/10 {        
                            gen var_`i' = .  
                      }
                      Last edited by Nick Cox; 24 Oct 2016, 14:49.

                      Comment


                      • #12
                        Note that the strtoname function will replace all characters not allowed in a variable name with an underscore. Using the immediate expansion macro operator (help macro):

                        Code:
                        clear  
                        set obs 1  
                        
                        forvalues i = -10/10 {    
                             gen `=strtoname("var_`i'")' = .  
                        }

                        Comment

                        Working...
                        X