Search code examples
loopsstata

Fill variable with a nested loop Stata


I´m trying to create a variable like this in Stata:

date
2012_1
2012_2
2013_1
2013_2

with the next loop:

forval y=2012/2013{
forval m=1/2{
display `m'         
    gen date =  `y'_`m'
}
}   

But I´m getting this error in the first iteration: 2012_1 invalid name. Sorry if the question is obvious, I´m newbie in Stata.


Solution

  • You face more problems than you realise here, but all are simple.

    1. The immediate problem with your loop is that a value such as 2012_1 is intended by you as a value of a variable, but if so it must explicitly be a string, surrounded by "". The reason is that underscore _ is only acceptable as part of a string. Stata is clearly puzzled by your command. The error message does not quite fit the situation, although it is correct that 2012_1 is not an acceptable name, meaning the name of a variable or scalar.

    2. If you fixed that, your next problem would be that second time around your loop the variable already exists and so generate is unacceptable. You would need to replace. So, the generate statement should be taken outside the loop.

    3. Then again, all your loop does even with those problems fixed is to overwrite the variable each time with the same value. At your end of your loops all observations would contain the constant value 2013_2.

    4. Longer term, there is still a problem. Evidently you want a monthly date variable, but monthly date variables like that are of little use in Stata. They sort in the correct order, but they are essentially useless for statistics or graphics.

    This is a better idea all round:

    generate mdate = . 
    local i = 1 
    
    forval y = 2012/2013 {
        forval m = 1/2 {
            replace mdate = ym(`y', `m') in `i' 
            local ++i       
        }
    } 
    

    That is still not good style. I guess that you don't really want only months 1 and 2, but we can't know what you really want.

    Do this in Stata:

    clear 
    set obs 48 
    generate mdate = ym(2011, 12) + _n 
    format mdate %tm 
    list 
    

    to get an idea of a better approach -- with no loops at all.