Announcement

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

  • Loops and double loops

    Hi everybody
    I am new to programming in stata and need some help to run a loop (or a double loop).
    By mistake I posted my question in Sandbox, so if you have seen it there, I apologize for double posting.

    I have a dataset with more than 600 variables and 1300 observations.
    I know you prefer real data, however, I cant load an example of my data, as I work on a remote server, but I can provide a simple example to illustrate my case (also not in STATA):
    id a_1 b_2 c_3 d_4 e_1 f_2 g_3 h_4 i_1 j_2 k_3 l_4 x
    1 2 2 5 6 2 1 9 4 3 4 5 6 34
    2 3 2 6 9 9 5 3 9 6 4 8 1 55
    3 9 4 1 1 5 7 6 5 4 1 1 8 87
    My data is built upon 3 types of variables which are connected. All _1 is connected, all _2 and so on.
    I want to do something like this:
    1. If a_1 * e_1 <x then do a_1 * e_1 + b_2 *f_2 else stop. If a_1 * e_1 + b_2 *f_2 <x then do a_1 * e_1 + b_2 *f_2 + c_3*g_3, else stop and soforth until ….. + d_4*h_4 if <= x then stop else stop at the step before. (for id1 the loop should stop at a_1*e_1 + b_2*f_2 = 6 < 34, adding the next pair of variables c_3*g_3 make the sum exceed 34).
    2. sum(i_1 * e_1 + j_2*f_2 + k_3*g_3 + l_4*h_4) until we reach the max variable from the above loop (e f g or h). (for id1 it will be i_1*e_1 + j_2*f_2 = 10)

    I have done something like the code beneath, but it do not keep the variables together (_1 with _1 and so forth) or in order (it is important that the first sum is evaluating first a_1*e_1, then b_2*f_2, then c_3*g_3 and then d_4*h_4 until x is reached, and stop, if one more variable exceed x) and the second "loop" do not stop at the max variable from first “loop” (it should also evaluate in order from variable i to l):

    vl create omk = (a_1 b_2 c_3 d_4)
    vl create pot = (e_1 f_2 g_3 h_4)
    vl create eff = (i_1 j_2 k_3 l_4)
    gen omk = 0
    gen omk_temp = 0
    gen eff = 0

    foreach i of varlist $omk {
    foreach v of varlist $pot {
    foreach y of varlist $eff {
    replace omk_temp = omk_temp + `i’ * `v’
    replace omk = omk + `i’ * `v’ if omk_temp <= x
    replace eff = eff + `y’ * `v’ if omk_temp <= x
    }
    }
    }

    The result should for the example be:
    Id omk eff
    1 6 10
    2 55 98
    3 84 73
    It might be the wrong way to go, and "while" could be an opportunity, I just cannot figure how.

    Hope you have some kind of suggestion.

    All the best,
    Line

  • #2
    Better to have common prefixes. Here is some technique.

    Code:
    * Example generated by -dataex-. For more info, type help dataex
    clear
    input byte(id a_1 b_2 c_3 d_4 e_1 f_2 g_3 h_4 i_1 j_2 k_3 l_4 x)
    1 2 2 5 6 2 1 9 4 3 4 5 6 34
    2 3 2 6 9 9 5 3 9 6 4 8 1 55
    3 9 4 1 1 5 7 6 5 4 1 1 8 87
    end
    
    frame put *, into(new)
    
    frame new{
        rename (a_1- d_4) (var1_#), addnumber(1)
        rename (e_1- h_4) (var2_#), addnumber(1)
        rename (i_1- l_4) (var3_#), addnumber(1)
        gen wanted1=cond(var1_1*var2_1<=x, var1_1*var2_1, .)
        gen wanted2= cond(var1_1*var2_1<=x, var2_1*var3_1, .)
        g next=wanted1
        forval i=2/4{
            qui replace next= next + (var1_`i'*var2_`i') if !missing(next)
            qui replace wanted1= next if next<=x & !missing(wanted1)
            qui replace wanted2= wanted2 + (var2_`i'*var3_`i') if next<=x & !missing(wanted1)
        }
    }
    
    frlink 1:1 id, frame(new)
    frget wanted*, from(new)
    frame drop new
    Res.:

    Code:
    . l
    
         +-----------------------------------------------------------------------------------------------------------+
         | id   a_1   b_2   c_3   d_4   e_1   f_2   g_3   h_4   i_1   j_2   k_3   l_4    x   new   wanted1   wanted2 |
         |-----------------------------------------------------------------------------------------------------------|
      1. |  1     2     2     5     6     2     1     9     4     3     4     5     6   34     1         6        10 |
      2. |  2     3     2     6     9     9     5     3     9     6     4     8     1   55     2        55        98 |
      3. |  3     9     4     1     1     5     7     6     5     4     1     1     8   87     3        84        73 |
         +-----------------------------------------------------------------------------------------------------------+
    
    .

    Comment

    Working...
    X