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

  • Macros and loops

    Dear All,

    I have a couple of problems with macro and loops (they migh be correlated anyway):


    suppose I have the following models:

    reg y x z
    reg y x z k
    reg y x z k w
    Regressors have completely different names. I would like to set a loop to run those regressions. I tried the following:

    global set1 "x z"
    global set2 "x z k"
    global set3 "x z k w"
    local All "set1 set2 set3"
    foreach s in local All{
    reg y `s'
    est store mod_`s'

    It happens that Stata run many models one for each variable within the global macro, instead of having only 3 estimations.


    Another problem is the following. I have many models and usually I need to drop some variables. For instance i use "x z k w a b c d e f g" as regressors. In some cases I need to drop regressor "a", in other cases regressor "e" and so on. Is there any way I can do it within a loop? Maybe exploiting the position of each variable within the string?

    As I mentioned above, the two problems may be correlated each other. Possibily, solving the second one could solve the first as well.

    Thanks in advance.


  • #2
    It's best to learn to solve one problem before you try to solve another.

    Your First block of code seems very confused to me. There is syntax to refer to globals and locals once you've defined them, but you're hardly using it.

    Also, you're confusing two syntaxes, foreach ... of and foreach ... in.

    So, your syntax will expand to

    reg y local
    est store mod_local
    reg y All
    est store mod_All 
    which isn't what you want at all. The first line is meaningless and the code will fail there. But the second wouldn't work as you wish either, because Stata won't expand the local name.

    There are various ways to get #1 to work. Here's one.

    local set1 "x z"
    local set2 "x z k"
    local set3 "x z k w"  
    foreach i in 1 2 3 {    
        reg y `set`i''    
        est store mod_`i'  
    You're setting up three levels there in your original code: an overall set All, a set of set names that it contains and a set of variable names in each set. But all you want is a loop over three models. In fact, there is no real gain over doing it directly.

    regress y x z
    est store mod_1  
    regress y x z k
    est store mod_2  
    regress y x z k w  
    est store mod_3
    Naturally, your real problem may be one where a loop is a good idea, but we can't see that.

    On Second, your question isn't clear. If there's more structure in your question than "I want to omit the 5th variable named"; then "I want to omit the 9th variable named", and so on -- then possibly there is a way of doing it neatly. Sorry, but your question isn't far from "I am planning to do something that is a bit complicated. Will there be a simple way to code it?" The answer might be Yes, but that answer can't be helpful.

    Last edited by Nick Cox; 12 Feb 2019, 09:05.


    • #3
      Nick Cox Thanks Nick. Regarding my first question, you are right. I could do in the way you suggested and it will be much simpler. Regarding the second question, I try to be more specific.

      Consider the following example (this is a simplified example, as my model contains more regressors). I use the dataset auto.dta and choose the following set of regressors "weight foreign length price" . I would like to run some models and in one of them I would drop for instance the regressor foreign. So I try to use:

      sysuse auto, clear
      local regressors "weight foreign length price"
      tokenize "`regressors'"
      forvalues i=1/4{
      reg mpg `regressors' if `i'!=`2'
      If I run the above code, I do not get what I want. In my idea, the above lines should returns an estimation which contains all the regressors but not foreign as is the 2 token in the list.

      Since in my model, I have at least 10 regressors, if I can "exclude" in such a way one of them when I have to do so, it would be much easier than writing down all the list of regressors every time.
      Last edited by Dario Maimone Ansaldo Patti; 12 Feb 2019, 10:00.


      • #4
        In the problem underlining #3 there are two regressions so far as I can see, omitting the second predictor and including it. That's not even a loop problem. It's two lines of code, one regress statement with and one without.

        Your code expands to -- with the data example

        reg mpg weight foreign length price if 1 != foreign
        reg mpg weight foreign length price if 2 != foreign
        reg mpg weight foreign length price if 3 != foreign
        reg mpg weight foreign length price if 4 != foreign
        The first implies domestic cars only. The others imply all cars. The last three regressions are all the same. The statements are all legal. They have nothing to do with omitting regressors. They may or may not omit observations.

        You may be reaching for quite different technique. Here is a problem that is a loop: to use every other predictor.

        foreach v of local regressors {
              local x : list regressors - v
              regress mpg `x'
        The biggest enemy of programmers -- after not knowing the language enough or indeed at all -- is wishful thinking, hoping that the language behaves in ways that you would like.


        • #5
          Nick Cox Thanks a lot.