Announcement

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

  • writing a program within a foreach loop in STATA : avoiding error r(1)

    Hi all,

    I am trying to run a program to generate bootstrapped indirect effects from an SEM model in STATA. The program runs fine by itself but when I insert it in a foreach loop, the end of the program is read by STATA as end of my do-file. Is there a way to avoid this? A possible solution is to write the program outside of the foreach loop but given I need to do this for each IV/DV combination, it would be a lot of separate programs to write. Looking for a more elegant solution.

    Code:
    foreach dv in dv1 dv2 dv3 { 
        local i=1
        foreach iv in iv1 iv2 iv3 {
            capture program drop IndirectModel`dv'`i'
            program IndirectModel`i', rclass
            syntax [if] [in]
            quiet sem (`iv' -> med1) (`iv'  -> med2) (`iv' med1 med2 -> `dv') `if' `in'
            return scalar med1`iv' = [med1]_b[`iv']*[`dv']_b[med1]
            return scalar med2`iv' = [med2]_b[`iv']*[`dv']_b[med2]
            end  //this end leads to r(1) error in stata - 'end of do-file'
            local i=`i'+1
        }
            bootstrap r(med1`iv') r(med2`iv') , bca reps(5) nodots: IndirectModel`dv'`i'
            eststo model`iv'
    }

  • #2
    I don't get the need to write a program here.


    EDIT: show me what happens when you do
    Code:
    set tr on
    Before the loop
    Last edited by Jared Greathouse; 07 Sep 2022, 17:35.

    Comment


    • #3
      Yes, you absolutely must define the program(s) outside the loop. Any mention of -end- inside of a -foreach- loop leads to the error you are encountering. Here's an example that does not even include a program but just throws in an -end- command:

      Code:
      . clear*
      
      .
      . sysuse auto, clear
      (1978 automobile data)
      
      .
      . foreach v of varlist _all {
        2.     summ `v'
        3.     end
      --Break--
      r(1);
      
      end of do-file
      
      --Break--
      r(1);

      Comment


      • #4
        If you want
        • a Stata program, whose definition will be terminated by end
        to run within
        • a Stata block surrounded by braces {}, such as a loop
        you need to
        • define your program outside the brace-enclosed block, passing needed local variables to it as arguments
        • call program within the brace-enclosed block
        Even though your "end" is meant to terminate the program definition, at the time Stata is parsing the loop, the fact that the "end" belongs to the program definition and not to the loop is not recognized, and causes Stata to react incorrectly.

        In your case, you will need to pass the local macros `iv' and `dv' into your program as arguments. I think the following untested code might point you in a useful direction.
        Code:
        capture program drop IndirectModel
        program IndirectModel, rclass
        syntax varlist(min=2 max=2) [if] [in]
        local dv : word 1 of `varlist'
        local iv : word 2 of `varlist'
        quiet sem (`iv' -> med1) (`iv'  -> med2) (`iv' med1 med2 -> `dv') `if' `in'
        return scalar med1`iv' = [med1]_b[`iv']*[`dv']_b[med1]
        return scalar med2`iv' = [med2]_b[`iv']*[`dv']_b[med2]
        end  
        
        foreach dv in dv1 dv2 dv3 { 
            foreach iv in iv1 iv2 iv3 {
                bootstrap r(med1`iv') r(med2`iv') , bca reps(5) nodots: IndirectModel `dv' `iv' 
            }
        }
        I did not include the eststo command because I didn't quite understand what you sought. But the bootstrap command needs to be inside the innermost loop if you expect to bootstrap 9 separate sem models.

        Comment


        • #5
          Hey Jared - The program is needed because I want calculate the total indirect effect using multiple mediators. Using nlcom is not advisable since it makes additional assumptions about normal distribution of the nonlinear combination of coefficients. Bootstrap is advisable but it needs scalars to run the bootstrap on and we need the program to create the scalars.

          Nick - got it. Very clear and useful for future reference.

          William - thanks a ton! This is fantastic. This is exactly what I was looking for but did not know how to. Your untested code ran just fine.

          Thank you all!

          Comment


          • #6
            Originally posted by Neal Jha View Post
            Your untested code ran just fine.
            I do wish that happened more often with the untested code I create and attempt to use in my own research.

            Comment


            • #7
              Hi Neal
              Not sure if this is relevant, but the medsem package might be useful for your purposes. It can be run within the loop after model estimation. You've probably come across it, but just in case: it's a Monte Carlo (parametric) bootstrap approach that is much faster than non-parametric bootstrapping -- maybe not a big issue with your model, but Stata's sem command can be a bit slow with larger models. It can reduce the chances of non-covergence during estimation when bootstrapping smaller samples, etc., if problems arise due to the model/data.

              In case it's relevant, Instats is offering a series of seminars on Stata's sem command including bootstrapped CIs for indirect effects and conditional indirect effects. All seminars are combined in a Structured Course in case it's of interest.

              Best wishes
              Mike
              Last edited by Mike Zyphur; 11 Sep 2022, 23:25.

              Comment


              • #8
                Hey Mike,

                thanks for this suggestion! Can I check if I understand this correctly?
                1. I should run medsem instead of the bootstrap command inside my foreach loop? I avoided using medsem originally because it could only handle one mediator at a time. But I am guessing to use medsem, I could re-write the loop such that I ran medsem multiple times, one for each mediator.

                2. I should run the medsem with the 'zlc' option to use Zhao, Lynch & Chen's approach for monte carlo boostrapping. Correct?

                Overall, William's solution worked so at this stage I am ok to run with the bootstrapping method unless the monte carlo method is more reliable.

                Thanks again Mike!

                Comment

                Working...
                X