Announcement

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

  • How to use foreach and forvalues?

    Hi, everyone. Lately I ran into a code writing problem. I am not very sure what is the difference between forvalues and foreach, and exactly how to use it in a loop.

    I have a variable items which is a string variable, and I hope to get a corresponding average of p, for each unique value of this items, e.g for product aaa, bbb, ccc, etc.

    The code I previously wrote could do the job to get the result, if I specify items == "bbb". But since the items actually contains hundreds of products, and I don't want to write manually the codes hundreds of times, so I tried to write a loop which looks like below. Obviously, my understanding of foreach and forvalues is still very clumsy after reading the stata manuals. As I click my do.file (below), the stata runs, gives no warnings in red, BUT there is no wanted result coming out. If I run the command -edit-, the ABC.dta looks still as it is. No observations deleted, no new variable is generated, and importantly, no wanted graphs are created.

    use ABC.dta

    levelsof items
    local items

    foreach l of local items{
    if items == `l'
    list if items == `l'
    keep if items == `l'
    egen avg_p = mean(p), by(country)
    }
    foreach l of local levels {
    sort country
    quietly by country: gen dup = cond(_N==1,0,_n)
    drop if dup>1
    save "`items`l''", replace
    }

    foreach l of local levels {
    clear
    use "`items`l''".dta
    edit

    merge m:1 country using income.dta

    scatter p income, mlabel(country)|| lfit p income ||, title("items"`l'"and income")
    graph save Graph "D:\STATA\items"`l'"and income.gph"
    }

    I wonder if anyone could help me check out where lies the problem. It is very hard for me to get any clue because stata runs the codes but produces no results and no warnings.

    I would like to thank you for your advice in advance!

    PS: how could I put the codes into a codes format which I often see in the forum? it looks very neat, but I don't know where is the icon for this function. can anyone help too?


    Best,
    Melanie

  • #2
    You can use the CODE keyword in square brackets to open the code block and use /CODE in square brackets to close the code block. The first problem in your code is the use of the -levelsof- command. To reference those values you need to use the local option for the command. However, given what it looks like you are doing, it would likely be much easier to use the collapse command to create a dataset with the summary statistics you are looking to graph and would reduce processing and I/O overhead.

    Comment


    • #3
      I think there's a simple answer -- the foreach code is not 100% correct! Here's what you want to do

      local var lva lgoutput lk lk_it lk_nit lemp lenergy
      foreach depvar in `var' {
      gen log_`depvar'=log(`depvar')
      }

      Maybe your version should also work, but I know for sure that "foreach" with "in" as with this setting works! Sometimes if the loop is not specified right, it just does nothing.

      Comment


      • #4
        A second issue is that the local macro levels is never initialized. So the second and third loops do nothing because there isn't anything to evaluate.

        Comment


        • #5
          Here are two variants on Christos's code:

          Code:
          local var lva lgoutput lk lk_it lk_nit lemp lenergy
          foreach depvar of local var {
               gen log_`depvar' = log(`depvar')
          }
          Code:
          foreach depvar in lva lgoutput lk lk_it lk_nit lemp lenergy {
               gen log_`depvar' = log(`depvar')
          }
          There is no inherent virtue in using a local for just this purpose (and no harm done either).

          Comment


          • #6
            Originally posted by wbuchanan View Post
            A second issue is that the local macro levels is never initialized. So the second and third loops do nothing because there isn't anything to evaluate.
            Thanks for your answers. So I try it here again Becuase I could not see a edit icon now.

            Code:
            use ABC.dta
            
            local items 
            
            foreach l of local items{
            if items == `l'
            list if items == `l'
            keep if items == `l'
            collapse (mean) items, by country dot
            }
            
            foreach l of local levels {
            sort country
            quietly by country: gen dup = cond(_N==1,0,_n)
            drop if dup>1
            save "`items`l''", replace
            }
            
            foreach l of local levels {
            clear 
            use "`items`l''".dta
            edit
            
            merge m:1 country using income.dta
            
            scatter p income, mlabel(country)|| lfit p income ||, title("items"`l'"and income")
            graph save Graph "D:\STATA\items"`l'"and income.gph"
            }
            However, I don't quite understand why you say my local macro levels are not initialized. What would be the sign that they are initialized or not? I think all my three loops have done nothing :P

            Thanks!

            Comment


            • #7
              Originally posted by Nick Cox View Post
              Here are two variants on Christos's code:

              Code:
              local var lva lgoutput lk lk_it lk_nit lemp lenergy
              foreach depvar of local var {
              gen log_`depvar' = log(`depvar')
              }
              Code:
              foreach depvar in lva lgoutput lk lk_it lk_nit lemp lenergy {
              gen log_`depvar' = log(`depvar')
              }
              There is no inherent virtue in using a local for just this purpose (and no harm done either).
              Nick,
              Thanks for the confirmation!

              Comment


              • #8
                Some comments on '#6:

                You set the local macro items to blank, i.e. you create it and destroy it all at once.

                You also seem to be confused between a variable and a local macro items.

                You never put anything in local macro levels, which is equivalent.

                Comment


                • #9
                  Melanie Fan In your first post you said you tried:

                  Code:
                  use ABC.dta
                  
                  levelsof items
                  local items 
                  
                  foreach l of local items{
                  if items == `l'
                  list if items == `l'
                  keep if items == `l'
                  egen avg_p = mean(p), by(country)
                  }
                  foreach l of local levels {
                  sort country
                  quietly by country: gen dup = cond(_N==1,0,_n)
                  drop if dup>1
                  save "`items`l''", replace
                  }
                  
                  foreach l of local levels {
                  clear 
                  use "`items`l''".dta
                  edit
                  
                  merge m:1 country using income.dta
                  
                  scatter p income, mlabel(country)|| lfit p income ||, title("items"`l'"and income")
                  graph save Graph "D:\STATA\items"`l'"and income.gph"
                  }
                  My suggestion was to instead so something like:

                  Code:
                  use ABC.dta
                  egen avg_p = mean(p), by(country items)
                  duplicates drop
                  merge m:1 country using income.dta
                  qui: levelsof items, loc(items)
                  foreach v of loc items {
                      scatter avg_p income if items == `v'  || lfitci avg_p income if items == `v', ti("Item `v' and Income") name(item`i', replace)
                  }
                  In other words, you do not need to use so many loops to accomplish what you are trying to do.

                  Comment

                  Working...
                  X