Announcement

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

  • Problem with local marco or If-conditions?

    Dear Statalist,

    I wish to generate variable "a" on basis of variable "a" (data generated within script) and "b" (cont.data) and scalar "c" and "d"

    time_id a b
    1 . 1
    2 . 0
    3 . 2.8
    4 . 0.325
    5 . 0
    6 . 0
    7 . 0.73
    8 . 0
    9 . 1.6
    10 . 0

    scalar c 0.01
    scalar d 1


    generate a = 0
    if time_id>1 local i = a[_n-1] + b - c
    if `i' < d {
    replace a = `i'
    }
    else if `i' > d {
    replace a = d
    }
    else if `i' < 0 {
    replace a = 0
    }

    It appears to be some problem with the program which perhaps is related to how I conditioned the local macro.

    Any suggestions?

  • #2
    Your post is very difficult to understand. There is something that, I guess, is supposed to be a data listing, and the header refers to three variables time_id, a, and b, but the data shown underneath have only two values in each record. Moreover, it's unclear if the numbers 1., 2. 3;. etc. are intended to be values of time_id or are just sequential record numbers. Please read FAQ #12 for good advice has to how to post data examples in a useful manner.

    Moreover, you then post two -scalar- commands that are both syntax errors, so you never actually got to the part of the code you seem to be questioning. Please read the FAQ, again, to be reminded that when you post code you should post what you actually ran, and also show the output you actually got.

    Now, even without reference to any sample data, your code
    Code:
    if time_id>1 local i = a[_n-1] + b - c
    is almost certainly wrong. You are using an -if- command, which is different from an -if- qualifier or condition. In particular, -if- commands cannot refer to variables, because only one value will be accessed. When you mention a variable (a) in the -if- command, Stata assumes you are referring to the value in the first observation. But you have gone farther and subscripted it with [_n-1], so Stata interpretes this as asking about the value of a in the 0th observation. There is, of course, no 0th observation, so the value is missing. At that point, no matter what b and c are, local i is set to missing value. Now, since missing value is larger than any non-missing value, the -else if `i' > d- branch will apply. (Actually, that's what would happen if scalar d were defined, which it isn't because your -scalar d 1- command is a syntax error and doesn't actually define scalar d. In reality, you will just get an error message.)

    The difference between -if- commands, which assess a single static boolean condition and then determine whether a command (or block of commands) will be executed at all, and -if-qualifiers, which are used to identify a subset of the data to which a command will be applied, is fundamental in Stata. It takes a while to get comfortable with the distinction. But they are by no means exchangeable. Wherever you need one, the other will surely fail. So do read -help if- and -help ifcmd-, and the associated sections of the users's manuals.

    Now, while it is easy to pick out why the code cited is wrong, there isn't much to go by in your post to help you find a correct approach to what you're trying to do. So, after you read the FAQ, try re-posting your question. Be sure to include some actual example data (using -dataex-), your current version of the actual code (in code delimiters) and also show us what you expect the results to be.

    Comment


    • #3
      Clyde's critique is comprehensive. I spent my time trying to figure out what you might be trying to do. As Clyde says, the use of the if command has almost certainly led you down the wrong path.

      Does the following produce what you expect? Note the corrections to the scalar statement, and the use of dataex to present the values of time_id and b (the value of a shown in your data is always missing, no need to input it.)
      Code:
      * Example generated by -dataex-. To install: ssc install dataex
      clear
      input float(time_id b)
       1    0
       2    0
       3  2.8
       4 .325
       5    0
       6    0
       7  .73
       8    0
       9  1.6
      10    0
      11  -99
      end
      
      scalar c = 0.01
      scalar d = 1
      
      generate a = 0
      replace a =  max(0,min(a[_n-1]+b-c, d)) if time_id>1
      Code:
      . list
      
           +----------------------+
           | time_id      b     a |
           |----------------------|
        1. |       1      0     0 |
        2. |       2      0     0 |
        3. |       3    2.8     1 |
        4. |       4   .325     1 |
        5. |       5      0   .99 |
           |----------------------|
        6. |       6      0   .98 |
        7. |       7    .73     1 |
        8. |       8      0   .99 |
        9. |       9    1.6     1 |
       10. |      10      0   .99 |
           |----------------------|
       11. |      11    -99     0 |
           +----------------------+

      Comment


      • #4
        I can see why you consider my post difficult to understand. I was not clear about my data and made some mistakes (e.g. missing = in defining the scalars). However, many thanks for useful hints AND William, for solving my problem with:

        replace a = max(0,min(a[_n-1]+b-c, d)) if time_id>1

        It does the job! William, could you please describe in detail how to interpret this sequence?

        It is correct understood that 'max' ignores missing values, then write "0" if a[_n-1]+b-c<>0, d & <>0), write a[_n-1]+b-c < d & <>0, write d<a[_n-1]+b-c & <>0?

        Many thanks for swift reply and for helping me although a confusing post.
        Last edited by Simon Falck; 06 May 2017, 14:28.

        Comment


        • #5
          Max does not ignore missing values.

          Missing values are only an issue on the first observation where _n is 1, because a[_n-1] will be a[0] which is missing. For _n>1 there will be no issue (at least with your sample data) because a[_n-1] will not be missing, and I assume (since your sample data suggests it) that b is not ever missing, and c and d are scalars that are not missing.

          With that out of the way, we can think of this as three steps in a single expression
          1. calculating a[_n-1]+b-c, then
          2. replacing that result with d if d is smaller, then
          3. replacing that result with 0 if 0 is larger

          Comment


          • #6
            Dear William,

            Many thanks for explaining this, for your help!

            Best

            Comment

            Working...
            X