Announcement

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

  • Balance table with survey data (using svy)?

    How can I generate a simple balance table, something like the screenshot below (i.e., three columns: male mean (sd in parenthesis), female mean (s.d. in parenthesis), and difference (s.e. in parenthesis)) for nationally representative survey data, i.e., adjusting the standard errors for survey design stratification and clustering? And then export it to a latex table?

    The 'svy' option that defines the data to be survey data doesn't work with most commands I would normally use for this (e.g. tabstat, summ, ttest, iebaltab).

    Trying to avoid calculating the means and SDs for each var separately and then formatting them in a table using a ton of manual coding.

    Thanks!
    Attached Files

  • #2
    If you have Stata 17 or newer, you can build your table with the
    collect suite of commands and export the resulting table to LaTeX.

    Here is what I came up with using some publicly available survey data.
    Code:
    webuse nhanes2l
    
    label var age "Age"
    
    gen age2 = age*age
    label var age2 "Age-squared"
    
    svy: mean age age2 highbp, over(sex)
    
    * start with a style with only horizontal borders
    collect style use etable, replace
    * show variable labels
    collect style header colname_remainder, level(label)
    
    * collect mean and sd values
    collect : estat sd
    
    * define new dimension for identifying the table columns
    collect addtags group["(1)"], fortags(sex[1])
    collect addtags group["(2)"], fortags(sex[2])
    
    * draft of table so far
    collect layout (colname_remainder#result[mean sd]) (group)
    
    * hide the result levels from the row header
    collect style header result, level(hide)
    
    * getting there
    collect preview
    
    * collect differences and their SE values, differences will be tagged
    * with result[_r_b] and their SEs will be tagged with result[_r_se]
    collect: contrast c.(age age2 highbp)#r.sex
    
    * define new column group for these results
    collect addtags group["(3)"], fortags(cmdset[2])
    
    * define composite result that will allow us to keep the means on the
    * same row level as their difference
    collect composite define r1 = mean _r_b
    
    * define composite result that will allow us to keep the sds on
    * the same row level as the SE of the mean difference
    collect composite define r2 = sd _r_se
    
    * format numbers and surround the SD/SE values in parens
    collect style cell result[r1], nformat(%12.2fc)
    collect style cell result[r2], nformat(%12.2fc) sformat("(%s)")
    
    * update layout using new composite results
    collect layout (colname_remainder#result[r1 r2]) (group)
    
    * define new dimension with informative headers for each column group
    collect addtags ginfo["Male Mean (S.D.)"], fortags(group["(1)"])
    collect addtags ginfo["Female Mean (S.D.)"], fortags(group["(2)"])
    collect addtags ginfo["Difference (S.E.)"], fortags(group["(3)"])
    
    * update the layout
    collect layout (colname_remainder#result[r1 r2]) (group#ginfo)
    
    * add rules for significance stars
    collect stars _r_p .1 "*" .05 "**" .01 "***", attach(_r_b)
    
    * center the column headers and table items
    collect style cell cell_type[column-header item], halign(center)
    
    * verify we like what we get
    collect preview
    
    * export to LaTeX
    collect export table.tex, replace
    Here is the resulting table.
    Code:
    -------------------------------------------------------------------------
                               (1)               (2)               (3)
                        Male Mean (S.D.) Female Mean (S.D.) Difference (S.E.)
    -------------------------------------------------------------------------
    Age                       41.91             42.57
                             (15.25)           (15.72)            (0.37)
    Age-squared             1,991.55          2,056.93
                           (1,371.96)        (1,425.73)          (32.92)
    High blood pressure       0.43              0.31
                             (0.49)            (0.47)             (0.01)
    -------------------------------------------------------------------------
    Here is a screenshot of the PDF file created from the exported LaTeX file.


    Click image for larger version

Name:	Screenshot 2025-04-10 at 8.50.46 PM.png
Views:	1
Size:	60.1 KB
ID:	1775748

    Comment


    • #3
      My eyes were a little tired when I posted the above, and I did not notice that adding the significance stars caused the differences to disappear from the table. This was a side effect of the etable style; and the fix is to add option result in the call to collect stars.
      Code:
      * add rules for significance stars
      collect stars _r_p .1 "*" .05 "**" .01 "***", attach(_r_b) result
      The resulting table is then
      Code:
      -------------------------------------------------------------------------
                                 (1)               (2)               (3)
                          Male Mean (S.D.) Female Mean (S.D.) Difference (S.E.)
      -------------------------------------------------------------------------
      Age                       41.91             42.57             0.65*
                               (15.25)           (15.72)            (0.37)
      Age-squared             1,991.55          2,056.93            65.38*
                             (1,371.96)        (1,425.73)          (32.92)
      High blood pressure       0.43              0.31             -0.11***
                               (0.49)            (0.47)             (0.01)
      -------------------------------------------------------------------------
      Here is the corresponding screenshot of the PDF file created from the exported LaTeX file.

      Click image for larger version

Name:	Screenshot 2025-04-14 at 4.39.51 PM.png
Views:	1
Size:	18.5 KB
ID:	1776014

      Comment


      • #4
        How to export it as .docx file in STATA 18?
        Thank you!
        Best regards,
        Mukesh

        Comment


        • #5
          There are a couple ways to export to .docx, one is collect export, the other is putdocx collect.
          Using the above example, change the file extension
          Code:
          collect export table.docx, replace

          Comment


          • #6
            Thank you very much Jeff for the code example! Appreciate it!

            Comment


            • #7
              dtable has a svy option that will get you most of the way there:

              Code:
              webuse nhanes2l
              
              svyset [w = finalwgt], psu(psu) strata(strata)
              
              dtable, continuous(age highbp) by(sex, tests nototals) svy nosample
              which produces

              Code:
              ----------------------------------------------------------
                                                    Sex                 
                                        Male           Female      Test
              ----------------------------------------------------------
              Age (years)         41.913 (15.327) 42.565 (15.658)  0.091
              High blood pressure   0.428 (0.495)   0.314 (0.464) <0.001
              ----------------------------------------------------------

              Comment

              Working...
              X