Announcement

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

  • Looping over alphabet

    I'm trying to use a loop to do several tabulations all at once. I'm using survey data, and have two distinct categories of variables: Q52* and Q53* where each '*' is a letter from the alphabet A-R. I know I could change the variable names to numeric and run a loop that way, but I was looking to see if there was an easy way to loop through letters; my searches haven't yielded anything I can use. I need to match the two groups to each other based on the alpha - for instance, Q52A to only Q53A. I can do them one at a time using

    svy linearized : tabulate Q52G Q53G, count cell

    but I want something similar to:
    quietly forval j = A/R {
    forval k = A/R {
    svy linearized : tab Q52`i' Q53`j' if (Q52`j'==Q53`k'), count cell
    }
    }

    Obviously, this does not work with letters, but is there a way to do this or should I just do them one at a time?

  • #2
    Stata stores the values in the alphabet in `c(alpha)' or `c(ALPHA)', see -help creturn- or type -creturn list-. This makes looping over the entire alphabet pretty easy, but since you want to loop over specific ranges of characters, you can use the ascii codes to do this. (Notes: 1) you can also just use variable list ranges like Qa1-Qb70 if your variables are in the correct order, or (2) you can also use -ds- to construct varlists using variable characteristics of interest. 3) for adapting your example, I simplified the loops since it's not clear what 'i' refers to.) Here's an example for looping over alpha characters in the way you describe:
    Code:
    
    
    
    clear
    set obs 100
    
    display `"`c(ALPHA)'"'
    
    forval j = 1/5 {
        foreach k in `c(ALPHA)' {
            gen Q`j'_`k' = int(runiform()*3)
            }
            }
            su *
            
    di `" `=char(65)'  to  `=char(90)' "'
    
    
      forval j = 82/90 {
    forval k = 82/90 {
       tab Q4_`=char(`j')'  Q5_`=char(`k')'
    }
    }
    Eric A. Booth | Senior Director of Research | Far Harbor | Austin TX

    Comment


    • #3
      Thank you for this. I'll look into modifying. The `i' was a typo; it should read:
      svy linearized : tab Q52`j' Q53`k' if (Q52`j'==Q53`k'), count cell

      Comment


      • #4
        So I tried this:
        quietly foreach j in `c(ALPHA)' {
        foreach k in `c(ALPHA)' {
        svy linearized : tab Q52`j' Q53`k' if (Q52`j'==Q53`k'), count cell
        }
        }

        However, I get an error when it tries to cycle to Q53S (which doesn't exist because the variables stop at R). How to I truncate this to only contain A-R?

        Comment


        • #5
          Consider the following, which stops at D rather than R for this example and displays the command I think you intend to run:
          Code:
          foreach j in `c(ALPHA)' {
            if "`j'"<="D" {
              display "COMMAND TO BE RUN: svy linearized : tab Q52`j' Q53`j', count cell"
            }
          }
          which produces
          Code:
          . foreach j in `c(ALPHA)' {
            2.   if "`j'"<="D" {
            3.         display "COMMAND TO BE RUN: svy linearized : tab Q52`j' Q53`j', count cell"
            4.   }
            5. }
          COMMAND TO BE RUN: svy linearized : tab Q52A Q53A, count cell
          COMMAND TO BE RUN: svy linearized : tab Q52B Q53B, count cell
          COMMAND TO BE RUN: svy linearized : tab Q52C Q53C, count cell
          COMMAND TO BE RUN: svy linearized : tab Q52D Q53D, count cell

          Comment


          • #6
            The second loop in my example above uses the ascii code equivalent to run from R to Z (the first loop was just to create some fake variables for the example and, as a bonus, to show how the complete alphabet can be accessed via `c(alpha)') To utilize my example just change this for the ascii codes for A through R in my second loop (you can use the SSC program -ascii- for quickly referencing the ascii codes).


            Code:
            clear
            set obs 100
            
            display `"`c(ALPHA)'"'
            
            forval j = 1/5 {
                foreach k in `c(ALPHA)' {
                    gen Q`j'_`k' = int(runiform()*3)
                    }
                    }
                    su *
                    
            di `" `=char(65)'  to  `=char(90)' "'
            
            
              forval j = 65/82 {
            forval k = 65/82 {
               tab Q4_`=char(`j')'  Q5_`=char(`k')'
            }
            }

            Last edited by eric_a_booth; 04 Jun 2017, 17:16.
            Eric A. Booth | Senior Director of Research | Far Harbor | Austin TX

            Comment


            • #7
              Originally posted by William Lisowski View Post
              Consider the following, which stops at D rather than R for this example and displays the command I think you intend to run:
              Code:
              foreach j in `c(ALPHA)' {
              if "`j'"<="D" {
              display "COMMAND TO BE RUN: svy linearized : tab Q52`j' Q53`j', count cell"
              }
              }
              which produces
              Code:
              . foreach j in `c(ALPHA)' {
              2. if "`j'"<="D" {
              3. display "COMMAND TO BE RUN: svy linearized : tab Q52`j' Q53`j', count cell"
              4. }
              5. }
              COMMAND TO BE RUN: svy linearized : tab Q52A Q53A, count cell
              COMMAND TO BE RUN: svy linearized : tab Q52B Q53B, count cell
              COMMAND TO BE RUN: svy linearized : tab Q52C Q53C, count cell
              COMMAND TO BE RUN: svy linearized : tab Q52D Q53D, count cell
              This worked like a charm! I guess I was making it more complicated than need be. Thank you!

              Comment

              Working...
              X