Announcement

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

  • Iteration over variables

    Dear Statalist, I need your help again.

    Is there a way to iterate over variables that have an index in the name? Using _i or something similar?

    I know foreach var but this is a slightly more complicated problem.

    I have a list of variables S1 through S7, each indexed from 1 to 10 by the household member number. Eg: S1_01, S1_02...S1_10, S2_01 etc etc
    S1* stands for the name of the respondent (John, Mary, etc.)

    In another variable resp_name I have the name of the chosen respondent (John)

    I want to create new variables S1_resp-S7_resp in which to copy the values of the S1-S10 responses for the chosen respondent.

    Eg: gen S2_resp = S2_01 if S1_01=resp_name

    But without copying this 70 times. There has to be a smarter way.

    Foreach var iterates only over one variable, but I need to iterate over two at the same time (S1 and one of the others)

    Any ideas?
    Thank you very much.
    Regards,
    Laura Cojocaru

  • #2
    I think I solved it, thank you!
    Regards,
    Laura Cojocaru

    Comment


    • #3
      Originally posted by Laura C View Post
      I think I solved it, thank you!
      Laura,

      you could do it a in a number of ways, below is example with a while loop:
      Code:
      local i = 1
      while `i' <= 10 {
      su var_`i'
      local ++i
      }>
      Could you post your solution? The forum is a greatest of value if it provides a quick and easy access to practical solutions to existing problems. There is chance that in future someone will have a similar question and will simply borrow your code.
      Kind regards,
      Konrad
      Version: Stata/IC 13.1

      Comment


      • #4
        Konrad: To loop over strings "01" to "10", it is not sufficient to loop over numbers 1 to 10.

        One way to approach this is to apply an appropriate display format on the fly:

        Code:
        forval i = 1/10 {
             local I : di %02.0f `i'
             <code referring to `I'>
        }
        This question was also discussed in http://www.stata-journal.com/article...article=pr0051 The link leads to a .pdf accessible to all.

        Comment


        • #5
          I am sorry, I only see the answers now. Thank you both.

          This is how I solved it in the end.
          I had two types of variable names, the second one had a letter in the name. Maybe the two could have been combined but I was happy with this given the time constraints.

          1)
          forvalues index=2/7 {
          foreach num in 01 02 03 04 05 06 07 08 09 10{
          replace S`index'_resp=S`index'_`num' if S1_`num'==NOM_E
          }
          }

          2)
          foreach letter in A B {
          foreach num in 01 02 03 04 05 06 07 08 09 10{
          replace S4`letter'_resp=S4_`letter'_`num' if S1_`num'==NOM_E
          }
          }

          Does it look OK to you?
          Regards,
          Laura Cojocaru

          Comment


          • #6
            Listing the index 01 02 etc worked OK for my limited number of possible respondents, but Nick's solution seems much better for cases where it would be too much to list all of them. I will keep it in mind.
            Regards,
            Laura Cojocaru

            Comment


            • #7
              Practising and refining loop technique is a good idea as a preparation for when you really need it. I just note that in practice

              Code:
              foreach letter in A B {
                  foreach num in 01 02 03 04 05 06 07 08 09 10 {
                      replace S4`letter'_resp=S4_`letter'_`num' if S1_`num'==NOM_E
                  }
              }
              could be rewritten as

              Code:
              foreach num in 01 02 03 04 05 06 07 08 09 10{
                  replace S4A_resp=S4_A_`num' if S1_`num'==NOM_E
                  replace S4B_resp=S4_A_`num' if S1_`num'==NOM_E
              }
              but what you did is fine. Notice the indenting, which is not required by the syntax, but often improves readability. Big wars have been fought over the best number of spaces. I used to vote for 8, but have come to use 4 at least some of the time.

              Comment


              • #8
                Wow! Your rewriting of this code makes me laugh and cry at the same time. It is not the first time when I don't see the obvious, simple idea!

                Many thanks!
                Regards,
                Laura Cojocaru

                Comment


                • #9
                  I think you think I was joking, but I never joke on Statalist. See http://www.catb.org/jargon/html/I/indent-style.html

                  Comment


                  • #10
                    Apologies, my post probably came across as something different. I was actually serious, but not talking about indentation (I agree it is useful).

                    I was talking about figuring out how to deal with the letter in the name of the variable. It took me half an hour of searches, when I was in a time crunch. It did not cross my mind to repeat the command with the letter in the name. I am always shocked and saddened to see my mind failing me in this way. It made me laugh to realize just how easy the solution was. But it made me sad to see that how I was complicating an easy problem.
                    Regards,
                    Laura Cojocaru

                    Comment


                    • #11
                      Absolutely no need to apologise, as I really was joking, as you will find out if you stick out long enough.

                      The long-term point is that getting used to double loops is no loss, as they often are needed.

                      Comment


                      • #12
                        Hello again everyone. I am adding to my own older thread although this is a different issue that I would need help with.

                        I am trying to split some string responses. But the variable names are awful so I was trying to get the "splits" to be name q1_1 q1_2 etc

                        foreach var of varlist q1inth - q9inthecomingyearasofoctober1201{
                        split `var', parse(X) gen (substr("`var'"1,2)_)
                        }

                        This is not working. I get this error.

                        ( invalid name
                        "q1inthepast12monthsduringwhichmo invalid name
                        1 invalid name
                        , invalid name
                        2 invalid name
                        ) invalid name

                        While trying to figure out a solution, I also tried to first rename the variables and I realized that this is not working either: rename `var' substr( " `var' ",1,2 )

                        I did find this http://www.stata.com/statalist/archi.../msg00661.html but frankly I could not follow the explanation.

                        I have less than 20 variables so no big deal, I can split and/or rename manually, but as a matter of principle...it bothers me that I can;t figure it out. Any ideas?

                        Thank you so much.
                        Laura
                        Regards,
                        Laura Cojocaru

                        Comment


                        • #13
                          I am not flattered that you couldn't follow my post!

                          split
                          is for splitting the values of variables, not their names.

                          rename is nearer the mark, but it won't evaluate strings for you on the fly.

                          The following code renames variables to their first two characters:

                          Code:
                           
                          foreach var of varlist <whatever> { 
                              local new = substr("`var'", 1, 2) 
                              rename `var'  `new' 
                          }
                          but despite your use of similar expressions it seems that you don't want that as you mention names q1_1, q1_2.

                          My guess is that you want variables whose names begin with q1 to be named q1_1, q1_2, etc.; with q2 to be renamed q2_1, q2_2, etc.

                          If so, consider this:

                          Code:
                           
                          forval j = 1/9 { 
                              local i = 1   
                              foreach v of var q`j'* { 
                                  rename `v' q`j'_`i' 
                                  local ++i 
                              }
                          }
                          P.S. Please note the request on this forum to use full real names, e.g. Laura C????. See FAQ Advice Section 6.

                          Comment


                          • #14
                            Not following the post only speaks about my own limitations.

                            I just failed at explaining what I wanted to do.

                            My variables are currently named q1whatdidyoudolastyearbetweenjuneandjuly q2bhdjgfdufudsdds (awful stuff).....But this is not that important. The renaming of variables was only my attempt to understand why the split was not working. I think your solution is great. Thank you!!!

                            In fact, I WAS trying to split the content of the variables. They contain multiple possible answers to various questions, and the answers are demarcated by "X"s. Since split uses the variable name as a stub, with my split statement I was trying to extract just the first part of the var name to be used in the name of the resulting variables.

                            Eg. for variable q1whatdidyoudolastyearbetweenjuneandjuly , the first entry would be blahXetcetcXsomething
                            I was trying to split q1whatdidyoudolastyearbetweenjuneandjuly into q1_1 q1_2 q1_3 which would have the first entries blah etcetc something, respectively

                            Am I making more sense now?

                            I will change my name, but I may not be exactly proud of some of my questions.

                            Regards,
                            Laura Cojocaru

                            Comment


                            • #15
                              Thanks; that makes more sense. But the first code segment shows you how to rename to q1 etc. after which you should be able to loop over variables with code like

                              Code:
                               
                              forval j = 1/9 { 
                                  split q`j', parse(X) gen(q`j'_) 
                              }
                              I don't follow how you have more like 20 variables unless you are counting how many you will have after the split loop.

                              Comment

                              Working...
                              X