Announcement

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

  • estout Manipulation: Add Scalars, but as Columns to Wide Tables

    Hi all,

    This post concerns estout (SSC, by Ben Jann) in Stata 16. I wonder how one can add series of scalars as columns to a wide table. Multiple posts have shown 1) how to estadd scalars (e.g. here); and 2) how to display these scalars to the bottom of a long table (e.g. here). I am struggling to synthesize the methods to make wide tables.

    Example (with sysuse auto). The ideal output looks like this, from which I have difficulty adding the rightmost column of p valus from chi2 independent test (stored as scalars from tab x y, chi2) in red.

    The difficulties are combining these aspects:
    1) properly store the chi2 p results as there are P values from both the ttest and the chi2 test
    2) retain the stars for these scalars (Andrew did show a "manual" way here, would this be the way?)
    3) printing them as columns


    I was able to use the following script to produce the first six columns (i.e. excl. the rightmost):

    Code:
    version 16
    clear all
    set linesize 120
    set more off
    
    * Input data set
    sysuse auto
    
    
    eststo clear
    
    eststo dom: qui estpost sum price mpg if foreign == 0
                                
    eststo for: qui estpost sum price mpg if foreign == 1
                                
    eststo dom_for: qui estpost ttest price mpg, by(foreign) unequal
    
    eststo price_c2: qui estpost tab price foreign, chi2
    eststo mpg_c2: qui estpost tab mpg foreign, chi2
    
    esttab dom for dom_for, replace star(* 0.10 ** 0.05 *** 0.01) nonumber noobs label ///
    alignment(rrrr) ///
    cells("count(pattern(1 1 0 0) fmt(0)) mean(pattern(1 1 0 0) fmt(2)) b(star pattern(0 0 1 0) fmt(2))") ///
    mtitle("Domestic" "Foreign" "ttest") ///
    collabels("N" "Mean" "Mean Diff.")
    
    eststo clear
    Output:
    Code:
    ----------------------------------------------------------------------------------------
                             Domestic                   Foreign                     ttest  
                                    N         Mean            N         Mean   Mean Diff.  
    ----------------------------------------------------------------------------------------
    Price                          52      6072.42           22      6384.68      -312.26  
    Mileage (mpg)                  52        19.83           22        24.77        -4.95***
    ----------------------------------------------------------------------------------------

    Appreciate any pointers or advice!
    Last edited by Jas Koizumi; 12 Apr 2022, 10:31.

  • #2
    Thanks for the reproducible example. Here is a way, collating the statistics in a matrix and adding them to the estimates using estadd.

    EDITED: Sorry, I assigned the p-values from the Chi2 test to star the Mean Diff coefficients. If the defaults in your tables (excluding the option -pval(pval)- in my code) are not correct, save the p-values from the t-tests in another matrix, say pval2 as I do below for pval, and include the option -pval(pval2)-. Let me know if you face any issues.

    Code:
    sysuse auto
    
    eststo clear
    
    eststo dom: qui estpost sum price mpg if foreign == 0
                                
    eststo for: qui estpost sum price mpg if foreign == 1
                                
    eststo dom_for: qui estpost ttest price mpg, by(foreign) unequal
    
    qui estpost tab price foreign, chi2
    local pval1= e(p)
    qui estpost tab mpg foreign, chi2
    local pval2= e(p)
    
    estimates restore dom_for
    mat define pval=(`pval1', `pval2')
    mat colnames pval= "price mpg"
    estadd matrix pval= pval
    estimates store dom_for
    
    esttab dom for dom_for, replace star(* 0.10 ** 0.05 *** 0.01) nonumber noobs label ///
    alignment(rrrr) ///
    cells("count(pattern(1 1 0 0 0) fmt(0)) mean(pattern(1 1 0 0 0) fmt(2)) b(star  pval(pval) pattern(0 0 1 0) fmt(2)) pval(pattern(0 0 1 0) fmt(3))") ///
    mtitle("Domestic" "Foreign" "ttest") ///
    collabels("N" "Mean" "Mean Diff." "p-value")
    
    eststo clear
    Res.:

    Code:
    . esttab dom for dom_for, replace star(* 0.10 ** 0.05 *** 0.01) nonumber noobs label ///
    > alignment(rrrr) ///
    > cells("count(pattern(1 1 0 0 0) fmt(0)) mean(pattern(1 1 0 0 0) fmt(2)) b(star pval(pval) pattern(0 0 1 0) fmt(2)) pval(pattern(0 0 1
    > 0) fmt(3))") ///
    > mtitle("Domestic" "Foreign" "ttest") ///
    > collabels("N" "Mean" "Mean Diff." "p-value")
    
    -----------------------------------------------------------------------------------------------------
                             Domestic                   Foreign                     ttest                
                                    N         Mean            N         Mean   Mean Diff.         p-value
    -----------------------------------------------------------------------------------------------------
    Price                          52      6072.42           22      6384.68      -312.26           0.445
    Mileage (mpg)                  52        19.83           22        24.77        -4.95**         0.016
    -----------------------------------------------------------------------------------------------------
    Last edited by Andrew Musau; 12 Apr 2022, 13:32.

    Comment


    • #3
      Andrew - Thank you so much for the prompt reply. I'd like to organize responses and follow-up questions in two folds.

      Response 1. I want to confirm my understanding your code. My take on what it does: you stored the Chi2 p-vals as 1x2 matrix, then attach it to the list of returns generated by the ttest. This matrix then becomes part of the stored estimates from the ttest "model" (and this is the 3rd model stored, following the sum stats from domestic and from foreign).

      Q1: Is this the right understanding? If so, could you advise an alternative way to store and output the chi2 results as a separate model? Keeping it separate seems cleaner to me, and allows things like giving a separate mtitle (instead of sharing the ttest mtitle).


      Response 2. Some additional follow-ups on your code.

      Q2: For future reference: when you advise "saving pvals to another matrix", do you mean something like:
      Code:
      estimates restore dom_for
      
      matrix define pval2 = e(p)
      estadd matrix pval2 = pval2
      
      estimates store dom_for
      For the record, I was able to adapt your code to produce this result without having to save the pvalues from ttest to a seaprate matrix. All I do is to not specify pval(pval) in the b(...) to avoid assigning star significance incorrectly:
      Code:
      . esttab dom for dom_for, replace star(* 0.10 ** 0.05 *** 0.01) nonumber noobs label ///
      > alignment(rrrr) ///
      > cells("count(pattern(1 1 0) fmt(0)) mean(pattern(1 1 0) fmt(2)) b(star  pattern(0 0 1) fmt(2)) pval(pattern(0 0 1) fmt
      > (3))") ///
      > mtitle("Domestic" "Foreign" "ttest" "Chi2") ///
      > collabels("N" "Mean" "Mean Diff." "p-value")
      *^ Besides leaving out pval(pval), the other minor change is the pattern, since there are only three "models" in this output.
      -----------------------------------------------------------------------------------------------------
                               Domestic                   Foreign                     ttest                
                                      N         Mean            N         Mean   Mean Diff.         p-value
      -----------------------------------------------------------------------------------------------------
      Price                          52      6072.42           22      6384.68      -312.26           0.445
      Mileage (mpg)                  52        19.83           22        24.77        -4.95***        0.016
      -----------------------------------------------------------------------------------------------------

      Comment


      • #4
        Originally posted by Jas Koizumi View Post
        Andrew - Thank you so much for the prompt reply. I'd like to organize responses and follow-up questions in two folds.

        Response 1. I want to confirm my understanding your code. My take on what it does: you stored the Chi2 p-vals as 1x2 matrix, then attach it to the list of returns generated by the ttest. This matrix then becomes part of the stored estimates from the ttest "model" (and this is the 3rd model stored, following the sum stats from domestic and from foreign).

        Q1: Is this the right understanding? If so, could you advise an alternative way to store and output the chi2 results as a separate model? Keeping it separate seems cleaner to me, and allows things like giving a separate mtitle (instead of sharing the ttest mtitle).

        Correct. You can easily recycle one of the estimates to achieve what you want (illustrated below).


        Response 2. Some additional follow-ups on your code.

        Q2: For future reference: when you advise "saving pvals to another matrix", do you mean something like:
        Code:
        estimates restore dom_for matrix define pval2 = e(p) estadd matrix pval2 = pval2 estimates store dom_for

        If a p-values matrix already exists, no need to create a new one. I misread what was intended, hence my edit in #2. Only if it does not exist, you create one manually as I did for the Chi2 test in #2. So you want:


        Code:
        sysuse auto
        
        eststo clear
        
        eststo dom: qui estpost sum price mpg if foreign == 0
                                    
        eststo for: qui estpost sum price mpg if foreign == 1
                                    
        eststo dom_for: qui estpost ttest price mpg, by(foreign) unequal
        
        qui estpost tab price foreign, chi2
        local pval1= e(p)
        qui estpost tab mpg foreign, chi2
        local pval2= e(p)
        
        *RECYCLE ONE OF THE STORED ESTIMATES
        estimates restore dom_for
        mat define pval=(`pval1', `pval2')
        mat colnames pval= "price mpg"
        estadd matrix pval= pval
        estimates store dom_for2
        
        esttab dom for dom_for dom_for2, replace star(* 0.10 ** 0.05 *** 0.01) nonumber noobs label ///
        alignment(rrrr) ///
        cells("count(pattern(1 1 0 0 ) fmt(0)) mean(pattern(1 1 0 0) fmt(2)) b(star pattern(0 0 1 0) fmt(2)) pval(pattern(0 0 0 1) fmt(3))") ///
        mtitle("Domestic" "Foreign" "ttest" "p-value") ///
        collabels("N" "Mean" "Mean Diff." "p-value")
        
        eststo clear

        Res.:

        Code:
        . esttab dom for dom_for dom_for2, replace star(* 0.10 ** 0.05 *** 0.01) nonumber noobs label ///
        > alignment(rrrr) ///
        > cells("count(pattern(1 1 0 0 ) fmt(0)) mean(pattern(1 1 0 0) fmt(2)) b(star pattern(0 0 1 0) fmt(2)) pval(pattern(0 0 0 1) fmt(3))") /
        > //
        > mtitle("Domestic" "Foreign" "ttest" "p-value") ///
        > collabels("N" "Mean" "Mean Diff." "p-value")
        
        -----------------------------------------------------------------------------------------------------
                                 Domestic                   Foreign                     ttest         p-value
                                        N         Mean            N         Mean   Mean Diff.         p-value
        -----------------------------------------------------------------------------------------------------
        Price                          52      6072.42           22      6384.68      -312.26           0.445
        Mileage (mpg)                  52        19.83           22        24.77        -4.95***        0.016
        -----------------------------------------------------------------------------------------------------
        Last edited by Andrew Musau; 14 Apr 2022, 16:33.

        Comment


        • #5
          Andrew, clever "rigging" as always! Then, to synthesize the point in #2 about using different pvals for starring: if I want to star the chi2 pvalues according to these pvalues per se, not the pvalues from whichever estimate I recycle, do I just specify as below:

          Code:
          esttab dom for dom_for dom_for_chi2, replace star(* 0.10 ** 0.05 *** 0.01) nonumber noobs label ///
          alignment(rrrr) ///
          cells("count(pattern(1 1 0 0) fmt(0)) mean(pattern(1 1 0 0) fmt(2)) b(star pattern(0 0 1 0) fmt(2)) pval(star pval(pval) pattern(0 0 0 1) fmt(3)) ") ///
          mtitle("Domestic" "Foreign" "ttest" "Chi2") ///
          collabels("N" "Mean" "Mean Diff." "p-value")
          This is the output I get:
          Code:
          --------------------------------------------------------------------------------------------------------
                                   Domestic                   Foreign                     ttest            Chi2   
                                          N         Mean            N         Mean   Mean Diff.         p-value   
          --------------------------------------------------------------------------------------------------------
          Price                          52      6072.42           22      6384.68      -312.26           0.445   
          Mileage (mpg)                  52        19.83           22        24.77        -4.95***        0.016** 
          --------------------------------------------------------------------------------------------------------

          Comment


          • #6
            Correct. Note the defaults are * p<0.05, ** p<0.01, *** p<0.001. If you want the defaults in some other field, e.g., Economics, add the option:

            Code:
            starlevels(* 0.10 ** 0.05 *** 0.01)

            Comment

            Working...
            X