Announcement

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

  • estout: flip models and coefficients when using factor variables

    Dear Stata Experts,

    I am trying to apply the code that Ben Jann provided for flipping the models and coefficients in a table of regression results made with his estout package.
    The code is listed as "Approach 2" at http://repec.org/bocode/e/estout/advanced.html.

    The code works very nicely in many situations, but it gets caught if I include factor variables in my regression command. I have provided an example below, which produces the error: 2bn.race invalid name r(198).
    I know I could just create the dummy variables for race with tab, gen(), but it would be really nice if factor variables worked.

    Does anyone know how to modify Ben's code to allow for factor variables?

    Thanks,

    Jeremy

    Code:
    *open some data
    sysuse nlsw88, clear
    
    *estimate some regressions
    eststo clear
    eststo wage: regress wage i.race
    eststo hours: regress hours i.race
    eststo ttl_exp: regress ttl_exp i.race
    eststo tenure: regress tenure i.race
    
    *make a table with estout
    esttab, b(2) not n r2 label nobase rename(_cons White) noomitted
    
    *use Ben's code to flip the table
    matrix C = r(coefs)
    matrix S = r(stats)
    eststo clear
    local rnames : rownames C
    local models : coleq C
    local models : list uniq models
    local i 0
    
    foreach name of local rnames {
        local ++i
        local j 0
        capture matrix drop b
        capture matrix drop se
        foreach model of local models {
            local ++j
            matrix tmp = C[`i', 2*`j'-1]
            if tmp[1,1]<. {
                matrix colnames tmp = `model'
                matrix b = nullmat(b), tmp
                matrix tmp[1,1] = C[`i', 2*`j']
                matrix se = nullmat(se), tmp
            }
        }
    ereturn post b
    quietly estadd matrix se
    eststo `name'
    }
    
    local snames : rownames S
    local i 0
    foreach name of local snames {
         local ++i
         local j 0
         capture matrix drop b
         foreach model of local models {
             local ++j
            matrix tmp = S[`i', `j']
            matrix colnames tmp = `model'
            matrix b = nullmat(b), tmp
         }
    ereturn post b
    eststo `name'
    }

  • #2
    try this in esttab.

    Code:
    rename(_cons White 2.race Black 3.race Other)

    Comment


    • #3
      #2 may help: https://www.statalist.org/forums/for...erent-commands

      Comment


      • #4
        Thank you for the suggestions! Both solutions worked nicely.

        It would be even better to combine some benefits from the two approaches. Specifically, I wonder if it is possible to modify Andrew's code to automatically rename the factor variables with their variable or value labels.

        In my example, Andrew's code results in the row names _2bn_race and _3_race.

        The estout documentation indicates that the label option displays "variable labels" instead of variable names. This suggests that maybe it would be possible to replace the line below from Andrew's code:

        local rnames `rnames' `=strtoname("`name'")'

        with something like:

        local rnames `rnames': variable label `"`name'"'


        The line of code I suggest above does not work, but since Stata and estout are both capable of replacing factor variable names with labels, I suspect there is some way to do this . . .

        Thanks,

        Jeremy

        Comment


        • #5
          Report it to Stata support. Maybe they'll recode it to work with i. vars in future updates. Or, allow you to choose which format you'd like (maybe a "swap" option).

          Comment


          • #6
            The problem with value labels is that they can contain spaces and invalid name characters, just like factor variables. My modification in the linked thread changes the matrix row names. Your suggestions goes the opposite way and can be easily implemented by creating indicators from the factor variables and labeling them. One could also explore changing the row equation names and using these instead (as they accept invalid name characters), or creating a list and using the -substitute()- option of estout.

            Comment


            • #7
              If you can guarantee that the value labels are valid Stata names, then the following will work. For what constitutes a valid Stata name, see

              Code:
              help naming_conventions
              Code:
              webuse yield, clear
              eststo yield: pwmean yield, over(fertilizer) cimeans
              lab def fertlbl 1 "low" 2 "midlow" 3 "medium" 4 "midhigh" 5 "high", modify
              esttab yield
              matrix C = r(coefs)
              local rnames2 : rownames C
              local rnames
              foreach name of local rnames2{
                  if "`name'"=="`=strtoname("`name'")'"{
                      local rnames `rnames' `=strtoname("`name'")'
                  }
                  if "`name'"!="`=strtoname("`name'")'"{ 
                      local rnames `rnames' "`:lab (`=ustrregexra("`name'", "(.*)\.(.*)", "$2")') `=ustrregexra("`name'", "(.*)\.(.*)", "$1")''"
                  }
              }
              cap mat rownames C= "`rnames'"
              local models : coleq C
              local models : list uniq models
              eststo clear
              local i 0
              foreach name of local rnames {
                  local ++i
                  local j 0
                  capture matrix drop b
                  capture matrix drop se
                  foreach model of local models {
                      local ++j
                      matrix tmp = C[`i', 2*`j'-1]
                      if tmp[1,1]<. {
                          matrix colnames tmp = `model'
                          matrix b = nullmat(b), tmp
                          matrix tmp[1,1] = C[`i', 2*`j']
                          matrix se = nullmat(se), tmp
                     }
                  }
                  ereturn post b
                  quietly estadd matrix se
                  eststo `name'
              }
              esttab, se mtitle noobs compress nonumb
              Res.:

              Code:
              . esttab, se mtitle noobs compress nonumb
              
              --------------------------------------------------------------
                            midlow       medium      midhigh         high   
              --------------------------------------------------------------
              yield          41.36        44.99        41.85        46.29   
                           (36.79)      (40.01)      (37.23)      (41.17)   
              --------------------------------------------------------------
              Standard errors in parentheses
              * p<0.05, ** p<0.01, *** p<0.001

              Comment


              • #8
                Thank you Andrew!

                Following your suggestions and examples, I wrote the code below, that replaces the default factor variable names with the appropriate value labels. The code works with the example below, but it would need some refinement to work in more complicated situations.

                Jeremy

                Code:
                *example for help file 
                sysuse nlsw88, clear
                
                *estimate some regressions 
                eststo clear 
                eststo wage: regress wage i.race 
                eststo hours: regress hours i.race
                eststo ttl_exp: regress ttl_exp i.race
                eststo tenure: regress tenure i.race 
                esttab, b(2) not n r2 label nobase rename(_cons White) order(White) noomitted
                
                
                matrix C = r(coefs)
                matrix S = r(stats)
                
                local rnames2 : rownames C
                local rnames
                foreach name of local rnames2{
                    if "`name'"=="`=strtoname("`name'")'"{
                        local rnames `rnames' `=strtoname("`name'")'
                    }
                    if "`name'"!="`=strtoname("`name'")'"{ 
                        local dot = strpos("`name'", ".")
                        local varname = substr("`name'", `dot'+1, .)
                        local num = substr("`name'", 1, 1)
                        local valuelab: label (`varname') `num'
                        local rnames `rnames' `=strtoname("`valuelab'")'
                    }
                }
                cap mat rownames C= "`rnames'"
                
                local models : coleq C
                local models : list uniq models
                
                eststo clear
                local i 0
                
                foreach name of local rnames {
                    local ++i
                    local j 0
                    capture matrix drop b
                    capture matrix drop se
                    foreach model of local models {
                        local ++j
                        matrix tmp = C[`i', 2*`j'-1]
                        if tmp[1,1]<. {
                            matrix colnames tmp = `model'
                            matrix b = nullmat(b), tmp
                            matrix tmp[1,1] = C[`i', 2*`j']
                            matrix se = nullmat(se), tmp
                        }
                    }
                ereturn post b
                quietly estadd matrix se
                eststo `name'
                }
                
                local snames : rownames S
                local i 0
                foreach name of local snames {
                     local ++i
                     local j 0
                     capture matrix drop b
                     foreach model of local models {
                         local ++j
                        matrix tmp = S[`i', `j']
                        matrix colnames tmp = `model'
                        matrix b = nullmat(b), tmp
                     }
                ereturn post b
                eststo `name'
                }
                
                
                *make table with the flipped results 
                esttab, b(2) not mtitle noobs compress nonumb

                Comment


                • #9
                  or #2, which is not even a line of code.

                  Comment


                  • #10
                    I surmise that the issue here pertains to automation. If the task is not performed regularly, I concur that manual renaming is the optimal approach.

                    Comment


                    • #11
                      I just noticed that something is not quite right with the code I posted above. There is a mistake in the p-values in the flipped table. In the model where tenure is the dependent variable, the coefficient for "other" is correct (-.086), but it is marked with one star(p<0.05) and it should not be marked at all. In the regression, the p-value was 0.430. I haven't had time yet to figure out what is wrong.

                      As George suggested above, the solution in #2 is far easier (and the only correct solution at the moment).

                      Comment


                      • #12
                        After further examination, I determined that that the code in #8 that flips the models and coefficients (even if there are factor variables in the regressions) works properly, but only if the initial esttab call specifies that the s.e. be included and significance stars be omitted. I have pasted a corrected version below with the change in red.

                        Jeremy

                        P.S. In case anyone is wondering why I wanted to do this:
                        It makes it easy to create a table that show how the means for a list of variables differ across two or more groups while also providing statistical tests of whether each group differs from a reference group. It is like a table of t-tests but in a scenario where there are more than two groups to compare.



                        Code:
                        sysuse nlsw88, clear
                        
                        *estimate some regressions 
                        eststo clear 
                        eststo wage: regress wage i.race 
                        eststo hours: regress hours i.race
                        eststo ttl_exp: regress ttl_exp i.race
                        eststo tenure: regress tenure i.race 
                        esttab, b(2) se nostar n r2 label nobase rename(_cons White) order(White) noomitted
                        
                        
                        matrix C = r(coefs)
                        matrix S = r(stats)
                        
                        local rnames2 : rownames C
                        local rnames
                        foreach name of local rnames2{
                            if "`name'"=="`=strtoname("`name'")'"{
                                local rnames `rnames' `=strtoname("`name'")'
                            }
                            if "`name'"!="`=strtoname("`name'")'"{ 
                                local dot = strpos("`name'", ".")
                                local varname = substr("`name'", `dot'+1, .)
                                local num = substr("`name'", 1, 1)
                                local valuelab: label (`varname') `num'
                                local rnames `rnames' `=strtoname("`valuelab'")'
                            }
                        }
                        cap mat rownames C= "`rnames'"
                        
                        local models : coleq C
                        local models : list uniq models
                        
                        eststo clear
                        local i 0
                        
                        foreach name of local rnames {
                            local ++i
                            local j 0
                            capture matrix drop b
                            capture matrix drop se
                            foreach model of local models {
                                local ++j
                                matrix tmp = C[`i', 2*`j'-1]
                                if tmp[1,1]<. {
                                    matrix colnames tmp = `model'
                                    matrix b = nullmat(b), tmp
                                    matrix tmp[1,1] = C[`i', 2*`j']
                                    matrix se = nullmat(se), tmp
                                }
                            }
                        ereturn post b
                        quietly estadd matrix se
                        eststo `name'
                        }
                        
                        local snames : rownames S
                        local i 0
                        foreach name of local snames {
                             local ++i
                             local j 0
                             capture matrix drop b
                             foreach model of local models {
                                 local ++j
                                matrix tmp = S[`i', `j']
                                matrix colnames tmp = `model'
                                matrix b = nullmat(b), tmp
                             }
                        ereturn post b
                        eststo `name'
                        }
                        
                        
                        *make table with the flipped results 
                        esttab, b(2) not mtitle noobs compress nonumb

                        Comment

                        Working...
                        X