Announcement

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

  • Simultaneously run through two forvalues loops

    Dear statalist,
    I'm trying to program the following commands more mechanically:

    Code:
    rename intentionof14 intentionof6
    rename intentionof18 intentionof7
    rename intentionof112 intentionof8
    One problem is that the code is supposed to run through various datasets and the number of variables may vary each time (e.g. in this particular data there are the variables intentionof14-intentionof112 but for another data download there may be more variables, say intentionof14-intentionof118). Therefore I cannot use the actual numbers in the commands. I let stata read out the number of variables first and then use two foreach loops:

    Code:
    split intentionof, p(",")
    drop intentionof
    ds intentionof*
    local number13:  word count `r(varlist)'
    display `number13'
    5
    
    split intentionof1, p("#", "|")
    drop intentionof1
    ds intentionof1*
    local number14: word count `r(varlist)'
    display `number14'
    12
    
    local number15 = `number13'+1
    local `number16' = `number14'-4
    forvalues i=4(4)`number14' {
    forvalues j=`number15'/`number16' {
    rename intentionof1`i' intentionof`j'
    }
    }
    Obviously, this does not work because stata runs one loop after the other while I would need some command to run through both loops simultaneously. Maybe forvalues is not the right approach. Can anyone help?
    Thank you,
    Sarah Linde

  • #2
    You have a need for parallel loops, not nested loops -- which means that there is really just one loop there.

    This is a common question, and understandably. See e.g. this thread from yesterday https://www.statalist.org/forums/for...-loop-question

    Apart from the long-undocumented for, Stata doesn't have a construct explicitly for parallel loops, but the technique is just to write one loop and use other syntax for looping over other entities in the same loop.

    In your case, you could do this

    Code:
    local NEW  6 7 8 
    
    foreach old of numlist 4(4)12 { 
          gettoken new NEW : NEW 
          rename intentionof`old' intentionof`new' 
    }
    although for three renames that is really no gain over writing three individual statements.

    Comment


    • #3
      Dear Nick,
      thanks for the quick response. The problem is that I do not know the definitive list for the local. That is, in the case presented here, there are just three variables to be renamed in intentionof6, intentionof7, intentionof8 but in another case there might be more variables and the local would have to be for instance "6 7 8 9 10". The idea was to write the do-file in a way that it does not have to be adjusted manually for every new data download. That is why I created the locals "number13" to "number16" which "read out" the number of variables to be renamed each time. Any idea how I could incorprate this in the code you suggested?
      Thanks.

      Comment


      • #4
        Your question hinges on matters of principle together with many details specific to your dataset. That is natural, but it is easier for me to talk about principle than to absorb or understand all the detail you have given (or the detail you haven't given).

        I would loop over intentionof* and create new variables one by one around a loop.

        Code:
        local counter = 1 
        foreach var of var intentionof* { 
               gen new`counter' = `var' 
               local ++counter 
        }
        Your prefix could be anything legal: new is just something different.

        If it's important to you to use the same names, then after the loop you go

        Code:
        drop intentionof* 
        rename new* intentionof*
        In your case you seem to have a need (not explained) to start numbering at 6, but if so

        Code:
        local counter = 6
        is how you start.

        Comment


        • #5
          Thank you, that works perfectly.
          For information, see the final code below with the locals "number13" and "number14" representing the number of particular variables in the dataset extracted a few lines before.

          Code:
          local counter `=`number13'+1' // number13 here 6
          forvalues i=4(4)`number14' { // number14 here 12
              gen intentionof`counter' = intentionof1`i'
              local ++counter
              drop intentionof1`i'
          }

          Comment


          • #6
            Dear Nick,

            To go back to this question: I'd like to create a loop for local linear regressions between different intervals (i.e if x>=23 & x<=26 etc), I'm trying to do it with two forvalues but I get strange results. Thanks in advance.

            Code:
            local m=1
            foreach num of numlist 2001 2002 2004 2012 {
            forvalues i=26(1)29 {
            forvalues j = 23(-1)20 {
            di _n "Dependent Var = `dvar'"
            di "Year = `num'"
            eststo model_`m': ivregress 2sls `dvar' `ivar' (R = i.A) if x>=`j' & x<=`i' & year==`num'
            local m `++m'
            }}}
            Last edited by Gedeao Locks; 11 Oct 2019, 10:04.

            Comment


            • #7
              Without data there is nothing reproducible there.

              We don't know what "strange results" you're getting. Standard advice is to give, at a minimum, details on what happened and why it wasn't what you wanted. Otherwise you're not so very far from the limiting case of "My code doesn't work. Anyone know why not?".

              But my guess is that you have just one loop over 4 cases in each of three (really, four) parallel lists. What you are doing is asking for 4 x 4 x 4 = 64 possibilities most of which probably don't exist or make sense in your data.

              Here's my guess codified, but even fixing various likely problems I note that you don't explain in #6 where local macros dvar and ivar come from.


              Code:
              local nlist 2002 2002 2004 2012 
              local ilist 26 27 28 29 
              local jlist 23 22 21 20 
              
              forval m = 1/4 { 
                  gettoken n nlist : nlist 
                  gettoken i ilist : ilist 
                  gettoken j jlist : jlist 
              
                  di _n "Dependent Var = `dvar'"
                  di "Year = `n'"
              
                  eststo model_`m': ivregress 2sls `dvar' `ivar' (R = i.A) if inlist(x, `j', `i') 
              }
              I've avoided the problem by looping over m but the code


              Code:
              local m `++m'
              is a long way from what you want.

              local m is there assigned to be a copy of the local macro whose name is ++m . But if you get that far you will just be told


              Code:
              local macro `m' not found
              What you meant to write, presumably, was just

              Code:
              local ++m 
              but as said a loop is easier.

              Comment

              Working...
              X