Announcement

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

  • Create table of outputs from svy: mean, over(catvar) and Wald tests of differences between each pair of catvar levels

    Hi. I'm using a fully updated version of Stata 18 on Windows 10 to analyse survey data, which I have declared as such using svyset.

    I've been trying and failing to produce a table of mean values of a binary outcome variable (binvar) for a 12-level categorical/factor variable (catvar) and Wald tests of the differences between each pair of catvar level mean values after (or as part of) running the following loop:

    Code:
    svy: mean binvar , over(catvar)
    levelsof catvar, local(levels)
    foreach l of local levels{
    local lev1 : label (catvar) `l'
    levelsof catvar, local(levels)
    foreach m of local levels{
    local lev2 : label (catvar) `m'
    di "T tests for: `lev1' vs `lev2' "
    test c.binvar@`l'.catvar = c.binvar@`m'.catvar
    }
    }
    I think the very talented Andrew Musau comes close to what I’m trying to achieve in his reply to Statalist post 1737126-exporting-svy-mean-and-test-results, except that solution is for a table of mean values of three different variables for two groups (0.black and 1.black) and Wald test results for the differences between each of the group mean values for the three variables. Andrew's code follows:

    Code:
    webuse nhanes2f, clear
    svyset psuid [pweight=finalwgt], strata(stratid)
    estimates clear
    eststo m1: svy: mean zinc age weight, over(black)
    local i 0
    foreach var in zinc age weight{
       local ++i
        test _b[c.`var'@0.black] = _b[c.`var'@1.black]
        mat F`i'= `:di %3.2f `r(F)''
        mat colname F`i'= "c.`var'@1.black"
        mat pval`i'= `r(p)'
        mat colname pval`i'= "c.`var'@1.black"
    }
    mat F= F1,F2,F3
    mat pval= pval1,pval2,pval3
    estadd mat F: m1
    estadd mat pval: m1
    esttab m1, cells("b  F(star pval(pval))") starl(* 0.1 ** 0.05 *** 0.01) nonumb mlab(none) collab(Coef. F-stat.) label

    Using the table produced by the code above as an example of what might be possible, I would like to produce and export a table (to Word or Excel) featuring the mean values, standard errors, and 95% confidence intervals for each of the 66 pairs of catvar levels and the p value for each of the 66 Wald tests of the differences between these pairs of mean values. Something like this:
    Mean SE 95% CI p value (Prob > F)
    c.binvar@1.catvar [blank]
    c.binvar@2.catvar
    c.binvar@1.catvar [blank]
    c.binvar@3.catvar
    c.binvar@1.catvar [blank]
    c.binvar@4.catvar
    c.binvar@1.catvar [blank]
    ... [many missing rows]
    c.binvar@11.catvar [blank]
    c.binvar@12.catvar
    I would also like to export the resulting table to Word (or Excel if that’s easier) and, ideally, fix my loop, above, so it doesn’t duplicate all the Wald tests I need and include invalid Wald tests of the difference between the mean value for the same level of catvar, e.g. test c.binvar@2.catvar = c.binvar@2.catvar.

    However, fixing the loop is secondary to producing and exporting the table, because I can probably cope with deleting rows of a table exported into Word or Excel, if necessary.

    Please let me know if I need to provide more information to help inform a solution.

    Thank you very much for considering this post.
    Last edited by Kevin Chadwick; 30 Apr 2024, 22:01.

  • #2
    You could use frames to get the desired format, then export using export excel. Using collect would be even better as this would allow you to export in many different formats.

    Code:
    help collect
    Code:
    webuse nhanes2f, clear
    svyset psuid [pweight=finalwgt], strata(stratid)
    estimates clear
    set seed 05012024
    gen catvar=runiformint(1, 4)
    cap frame drop results
    frame create results str100(Variable) float(Mean SE) str20(CI pvalue)
    levelsof catvar, local(levels)
    foreach l of local levels{
        local lev1 : label (catvar) `l'
        levelsof catvar, local(levels)
        foreach m of local levels{
            local lev2 : label (catvar) `m'
                if `l'!=`m'{
                    svy: mean zinc if catvar==`l', over(catvar)
                    local name1= "`:colname r(table)'"
                    local mean1= r(table)["b", 1]
                    local se1= r(table)["se", 1]
                    local ci1 = "["+ strofreal(r(table)["ll", 1], "%4.3f")+ "," +strofreal(r(table)["ul", 1], "%4.3f")+"]"
                    svy: mean zinc if catvar==`m', over(catvar)
                    local name2= "`:colname r(table)'"
                    local mean2= r(table)["b", 1]
                    local se2= r(table)["se", 1]
                    local ci2 ="["+ strofreal(r(table)["ll", 1], "%4.3f")+ "," +strofreal(r(table)["ul", 1], "%4.3f")+"]"
                    qui: svy: mean zinc, over(catvar)
                    di "T tests for: `lev1' vs `lev2' "
                    test c.zinc@`l'.catvar = c.zinc@`m'.catvar
                    frame post results ("`name1'") (`mean1') (`se1') ("`ci1'") ("")
                    frame post results ("`name2'") (`mean2') (`se2') ("`ci2'") ("`=strofreal(`r(p)', "%5.4f")'")          
                }
            }
        }
    
    
    frame results: l, sep(0)
    frame results: export excel using myresults, replace keepcellfmt firstrow(variables)
    Res.:

    Code:
    . frame results: l, sep(0)
    
         +------------------------------------------------------------------+
         |        Variable       Mean         SE                CI   pvalue |
         |------------------------------------------------------------------|
      1. | [email protected]    87.1733   .5185216   [86.116,88.231]          |
      2. | [email protected]   87.51054   .5844588   [86.319,88.703]   0.5149 |
      3. | [email protected]    87.1733   .5185216   [86.116,88.231]          |
      4. | [email protected]   87.27916   .6151835   [86.024,88.534]   0.8210 |
      5. | [email protected]    87.1733   .5185216   [86.116,88.231]          |
      6. | [email protected]   86.74393   .6384489   [85.442,88.046]   0.3576 |
      7. | [email protected]   87.51054   .5844588   [86.319,88.703]          |
      8. | [email protected]    87.1733   .5185216   [86.116,88.231]   0.5149 |
      9. | [email protected]   87.51054   .5844588   [86.319,88.703]          |
     10. | [email protected]   87.27916   .6151835   [86.024,88.534]   0.6781 |
     11. | [email protected]   87.51054   .5844588   [86.319,88.703]          |
     12. | [email protected]   86.74393   .6384489   [85.442,88.046]   0.1892 |
     13. | [email protected]   87.27916   .6151835   [86.024,88.534]          |
     14. | [email protected]    87.1733   .5185216   [86.116,88.231]   0.8210 |
     15. | [email protected]   87.27916   .6151835   [86.024,88.534]          |
     16. | [email protected]   87.51054   .5844588   [86.319,88.703]   0.6781 |
     17. | [email protected]   87.27916   .6151835   [86.024,88.534]          |
     18. | [email protected]   86.74393   .6384489   [85.442,88.046]   0.3735 |
     19. | [email protected]   86.74393   .6384489   [85.442,88.046]          |
     20. | [email protected]    87.1733   .5185216   [86.116,88.231]   0.3576 |
     21. | [email protected]   86.74393   .6384489   [85.442,88.046]          |
     22. | [email protected]   87.51054   .5844588   [86.319,88.703]   0.1892 |
     23. | [email protected]   86.74393   .6384489   [85.442,88.046]          |
     24. | [email protected]   87.27916   .6151835   [86.024,88.534]   0.3735 |
         +------------------------------------------------------------------+
    Click image for larger version

Name:	Capture.PNG
Views:	1
Size:	95.6 KB
ID:	1751892

    Comment


    • #3
      Of course, if you want combinations rather than permutations, you can specify the condition:

      if `l'!=`m'{
      as

      Code:
      if `l'!=`m' & `l'<`m'{
      Res.:

      Code:
      . frame results: l, sep(0)
      
           +------------------------------------------------------------------+
           |        Variable       Mean         SE                CI   pvalue |
           |------------------------------------------------------------------|
        1. | [email protected]    87.1733   .5185216   [86.116,88.231]          |
        2. | [email protected]   87.51054   .5844588   [86.319,88.703]   0.5149 |
        3. | [email protected]    87.1733   .5185216   [86.116,88.231]          |
        4. | [email protected]   87.27916   .6151835   [86.024,88.534]   0.8210 |
        5. | [email protected]    87.1733   .5185216   [86.116,88.231]          |
        6. | [email protected]   86.74393   .6384489   [85.442,88.046]   0.3576 |
        7. | [email protected]   87.51054   .5844588   [86.319,88.703]          |
        8. | [email protected]   87.27916   .6151835   [86.024,88.534]   0.6781 |
        9. | [email protected]   87.51054   .5844588   [86.319,88.703]          |
       10. | [email protected]   86.74393   .6384489   [85.442,88.046]   0.1892 |
       11. | [email protected]   87.27916   .6151835   [86.024,88.534]          |
       12. | [email protected]   86.74393   .6384489   [85.442,88.046]   0.3735 |
           +------------------------------------------------------------------+
      Last edited by Andrew Musau; 01 May 2024, 09:00.

      Comment


      • #4
        Andrew. Thank you very much for such a quick and detailed response. It looks wonderful. Combinations is exactly what I want, so extra thanks for that extra thought. I never would have thought of using an 'if' statement to do that, though it seems like the simple and obvious solution, now! I'll try to transpose your code to my dataset and get back to you, probably early next week.

        Comment


        • #5
          Hi Andrew and thanks again for your help.

          It was very easy to adapt your solution to my dataset and it works wonderfully except for the final line of code
          Code:
          frame results: export excel using myresults, replace keepcellfmt firstrow(variables)
          After which I receive the error:
          Code:
          file myresults.xlsx could not be saved
          r(603);
          Of course, I can simply select the table produced by the code
          Code:
          frame results: l, sep(0)
          then right click, "copy table", and paste it into Excel, but I thought you'd like to know about the error.

          Also, I've found I can replace the generic variable names (e.g. [email protected]) in the table produced with the variable labels by changing the code lines:
          Code:
          frame post results ("`lev1'") (`mean1') (`se1') ("`ci1'") ("")
          frame post results ("`lev2'") (`mean2') (`se2') ("`ci2'") ("`=strofreal(`r(p)', "%5.4f")'")
          I think this is possible because the code sets this up earlier with the lines:
          Code:
          levelsof catvar, local(levels)
          foreach l of local levels{
              local lev1 : label (catvar) `l'
              levelsof catvar, local(levels)
              foreach m of local levels{
                  local lev2 : label (catvar) `m'
                  ...
          I've found out from the 'import excel' command manual, which also features the 'export excel' command, I can change the firstrow option from
          Code:
          firstrow(variables)
          to
          Code:
          firstrow(varlabels)
          This could mean the above changes to the 'frame post' code lines are not needed, but I can't check test that theory because the 'export excel' command results in the same error as above when this option is expressed either way.

          Do you have any ideas about why export excel isn't working for me and how to export catvar labels instead of variable names created by the svy: mean commands?

          This would really put the icing on the cake for me!

          Comment


          • #6
            I forgot to ask if it's possible to add a column to the table that includes the differences between the means of the two catvar levels included in each Wald test? This column would be blank on the same rows as the p value column. If not, this is an easy Excel operation to perform.

            Comment


            • #7
              Assuming that your categorical variable is labeled, the following should do it. Changes are highlighted.

              Code:
              webuse nhanes2f, clear
              svyset psuid [pweight=finalwgt], strata(stratid)
              estimates clear
              set seed 05012024
              gen catvar=runiformint(1, 4)
              lab define catvar 1 "Label level 1"  2 "Label level 2"  3 "Label level 3"  4 "Label level 4"
              label values catvar catvar
              cap frame drop results
              frame create results str100(Variable) double(Mean SE) str20(CI) double(Difference) str20(pvalue)
              levelsof catvar, local(levels)
              foreach l of local levels{
                  local lev1 : label (catvar) `l'
                  levelsof catvar, local(levels)
                  foreach m of local levels{
                      local lev2 : label (catvar) `m'
                          if `l'!=`m' & `l'<`m'{
                              svy: mean zinc if catvar==`l', over(catvar)
                              local name1= "`:lab (catvar) `l''"
                              local mean1= r(table)["b", 1]
                              local se1= r(table)["se", 1]
                              local ci1 = "["+ strofreal(r(table)["ll", 1], "%4.3f")+ "," +strofreal(r(table)["ul", 1], "%4.3f")+"]"
                              svy: mean zinc if catvar==`m', over(catvar)
                              local name2= "`:lab (catvar) `m''"
                              local mean2= r(table)["b", 1]
                              local diff= `mean1' -`mean2'
                              local se2= r(table)["se", 1]
                              local ci2 ="["+ strofreal(r(table)["ll", 1], "%4.3f")+ "," +strofreal(r(table)["ul", 1], "%4.3f")+"]"
                              qui: svy: mean zinc, over(catvar)
                              di "T tests for: `lev1' vs `lev2' "
                              test c.zinc@`l'.catvar = c.zinc@`m'.catvar
                              frame post results ("`name1'") (`mean1') (`se1') ("`ci1'") (.) ("")
                              frame post results ("`name2'") (`mean2') (`se2') ("`ci2'") (`diff') ("`=strofreal(`r(p)', "%5.4f")'")          
                          }
                      }
                  }
              
              
              frame results: l, sep(0)
              frame results: export excel using myresults, replace keepcellfmt firstrow(variables)
              Res.:

              Code:
              . frame results: l, sep(0)
              
                   +-------------------------------------------------------------------------------+
                   |      Variable        Mean          SE                CI   Difference   pvalue |
                   |-------------------------------------------------------------------------------|
                1. | Label level 1   87.173299   .51852159   [86.116,88.231]            .          |
                2. | Label level 2   87.510534   .58445883   [86.319,88.703]   -.33723424   0.5149 |
                3. | Label level 1   87.173299   .51852159   [86.116,88.231]            .          |
                4. | Label level 3    87.27916   .61518347   [86.024,88.534]   -.10586081   0.8210 |
                5. | Label level 1   87.173299   .51852159   [86.116,88.231]            .          |
                6. | Label level 4   86.743926   .63844888   [85.442,88.046]    .42937357   0.3576 |
                7. | Label level 2   87.510534   .58445883   [86.319,88.703]            .          |
                8. | Label level 3    87.27916   .61518347   [86.024,88.534]    .23137343   0.6781 |
                9. | Label level 2   87.510534   .58445883   [86.319,88.703]            .          |
               10. | Label level 4   86.743926   .63844888   [85.442,88.046]    .76660782   0.1892 |
               11. | Label level 3    87.27916   .61518347   [86.024,88.534]            .          |
               12. | Label level 4   86.743926   .63844888   [85.442,88.046]    .53523438   0.3735 |
                   +-------------------------------------------------------------------------------+

              Do you have any ideas about why export excel isn't working for me
              You need to make sure that the file is not open when trying to save, i.e., Excel should not be open. Otherwise, an already open file cannot be replaced. If this is not the issue, then make sure that you have write access to the directory where the file is to be saved. Start by typing

              Code:
              pwd
              then check if you are able to save files in this directory. If not, change it to a different directory where you have write access. See

              ​​​​​​​
              Code:
              help cd


              Comment


              • #8
                Hi Andrew. Brilliant, thank you! It works exactly as it should. I've learned enough from your solution to change the code a little to produce a table with the number formats I prefer and, hopefully, apply the same principles to create the many other tables of a similar nature I need to document my results.

                Once I changed the working directory, the export excel command worked fine - thanks again. The working directory was set to the Stata 18 folder in Program File, possibly because I had very recently installed Stata 18.

                I also moved the 'if' condition into the svy, subpop() option as recommended in the manual and included the full list command. I've copied the resulting code below to share with others:

                Code:
                webuse nhanes2f, clear
                svyset psuid [pweight=finalwgt], strata(stratid)
                estimates clear
                set seed 05012024
                gen catvar=runiformint(1, 4)
                lab define catvar 1 "Label level 1"  2 "Label level 2"  3 "Label level 3"  4 "Label level 4"
                label values catvar catvar
                svy: mean zinc, over(catvar)
                cap frame drop results
                frame create results str100(Variable) double(Mean SE) str20(CI) double(Difference) str20(pvalue)
                levelsof catvar, local(levels)
                foreach l of local levels{
                    local lev1 : label (catvar) `l'
                    levelsof catvar, local(levels)
                    foreach m of local levels{
                        local lev2 : label (catvar) `m'
                            if `l'!=`m' & `l'<`m'{
                                svy, subpop(if catvar==`l'): mean zinc, over(catvar)
                                local name1= "`:lab (catvar) `l''"
                                local mean1= strofreal(r(table)["b", 1],"%5.4f")
                                local se1= strofreal(r(table)["se", 1], "%4.3f")
                                local ci1 = "["+ strofreal(r(table)["ll", 1], "%5.4f")+ "," +strofreal(r(table)["ul", 1], "%5.4f")+"]"
                                svy, subpop(if catvar==`m'): mean zinc if catvar==`m', over(catvar)
                                local name2= "`:lab (catvar) `m''"
                                local mean2= strofreal(r(table)["b", 1],"%5.4f")
                                local diff= `mean1' -`mean2'
                                local se2= strofreal(r(table)["se", 1], "%4.3f")
                                local ci2 ="["+ strofreal(r(table)["ll", 1], "%5.4f")+ "," +strofreal(r(table)["ul", 1], "%5.4f")+"]"
                                qui: svy: mean zinc, over(catvar)
                                di "T test for: `lev1' vs `lev2' "
                                test c.zinc@`l'.catvar = c.zinc@`m'.catvar
                                frame post results ("`name1'") (`mean1') (`se1') ("`ci1'") (.) ("")
                                frame post results ("`name2'") (`mean2') (`se2') ("`ci2'") (`diff') ("`=strofreal(`r(p)', "%5.4f")'")          
                            }
                        }
                    }
                
                frame results: l, sep(0)
                frame results: export excel using myresults, replace keepcellfmt firstrow(variables)
                Thanks very much, again

                Kevin

                Comment

                Working...
                X