Announcement

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

  • Generate a variable picking the closest value to 0

    Hello,

    I have a data base composed of three numeric variables : A ; B ; C

    Code:
    clear
    input float(A B C)
    348  -6 -361
    436  82 -273
    403  49 -306
    376  22 -333
    390  36 -319
    390  36 -319
    397  43 -312
    383  29 -326
    364  10 -345
    375  21 -334
    384  30 -325
    403  49 -306
    422  68 -287
    355   1 -354
    413  59 -296
    347  -7 -362
    418  64 -291
    425  71 -284
    end
    I am trying to generate one variable (let's say X) containing the closest value to 0 among the three values provided by the variables A, B and C.

    For exemple, among the three values (348 ; -6 ; -361), I would like the X to choose -6. Among the values (383 ; 29 ; -326), I would like to X to choose 29.

    N.B. : I am using the Stata 14.0

    Thank you very much.
    Last edited by Bilal rafhi; 04 Jul 2022, 09:51.

  • #2
    Don't just say "I tried x and I wasn't successful, you need to actually SHOW what you did like I do here, and people will have an easier time of helping you.

    Comment


    • #3
      Code:
      gen new = cond(abs(A)>=abs(B), cond(abs(B)>=abs(C), C, B), A)
      Last edited by Bjarte Aagnes; 04 Jul 2022, 09:46.

      Comment


      • #4
        Code:
        gen long obs_no = _n
        rename (A-C) x=
        reshape long x, i(obs_no) j(vname) string
        gen x_abs = abs(x)
        by obs_no (x_abs), sort: gen wanted = x[1]
        drop x_abs
        reshape wide
        rename x* *
        Added: Crossed with #2 and #3. The solution proposed in #3 is simpler and more direct if the real situation involves only 3 variables. It will not scale well, however. The solution proposed here can be applied with any number of variables.

        Added Later: William Lisowski's solution in #5 is the best offered yet as it is scalable, simple, and transparent.
        Last edited by Clyde Schechter; 04 Jul 2022, 09:55.

        Comment


        • #5
          Code:
          generate X = .
          foreach v of varlist A-C {
              replace X = `v' if abs(`v')<abs(X)
          }
          list, clean noobs
          Code:
          . list, clean noobs
          
                A    B      C    X  
              348   -6   -361   -6  
              436   82   -273   82  
              403   49   -306   49  
              376   22   -333   22  
              390   36   -319   36  
              390   36   -319   36  
              397   43   -312   43  
              383   29   -326   29  
              364   10   -345   10  
              375   21   -334   21  
              384   30   -325   30  
              403   49   -306   49  
              422   68   -287   68  
              355    1   -354    1  
              413   59   -296   59  
              347   -7   -362   -7  
              418   64   -291   64  
              425   71   -284   71

          Comment


          • #6
            #3 shoud be disregarded if fail if abs(B) > abs(A) & abs(C) < abs(A). A similar approach, not depended on the given example data, could be:
            Code:
                gen Z = cond(abs(A)<=min(abs(B), abs(C)), A, cond(abs(B)<=abs(C), B, C))
            test:
            Code:
            clear all
            
            clear all
            
            set obs 100
            
            qui forvalues i = 1/3 {
                
                gen int v`i' = int(runiform(-10,10))
            }
            
            rename (v*)(A B C)
             
            expand 10^6
            
            timer clear
            
            timer on 1
            
                gen Z = cond(abs(A)<=min(abs(B), abs(C)), A, cond(abs(B)<=abs(C), B, C))
            
            timer off 1
            
            timer on 2
            
                generate X = .
            
                foreach v of varlist A B C {
                    
                    replace X = `v' if abs(`v')<abs(X)
                }
            
            timer off 2
            
            assert Z == X
            Last edited by Bjarte Aagnes; 04 Jul 2022, 14:13.

            Comment


            • #7
              Thank you very much for your answers. All your solutions worked very well.

              Comment


              • #8
                Do you need the sign of the result? or only the minimum absolute value - if so, and zero is also a valid return value, try
                Code:
                gen ZZ = min(abs(A), abs(B), abs(C))
                .

                Comment

                Working...
                X