Announcement

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

  • Invalid name error in foreach loop

    Hi,

    Same title as a similar post from 2020 which did not answer my problem...

    I am trying to run a foreach loop with the following code:

    foreach item in 19T 19U 24T 29U 44T 49U 64V{
    gen `item'=amount if item==`item'
    }

    Error I get is:
    19T invalid name

    item is already a variable, first few lines look line this:
    19T
    19U
    24T
    29U
    34T
    39U

    (the items will repeat, so 19T will show up multiple times in the item variable)

    amount is another variable, first few lines:
    465299
    8137124
    38958
    1410000
    98959
    1399849

    What I want is to generate new variables with the amount that corresponds to the desired item code. for example:
    New variable: 19T
    First few lines:
    465299
    .
    .
    .
    .
    .
    [another value for when 19T shows up again in the data]

    New variable: 19U
    First few lines:
    8137124
    .
    .
    .
    etc.....

    Hopefully this makes sense. I can clarify further if need be. Thank you in advance for any advice!
    Last edited by Brooke Jones; 17 Oct 2021, 12:57.

  • #2
    What you want is not possible in Stata. Variable names are not allowed to begin with a number. If you want to create variables named item19U or the like, you can do that. But 19U is itself an illegal variable name. Variable names must begin with a letter of an underscore (_) character.

    Comment


    • #3
      Two problems: variable names cannot start with numbers, and your if-condition for a string variable doesn't use double quotes. This code fixes both problems:

      Code:
      foreach item in 19T 19U 24T 29U 44T 49U 64V{
      gen _`item'=amount if item=="`item'"
      }
      
      .list,abbrev(100)
      
           +----------------------------------------------------------------+
           | item   amount   _19T   _19U   _24T   _29U   _44T   _49U   _64V |
           |----------------------------------------------------------------|
        1. |  19T       12     12      .      .      .      .      .      . |
        2. |  19U       34      .     34      .      .      .      .      . |
        3. |  24T       56      .      .     56      .      .      .      . |
        4. |  29U       79      .      .      .     79      .      .      . |
        5. |  29U       78      .      .      .     78      .      .      . |
           +----------------------------------------------------------------+
      Alternatively, a reshape wide will produce what I believe is the desired output, without a loop:

      Code:
      bysort item (amount): gen new = _n
      reshape wide amount, i(new) j(item,string)
      
      . list,abbrev(100)
      
           +-----------------------------------------------------+
           | new   amount19T   amount19U   amount24T   amount29U |
           |-----------------------------------------------------|
        1. |   1          12          34          56          78 |
        2. |   2           .           .           .          79 |
           +-----------------------------------------------------+

      Comment


      • #4
        All comments by reply are bang on target, but there is still scope for a one-line solution (no loop needed).

        Code:
        * Example generated by -dataex-. For more info, type help dataex
        clear
        input str3 item float amount
        "19U" 8137124
        "24T"   38958
        "29U" 1410000
        "34T"   98959
        "39U" 1399849
        end
        
        separate amount, by(item) veryshortlabel 
        
        Variable      Storage   Display    Value
            name         type    format    label      Variable label
        ------------------------------------------------------------------------------------------------
        amount1         float   %9.0g                 19U
        amount2         float   %9.0g                 24T
        amount3         float   %9.0g                 29U
        amount4         float   %9.0g                 34T
        amount5         float   %9.0g                 39U
        
        list 
        
             +------------------------------------------------------------------+
             | item    amount   amount1   amount2   amount3   amount4   amount5 |
             |------------------------------------------------------------------|
          1. |  19U   8137124   8137124         .         .         .         . |
          2. |  24T     38958         .     38958         .         .         . |
          3. |  29U   1410000         .         .   1410000         .         . |
          4. |  34T     98959         .         .         .     98959         . |
          5. |  39U   1399849         .         .         .         .   1399849 |
             +------------------------------------------------------------------+

        Comment


        • #5
          Thank you all so much!!! This was fantastic advice and information, I went with what Ali suggested for the foreach loop but appreciate the alternative suggestions.

          Comment

          Working...
          X