Announcement

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

  • Stata breaks the loop while looping over program define

    Hello Statalist,
    I need to bootstrap marginal effects from the two-part model as suggested in Belotti et al. 2015 (https://journals.sagepub.com/doi/pdf...867X1501500102). I have 40 equations (sub-sample groups) altogether, and instead of running each equation, I want to use do-loop to bootstrap the marginal effects of each estimate. I have tried to do this using the foreach loop, but stata breaks the loop when it encounters the end command. Would you mind offering some advice so that I do not have to define the program and bootstrap for each estimate?

    foreach sex in male female {
    foreach agegroup in age1824 age2544 age4564 age6574 age75over {
    foreach region in midw south neast west {
    capture program drop dydx_boot`sex'`agegroup'`region'
    program define dydx_boot`sex'`agegroup'`region', eclass
    svy: twopm totexp $varinterest $indepvar if `sex' ==1 & `agegroup' == 1 & `region' == 1, firstpart(logit) secondpart(glm, family(gamma) link(log))
    margins, dydx($varinterest) predict(duan) nose post
    end
    }
    }
    }

    foreach sex in male female {
    foreach agegroup in age1824 age2544 age4564 age6574 age75over {
    foreach region in midw south neast west {
    bootstrap _b, seed(12345) reps(1000): dydx_boot`sex'`agegroup'`region'
    }
    }
    }

    Thank you so much for your thoughts and expertise!

    Best,
    Ramesh
    Last edited by ramesh ghimire; 10 May 2021, 14:03.

  • #2
    Defining a program within a loop is something I've never seen done, and I suspect reflects a misunderstanding you have on how to introduce variations in the variables used by a program. If you don't find something illustrated in the documentation, it's likely it's not possible or not a good idea.

    Instead, you need to define your program outside the loop, and introduce your variations by making them parameters to your program. The "fancy" way to pass parameters to a program is via the -syntax- command, but it's the -args- command provides an easy approach to start off with while learning Stata programming, which I'll illustrate here. Further, I'd encourage you avoid the habit of using global macros, as they are essentially never necessary, and are considered a dangerous practice by most Stata programmers.
    I'm assuming that male, female, age*, midw, south, neast, and west are indicator variables defined in your data file, which I've guessed based on the way you tried to use them. (I'd say, by the way, that you've probably complicated things by creating all of these variables The Stata-ish way here would likely be to loop over the values of the original variables from which all those indicator variables were created.)

    Here's some example code, which I couldn't test, but which should illustrate some technique for you:
    Code:
    capture program dydx_boot
    program define dydx_boot, eclass
    args sexcat agecat regioncat
    svy: twopm totexp $varinterest $indepvar if `sexcat' == 1 & `agecat' == 1 & `regioncat' == 1, ///
            firstpart(logit) secondpart(glm, family(gamma) link(log))
    margins, dydx($varinterest) predict(duan) nose post
    end
    //
    foreach sex in male female {
        foreach agegroup in age1824 age2544 age4564 age6574 age75over {
            foreach region in midw south neast west {
                di "working on `sex' `agegroup' `region'"
                dydx_boot `sex' `agegroup' `region'
                bootstrap _b, seed(12345) reps(1000):dydx_boot `sex' `agegroup' `region'
                di  "-------------------------------------------------------------------"
            }
        }
    }

    Comment


    • #3
      You shouldn't be defining a new program for each group, since it's the same program just with different values of sex, agegroup and region. Take the program definition outside the loop. And then just have a single program dydx_boot that takes the values of sex, agegroup, and region as arguments. In order to do that, you need to reorganize your data. Instead of having separate variables called male and female or midw south neast and west, or those 5 age-group variables, create a single variable for sex, perhaps coded 0 for female and 1 for male, a single variable for region coded 1 for midw, 2 for south, 3 for neast, and 4 for west. Similarly create a single agegroup variable coded 1 through 5 for age1824 through age75over.

      The revised program looks like this:

      Code:
      capture program drop dydx_boot
      program define dydx_boot, eclass
          args sex agegroup region
          svy: twopm totexp $varinterest $indepvar if sex ==`sex' `agegroup == `agegroup' & region == `region', firstpart(logit) secondpart(glm, family(gamma) link(log))
          margins, dydx($varinterest) predict(duan) nose post
      end
      Do read -help args- and the linked section of the PDF documentation for a full understanding of how this works.

      And then your last section of code becomes something like this:

      Code:
      levelsof sex, local(sexes)
      levelsof agegroup, local(agegroups)
      levelsof region, local(regions)
      foreach s of local sexes {
          foreach a of local agegroups {
              foreach r of local regions {
                  bootstrap _b, seed(12345) reps(1000): dydx_boot `s' `a' `r'
              }
          }
      }
      In the future, when asking for help with code, show example data. As you did not do that, this proposed code is untested and may be incorrect. To show example data in a helpful way, always use the -dataex- command to do that. If you are running version 17, 16 or a fully updated version 15.1 or 14.2, -dataex- is already part of your official Stata installation. If not, run -ssc install dataex- to get it. Either way, run -help dataex- to read the simple instructions for using it. -dataex- will save you time; it is easier and quicker than typing out tables. It includes complete information about aspects of the data that are often critical to answering your question but cannot be seen from tabular displays or screenshots. It also makes it possible for those who want to help you to create a faithful representation of your example to try out their code, which in turn makes it more likely that their answer will actually work in your data.

      When asking for help with code, always show example data. When showing example data, always use -dataex-.

      Added: Crossed with #2, which suggests the same approach and also provides a helpful reminder about the danger of using global macros.

      Comment


      • #4
        Thanks you both - Mike Lacy and Clyde Schechter for your expertise! The program codes work to bootstrap marginal effects for each sub-sample.

        Comment

        Working...
        X