Announcement

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

  • Recoding variables in loops

    Hi, I am trying to recode three sets of variables (u* v* x*) into different categories from newly generated data in loop.


    Code:
    clear
    set seed 123
    set obs 100
    forvalues i = 1(1)10 {
    generate u`i' = round(runiform(1,10)*10)
    foreach var of varlist u* {
    recode `var' (min/50=1 yes) (*=2 no), g(new_`var')
    generate v`i' = round(runiform(1,10)*10)
    foreach var of varlist v* {
    recode `var' (min/30=1 yes) (31/50=2 maybe) (*=3 no), g(new_`var')
    generate x`i' = round(runiform(1,10)*10)
    foreach var of varlist x* {
    recode `var'  (min/30=1 yes) (31/50=2 maybe) (*=3 no), g(new_`var')
    }
    }
    }
    }
    The loop is running only once, and after that I get an error:

    Code:
    variable new_u1 already defined
    r(110);
    Please give me some suggestions about what might be going wrong here:

    Thank you!


  • #2
    If you followed the practice of indenting code within loops, it would be easier to see what is going wrong:

    Code:
    clear
    set seed 123
    set obs 100
    forvalues i = 1(1)10 {
        generate u`i' = round(runiform(1,10)*10)
        foreach var of varlist u* {
            recode `var' (min/50=1 yes) (*=2 no), g(new_`var')
            generate v`i' = round(runiform(1,10)*10)
            foreach var of varlist v* {
                recode `var' (min/30=1 yes) (31/50=2 maybe) (*=3 no), g(new_`var')
                generate x`i' = round(runiform(1,10)*10)
                foreach var of varlist x* {
                    recode `var'  (min/30=1 yes) (31/50=2 maybe) (*=3 no), g(new_`var')
                }
            }
        }
    }
    You have nested loops. So when i = 1, you create variable u`. You then do some recoding on u1, generate v1, etc. When you are done with i = 1, you have created variables u1, v1, x1, new_u1, new_v1, and new_x1. That is the end of the i = 1 iteration of the outermost loop. So Stata now sets i = 2. It generates variable u2. But now, -foreach var of varlist u* {- loop is asked to recode u1 and generate new_u1. But, Stata notices that new_u1 already exists--because it was created on the previous iteration of the loop. This error condition forces termination of execution and the error message.

    I assume what you want to do is create 10 u, v, and x variables, and then recode them to create 10 new_u, new_v, and new_x variables. The nested structure you have chosen can't accomplish that, as the loops over u*, v*, and x* attempt, in vain, to re-create the variables that already existed on the previous iteration for the -forvalues- loop.

    The simplest way to do this is with a single loop over i, and doing the -recode-s on the currently created variable.

    Code:
    forvalues i = 1(1)10 {
        generate u`i' = round(runiform(1,10)*10)
        recode u`i' (min/50=1 yes) (*=2 no), g(new_u`i')
        generate v`i' = round(runiform(1,10)*10)
        recode v`i' (min/30=1 yes) (31/50=2 maybe) (*=3 no), g(new_v`i')
        generate x`i' = round(runiform(1,10)*10)
        recode x`i'  (min/30=1 yes) (31/50=2 maybe) (*=3 no), g(new_x`i')
    }
    Last edited by Clyde Schechter; 07 Jan 2023, 17:49.

    Comment


    • #3
      Thanks so much Clyde! This is a very neat solution!

      Actually, I have difficulties with nested loops and was trying to do this as an experiment as well.

      I have a follow-up question to this please. I remember seeing the use of -repeat- function somewhere to create categorical variables, but unfortunately the help command shows -repeat is an out-of-date command; see foreach, forvalues, and while.-

      I want to create likert variables directly e.g. strongly agree, ... agree, instead of making numeric variables and then labelling them as in #2. Let's say 30 Likert questions in the sample data above. Is it possible to do that in Stata.

      Thanks in advance!

      Comment


      • #4
        Code:
        clear*
        set seed 1234
        set obs 100
        
        forvalues i = 1/30 {
            gen likert`i' = runiformint(1, 7)
        }
        label define likert 1   "Strongly Disagree" ///
                            2   "Disagree" ///
                            3   "Somewhat Disagree" ///
                            4   "Neither Agree Nor Disagree"    ///
                            5   "Somewhat Agree"    ///
                            6   "Agree" ///
                            7   "Strongly Agree"
                            
        label values likert* likert

        Comment

        Working...
        X