Announcement

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

  • table of several mediation models


    first, is it possible to use the -mediate- command when there is more than one mediator as in: predictor --> mediator 1 --> mediator 2 --> outcome (i.e., the mediators are not parallel)? second, if the above is not possible, I know I can turn to SEM for this but I'm not sure how get the results from "estat teffects" and from "estat ic" into a comparative table (my client wants to compare several possible mediators for an outcome and where the initial predictor is always the same); can I do this using -etable-? or do I need to go to -collect-? regardless is there a tutorial or FAQ on this using SEM? I am not providing data here but it is easy to envision using the auto data as in: foreign --> mpg --> headroom -->price and foreign --> weight --> trunk --> price and foreign --> mpg --> trunk --> price the above may not be sufficiently clear so here is the code for the first of the models above
    Code:
     sem (foreign -> mpg, ) (foreign -> price, ) (mpg -> headroom, ) (mpg -> price,) (headroom -> price, ), nocapslatent
    followed by
    Code:
     estat teffects  
    estat ic
    I want to include in the table the direct effects, the indirect effects the total effects, p-values and CIs for the preceding, and N, AIC, BIC

  • #2
    just to note that I, after more than 24 hours, received a response from Stata tech support, directing me to the following on Statalist:
    https://www.statalist.org/forums/for...lts-from-nlcom
    other responses welcome also as the above appears to be, at most, a start on an issue that I may not even want (i.e., I may want the total indirect effect - have to discuss with client)
    Last edited by Rich Goldstein; 18 Jul 2025, 11:40.

    Comment


    • #3
      Richard Williams had written a program that allows you to do this using estout from SSC (see https://www.statalist.org/forums/for...ects-after-sem). You just need to add the estat ic results to this. Below, you just need to change the command line (highlighted) across iterations.

      Code:
      capture program drop te_direct
      program te_direct, eclass
          quietly estat teffects
          mat b = r(direct)
          mat V = r(V_direct)
          local N = e(N)
          ereturn post b V, obs(`N')
          ereturn local cmd te_direct 
      end
      
      capture program drop te_indirect
      program te_indirect, eclass
          quietly estat teffects
          mat b = r(indirect)
          mat V = r(V_indirect)
          ereturn post b V
          ereturn local cmd te_indirect 
      end
      
      capture program drop te_total
      program te_total, eclass
          quietly estat teffects
          mat b = r(total)
          mat V = r(V_total)
          ereturn post b V
          ereturn local cmd te_total 
      end
      
      
      sysuse auto, clear
      estimates clear
      eststo main: sem (foreign -> mpg, ) (foreign -> price, ) (mpg -> headroom, ) (mpg -> price,) (headroom -> price, ), nocapslatent
      foreach eq in direct indirect total{
          est restore main
          te_`eq'
          est sto `eq'
      }
      est restore main
      estat ic
      estadd scalar AIC = r(S)[1, "AIC"]: direct
      estadd scalar BIC = r(S)[1, "BIC"]: direct
      esttab direct indirect total, cells(b(fmt(1)) p(par fmt(3)) ci(par fmt(1))) ///
      mtitles(direct indirect total) scalars(N AIC BIC) noomitted modelwidth(20)  ///
      note(P-values in parentheses; CIs in brackets) collab(none)
      Res.:

      Code:
      . estat teffects
      
      
      Direct effects
      ------------------------------------------------------------------------------
                   |                 OIM
                   | Coefficient  std. err.      z    P>|z|     [95% conf. interval]
      -------------+----------------------------------------------------------------
      Structural   |
        mpg        |
           foreign |   4.945804   1.343628     3.68   0.000     2.312341    7.579268
        -----------+----------------------------------------------------------------
        price      |
               mpg |  -303.8203   57.89831    -5.25   0.000    -417.2989   -190.3417
          headroom |  -186.5669   380.8368    -0.49   0.624    -932.9934    559.8596
           foreign |   1714.109   693.2622     2.47   0.013     355.3404    3072.878
        -----------+----------------------------------------------------------------
        headroom   |
               mpg |   -.060509   .0154749    -3.91   0.000    -.0908392   -.0301788
           foreign |          0  (no path)
      ------------------------------------------------------------------------------
      
      
      Indirect effects
      ------------------------------------------------------------------------------
                   |                 OIM
                   | Coefficient  std. err.      z    P>|z|     [95% conf. interval]
      -------------+----------------------------------------------------------------
      Structural   |
        mpg        |
           foreign |          0  (no path)
        -----------+----------------------------------------------------------------
        price      |
               mpg |   11.28898   23.22422     0.49   0.627    -34.22965    56.80761
          headroom |          0  (no path)
           foreign |  -1446.803   477.0048    -3.03   0.002    -2381.715   -511.8907
        -----------+----------------------------------------------------------------
        headroom   |
               mpg |          0  (no path)
           foreign |  -.2992658   .1116587    -2.68   0.007    -.5181128   -.0804188
      ------------------------------------------------------------------------------
      
      
      Total effects
      ------------------------------------------------------------------------------
                   |                 OIM
                   | Coefficient  std. err.      z    P>|z|     [95% conf. interval]
      -------------+----------------------------------------------------------------
      Structural   |
        mpg        |
           foreign |   4.945804   1.343628     3.68   0.000     2.312341    7.579268
        -----------+----------------------------------------------------------------
        price      |
               mpg |  -292.5314   54.64507    -5.35   0.000    -399.6337    -185.429
          headroom |  -186.5669   380.8368    -0.49   0.624    -932.9934    559.8596
           foreign |   267.3066   747.9207     0.36   0.721    -1198.591    1733.204
        -----------+----------------------------------------------------------------
        headroom   |
               mpg |   -.060509   .0154749    -3.91   0.000    -.0908392   -.0301788
           foreign |  -.2992658   .1116587    -2.68   0.007    -.5181128   -.0804188
      ------------------------------------------------------------------------------
      
      
      . esttab direct indirect total, cells(b(fmt(1)) p(par fmt(3)) ci(par fmt(1))) ///
      > mtitles(direct indirect total) scalars(N AIC BIC) noomitted modelwidth(20)  ///
      > note(P-values in parentheses; CIs in brackets) collab(none)
      
      ---------------------------------------------------------------------------
                                    (1)                  (2)                  (3)
                                 direct             indirect                total
      ---------------------------------------------------------------------------
      main                                                                       
      foreign                       4.9                                       4.9
                                (0.000)                                   (0.000)
                              [2.3,7.6]                                 [2.3,7.6]
      ---------------------------------------------------------------------------
      price                                                                      
      mpg                        -303.8                 11.3               -292.5
                                (0.000)              (0.627)              (0.000)
                        [-417.3,-190.3]         [-34.2,56.8]      [-399.6,-185.4]
      headroom                   -186.6                                    -186.6
                                (0.624)                                   (0.624)
                         [-933.0,559.9]                            [-933.0,559.9]
      foreign                    1714.1              -1446.8                267.3
                                (0.013)              (0.002)              (0.721)
                         [355.3,3072.9]     [-2381.7,-511.9]     [-1198.6,1733.2]
      ---------------------------------------------------------------------------
      headroom                                                                   
      mpg                          -0.1                                      -0.1
                                (0.000)                                   (0.000)
                            [-0.1,-0.0]                               [-0.1,-0.0]
      foreign                                           -0.3                 -0.3
                                                     (0.007)              (0.007)
                                                 [-0.5,-0.1]          [-0.5,-0.1]
      ---------------------------------------------------------------------------
      N                              74                                          
      AIC                        2107.3                                          
      BIC                        2130.3                                          
      ---------------------------------------------------------------------------
      P-values in parentheses; CIs in brackets

      Comment


      • #4
        Andrew Musau - thank you for this; however, I apparently wasn't clear enough in #1 - I want to be able to show several different models in the table where the mediators differ; possibly, your and Rich's code can be modified to do this, but I don't see how; to be clearer, I would like each different mediator model to have its results in a column and each column to have the results from a model with a different mediator (first level of mediation)
        Last edited by Rich Goldstein; 18 Jul 2025, 14:11.

        Comment


        • #5
          Then it's just a matter of looping over the models. I'm not sure whether you want all comparisons in one wide table or in three separate tables organized by effect. Both approaches are possible, but here's an implementation of the latter. You can assign the models more meaningful names — here, they are simply labeled 1, 2, and 3.

          Code:
          local m1 (foreign -> mpg, ) (foreign -> price, ) (mpg -> headroom, ) (mpg -> price,) (headroom -> price, )
          local m2 (foreign -> weight, ) (foreign -> price, ) (weight -> trunk, ) (weight -> price,) (trunk -> price, )
          local m3 (foreign -> mpg, ) (foreign -> price, ) (mpg -> trunk, ) (mpg -> price,) (trunk -> price, ) 
          local M 3
          
          
          
          capture program drop te_direct
          program te_direct, eclass
              quietly estat teffects
              mat b = r(direct)
              mat V = r(V_direct)
              local N = e(N)
              ereturn post b V, obs(`N')
              ereturn local cmd te_direct 
          end
          
          capture program drop te_indirect
          program te_indirect, eclass
              quietly estat teffects
              mat b = r(indirect)
              mat V = r(V_indirect)
              ereturn post b V
              ereturn local cmd te_indirect 
          end
          
          capture program drop te_total
          program te_total, eclass
              quietly estat teffects
              mat b = r(total)
              mat V = r(V_total)
              ereturn post b V
              ereturn local cmd te_total 
          end
          
          
          sysuse auto, clear
          estimates clear
          forval i=1/`M'{
              eststo m`i': sem `m`i'', nocapslatent
              foreach eq in direct indirect total{
                  est restore m`i'
                  te_`eq'
                  est sto `eq'_`i'
              }
              est restore m`i'
              estat ic
              estadd scalar AIC = r(S)[1, "AIC"]: total_`i'
              estadd scalar BIC = r(S)[1, "BIC"]: total_`i'
          }
          
          
          esttab total_* using myfile.rtf, replace title(Total Effects) ///
          cells(b(fmt(1)) p(par fmt(3)) ci(par fmt(1))) nomtitles ///
          scalars(N AIC BIC) noomitted modelwidth(15) ///
          note(P-values in parentheses; CIs in brackets) collab(none)
          
          esttab direct_* using myfile.rtf, append title(Direct Effects) ///
          cells(b(fmt(1)) p(par fmt(3)) ci(par fmt(1))) nomtitles ///
          scalars(N) noomitted modelwidth(15) ///
          note(P-values in parentheses; CIs in brackets) collab(none)
          
          esttab indirect_* using myfile.rtf, append title(Indirect Effects) ///
          cells(b(fmt(1)) p(par fmt(3)) ci(par fmt(1))) nomtitles ///
          scalars(N) noomitted modelwidth(15) ///
          note(P-values in parentheses; CIs in brackets) collab(none)
          Res.:

          Click image for larger version

Name:	Capture1.PNG
Views:	1
Size:	18.5 KB
ID:	1780017

          Click image for larger version

Name:	Capture3.PNG
Views:	1
Size:	11.6 KB
ID:	1780019
          Attached Files

          Comment


          • #6
            Andrew Musau - thank you very much - I will need to spend some time on this but this looks good; I will try it out no later than early next week

            Comment


            • #7
              if anyone can suggest standard Stata code (e.g., based on -collect-) that would be greatly appreciated

              Comment


              • #8
                Using the above code from Andrew Musau, here is how I used etable to build similar tables.
                Code:
                cls
                clear all
                
                program te_direct, eclass
                    quietly estat teffects
                    mat b = r(direct)
                    mat V = r(V_direct)
                    local N = e(N)
                    ereturn post b V, obs(`N')
                    ereturn local cmd te_direct
                end
                
                program te_indirect, eclass
                    quietly estat teffects
                    mat b = r(indirect)
                    mat V = r(V_indirect)
                    ereturn post b V
                    ereturn local cmd te_indirect
                end
                
                program te_total, eclass
                    quietly estat teffects
                    mat b = r(total)
                    mat V = r(V_total)
                    ereturn post b V
                    ereturn local cmd te_total
                end
                
                sysuse auto
                
                local m1 (foreign -> mpg, ) (foreign -> price, ) (mpg -> headroom, ) (mpg -> price,) (headroom -> price, )
                local m2 (foreign -> weight, ) (foreign -> price, ) (weight -> trunk, ) (weight -> price,) (trunk -> price, )
                local m3 (foreign -> mpg, ) (foreign -> price, ) (mpg -> trunk, ) (mpg -> price,) (trunk -> price, )
                local M 3
                
                forval i = 1/`M' {
                    sem `m`i'', nocapslatent
                    estimates store m`i'
                    foreach eq in direct indirect total {
                        estimates restore m`i'
                        te_`eq'
                        estimates store `eq'_`i'
                    }
                }
                
                etable, ///
                    showeq ///
                    estimates(m*) ///
                    mstat(N) ///
                    mstat(aic) ///
                    mstat(bic) ///
                    title(Fitted models)
                collect export fitted.tex, replace
                
                etable, ///
                    showeq ///
                    estimates(direct_*) ///
                    title(Direct effects)
                collect export direct.tex, replace
                
                etable, ///
                    showeq ///
                    estimates(indirect_*) ///
                    title(Indirect effects)
                collect export indirect.tex, replace
                
                etable, ///
                    showeq ///
                    estimates(total_*) ///
                    title(Total effects)
                collect export total.tex, replace
                Here are screenshots of the PDF files resulting from the exported LaTeX documents.

                Click image for larger version

Name:	Screenshot 2025-07-22 at 11.34.19 AM.png
Views:	1
Size:	25.4 KB
ID:	1780142

                Click image for larger version

Name:	Screenshot 2025-07-22 at 11.34.12 AM.png
Views:	1
Size:	48.1 KB
ID:	1780143

                Click image for larger version

Name:	Screenshot 2025-07-22 at 11.34.27 AM.png
Views:	1
Size:	83.6 KB
ID:	1780144

                Click image for larger version

Name:	Screenshot 2025-07-22 at 11.34.35 AM.png
Views:	1
Size:	43.1 KB
ID:	1780145

                Comment


                • #9
                  Jeff Pitblado (StataCorp) - thank you very much

                  Comment


                  • #10
                    thanks to all; but the solution I used was based on what tech support first sent (stupidly, I asked for a different solution from them and then went back to the first as, for this exploratory study, many models were estimated and reported; first, the code I eventually used:
                    Code:
                    collect clear 
                    use alldata1,clear
                    
                    noi di "outcome is insulinuiumlormiul"
                    noi su insulinuiumlormiul
                    noi di ""
                    noi di "table of results for this outcome:"
                    
                    sem (sci -> armspctfat, ) (sci -> insulinuiumlormiul, ) (armspctfat -> insulinuiumlormiul, ), nocapslatent
                    
                    estat teffects     
                    
                    collect get var = "Total.effect", tags(col[1])
                    collect get var = "Direct",tags(col[2])
                    collect get var = "Indirect",tags(col[3])
                    *collect get var = "Std.err", tags(col[4])
                    collect get var = "P-value", tags(col[4])
                    collect get var = "CI-lb", tags(col[5])
                    collect get var = "CI-ub", tags(col[6])
                    
                    collect get eff1 = r(total)[1,"insulinuiumlormiul:sci"],tags(col[1])
                    collect get eff1 = r(direct)[1,"insulinuiumlormiul:sci"],tags(col[2])
                    collect get eff1 = r(indirect)[1,"insulinuiumlormiul:sci"],tags(col[3])
                    *collect get eff1 = sqrt(r(V_indirect)[2,2]),tags(col[4])
                    * to calc and save p and CI
                    local pv = (2*normal((-abs(r(indirect)[1,3]))/sqrt(r(V_indirect)[3,3])))
                    local ci_lb = ((r(indirect)[1,3]) - ///
                    (invnormal(0.975)*sqrt(r(V_indirect)[3,3])))
                    local ci_ub = ((r(indirect)[1,3]) + ///
                    (invnormal(0.975)*sqrt(r(V_indirect)[3,3])))
                    *noi mac li _pv
                    collect get eff1 = `pv', tags(col[4])
                    collect get eff1 = `ci_lb', tags(col[5])
                    collect get eff1 = `ci_ub', tags(col[6])
                    
                    *obtain ic and collect
                    estat ic
                    collect get var = "N",tags(col[7])
                    collect get var = "AIC",tags(col[8])
                    collect get var = "BIC",tags(col[9])
                    collect get eff1 = r(S)[1,"N"],tags(col[7])
                    collect get eff1 = r(S)[1,"AIC"],tags(col[8])
                    collect get eff1 = r(S)[1,"BIC"],tags(col[9])
                    
                    *next mediator
                    
                    sem (sci -> legspctfat, ) (sci -> insulinuiumlormiul, ) (legspctfat -> insulinuiumlormiul, ), nocapslatent
                    
                    estat teffects     
                    
                    collect get eff2 = r(total)[1,"insulinuiumlormiul:sci"],tags(col[1])
                    collect get eff2 = r(direct)[1,"insulinuiumlormiul:sci"],tags(col[2])
                    collect get eff2 = r(indirect)[1,"insulinuiumlormiul:sci"],tags(col[3])
                    *collect get eff1 = sqrt(r(V_indirect)[2,2]),tags(col[4])
                    * to calc and save p and CI
                    local pv = (2*normal((-abs(r(indirect)[1,3]))/sqrt(r(V_indirect)[3,3])))
                    local ci_lb = ((r(indirect)[1,3]) - ///
                    (invnormal(0.975)*sqrt(r(V_indirect)[3,3])))
                    local ci_ub = ((r(indirect)[1,3]) + ///
                    (invnormal(0.975)*sqrt(r(V_indirect)[3,3])))
                    *noi mac li _pv
                    collect get eff2 = `pv', tags(col[4])
                    collect get eff2 = `ci_lb', tags(col[5])
                    collect get eff2 = `ci_ub', tags(col[6])
                    
                    *obtain ic and collect
                    estat ic
                    collect get eff2 = r(S)[1,"N"],tags(col[7])
                    collect get eff2 = r(S)[1,"AIC"],tags(col[8])
                    collect get eff2 = r(S)[1,"BIC"],tags(col[9])
                    *end of mediator
                    
                    collect layout (result) (col)
                    
                    collect style header col, level(hide)
                    collect style cell result[var],border(bottom) border(top,pattern(nil))
                    collect style cell result[var],smcl(text)
                    collect style cell result, basestyle nformat(%6.3f)
                    collect style cell result[N], nformat(%3.0f)
                    collect label levels result var "Mediator-1"
                    collect label levels result eff1 "arms%fat"
                    collect label levels result eff2 "legs%fat"
                    noi collect preview
                    and here is the output
                    Code:
                    outcome is insulinuiumlormiul
                    
                        Variable |        Obs        Mean    Std. dev.       Min        Max
                    -------------+---------------------------------------------------------
                    insulinuiu~l |         46    4.826087    2.962389          1       15.4
                    
                    table of results for this outcome:
                    
                    Mediator-1      | Total.effect Direct Indirect P-value  CI-lb CI-ub      N      AIC      BIC
                    ----------------+---------------------------------------------------------------------------
                    arms%fat        |        0.030 -0.135    0.165   0.622 -0.491 0.821 46.000  618.373  631.174
                    legs%fat        |        0.030 -0.974    1.005   0.334 -1.035 3.045 46.000  601.237  614.037
                    but my actual situation had many more rows

                    while this is meant as closure, there is actually one followup question: as you can see from the code, I duplicated the code for each possible mediator as I could not see how to loop and change both the mediator and the count (the number that the identifier "eff" end in as "eff1" and "eff2")

                    Comment


                    • #11
                      Originally posted by Rich Goldstein View Post

                      while this is meant as closure, there is actually one followup question: as you can see from the code, I duplicated the code for each possible mediator as I could not see how to loop and change both the mediator and the count (the number that the identifier "eff" end in as "eff1" and "eff2")
                      For such a purpose, it is common to set a counter that increments with each iteration of the loop. The following is not tested.

                      Code:
                      collect get var = "Total.effect", tags(col[1])
                      collect get var = "Direct",tags(col[2])
                      collect get var = "Indirect",tags(col[3])
                      collect get var = "P-value", tags(col[4])
                      collect get var = "CI-lb", tags(col[5])
                      collect get var = "CI-ub", tags(col[6])
                      collect get var = "N",tags(col[7])
                      collect get var = "AIC",tags(col[8])
                      collect get var = "BIC",tags(col[9])
                      
                      
                      local mediators armspctfat legspctfat
                      local i 0
                      foreach m of local mediators{
                          local++i
                          sem (sci -> `m', ) (sci -> insulinuiumlormiul, ) (`m' -> insulinuiumlormiul, ), nocapslatent
                          estat teffects
                          collect get eff`i' = r(total)[1,"insulinuiumlormiul:sci"],tags(col[1])
                          collect get eff`i' = r(direct)[1,"insulinuiumlormiul:sci"],tags(col[2])
                          collect get eff`i' = r(indirect)[1,"insulinuiumlormiul:sci"],tags(col[3])
                          local pv = (2*normal((-abs(r(indirect)[1,3]))/sqrt(r(V_indirect)[3,3])))
                          local ci_lb = ((r(indirect)[1,3]) - ///
                          (invnormal(0.975)*sqrt(r(V_indirect)[3,3])))
                          local ci_ub = ((r(indirect)[1,3]) + ///
                          (invnormal(0.975)*sqrt(r(V_indirect)[3,3])))
                          *noi mac li _pv
                          collect get eff`i' = `pv', tags(col[4])
                          collect get eff`i' = `ci_lb', tags(col[5])
                          collect get eff`i' = `ci_ub', tags(col[6])
                          *obtain ic and collect
                          estat ic
                          collect get eff`i' = r(S)[1,"N"],tags(col[7])
                          collect get eff`i' = r(S)[1,"AIC"],tags(col[8])
                          collect get eff`i' = r(S)[1,"BIC"],tags(col[9])
                      }

                      Comment


                      • #12
                        Andrew Musau - thank you - a little embarrassed that I didn't remember about that

                        Comment

                        Working...
                        X