Announcement

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

  • Assign range of values to local macro

    Hey,

    I have lots of loops in my code which all run through the same values. Currently the code looks as follows:

    Code:
    forval i = 4/12 {
    - do something -
    }
    Is there a way to get "4/12" in a macro WITHOUT doing it manually (i.e. macro vals 4 5 6 ....). In other words, is there a way to "evaluate" 4/12 and put the value in a macro?

    Additional question:
    Is there a way to get the maximum value of a macro and assign it to a different macro? E.g.:

    Code:
    local x 1 2 3 4
    I would like to have another local containing the value 4.

    Thanks in advance!

  • #2
    You can do this:

    Code:
    . numlist "4/12"
    
    . ret li
    
    macros:
                r(numlist) : "4 5 6 7 8 9 10 11 12"
    and then use the result.

    But forval is precisely the place where you should (usually) let forval work out what it is looping over. That is much more efficient.

    Similarly, there is no obvious gain from

    Code:
    local limits 4/12
    
    forval i = `limits' {
          ...
    }
    unless it especially suits you. I wouldn't want to read that code.

    There is no simple way of extracting the maximum from a macro that springs to mind.

    It's just a string, so somehow or other you have to arrange a loop over its words, which in your example are all numeric.

    Here are two ways to do it and no doubt there are several others.

    Code:
    local x 1 2 3 4
    
    local max : word 1 of `x'
    
    forval j = 2/`: word count `x'' {
        local max = max(`max', `: word `j' of `x'')
    }
    
    di `max'
    
    local x : list clean x
    local X : subinstr local x " " ",", all
    di max(`X')
    Another method is to sort the list and then peel off the last value.
    Last edited by Nick Cox; 12 Jul 2017, 08:29.

    Comment


    • #3
      Thanks for your quick reply!

      The problem is, I don't want to write all elements of the list (4/12 would be ok, but in one case my loops are running from 1 to 58, which would be very cumbersome).

      Code:
       
       local limits 4/12  forval i = `limits' {       ... }
      Using this I get a invalid syntax error.

      Comment


      • #4
        When do you (think you) need to spell out 1 2 3 ... 58?

        You can always go

        Code:
        forval j = 1/58 { 
              ...
        }

        This worked for me:


        Code:
        local limits 4/12
        
        forval i = `limits' {
              di `i' 
        }
        The definition of the local must be visible to the loop syntax.

        Comment


        • #5
          I have a panel dataset with 58 countries and loops are running through all of them. I just want to "centralize" this part (to make it easier to change that if I should just need a subset).


          Thanks, the second example works! (Currently it looks like your first example)

          Could you please also answer my additional question about the maximum value?

          Comment


          • #6
            Sorry, but I don't understand #5.

            I have a panel dataset with 58 countries and loops are running through all of them. I just want to "centralize" this part (to make it easier to change that if I should just need a subset).
            That is not to me a precise programming problem. You would need to select a subset -- but how best to do it depends on what the subset is.

            I commented at length on getting the maximum in #2. What else are you asking for?

            Comment


            • #7
              Originally posted by Nick Cox View Post
              That is not to me a precise programming problem. You would need to select a subset -- but how best to do it depends on what the subset is.
              Yes, I just want to select a subset. But for me it is a programming problem. At least the way I described it. But it might make more sense to extract the country ids at the beginning and adjust the loops accordingly. This way it would also be straightforward to select a subset at the beginning (which is currently not possible, at least not without the loops running through ids that are not in the dataset).

              Originally posted by Nick Cox View Post
              I commented at length on getting the maximum in #2. What else are you asking for?
              Sorry, I missed that.

              Thank you!

              Comment


              • #8
                You can always turn your script into a program defined by an ado file and use if and in machinery for selecting a subset. That's a good way to learn important programming skills. Conversely, it can be hard work making a program truly general.

                Comment


                • #9
                  Originally posted by Nick Cox View Post
                  You can always turn your script into a program defined by an ado file and use if and in machinery for selecting a subset. That's a good way to learn important programming skills.
                  Thanks for the hint, I'll keep that in mind!

                  Originally posted by Nick Cox View Post
                  Conversely, it can be hard work making a program truly general.
                  Yes, definitely. Sometimes it doesn't make sense to invest the time to make it "truly general".

                  Comment

                  Working...
                  X