Announcement

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

  • Multiplying coefficients by a constant

    It is sometimes helpful to multiply regression coefficients by a constant (such as 37). What would be the simplest way to do this? For example, after
    Code:
    sysuse auto
    regress mpg weight foreign
    I'd like to multiply the coefficients of 'e(b)' by 37 and the variance-covariance matrix in `V(b)' by 37^2. And then display the results in a regression table and/or export them using outreg2.

    I'm guessing one solution would use ereturn post, but I'm new to that game. And maybe there's another way.

    Best,
    Paul

  • #2
    How about

    Code:
    generate weight37 = weight/37
    generate foreign37 = foreign/37
    regress mpg weight37 foreign37
    I'm not so sure that standardizing categorical variables, such as foreign, is a great idea, though.

    Comment


    • #3
      Indeed, dividing every X by 37 would do it -- or, even simpler, multiplying Y by 37.*

      But transforming variables makes some folks uneasy, as you've noticed. So I'm wondering if there's an easy way to work with the coefficients and standard errors (or variance-covariance matrix).

      -------------------------------------
      *Dividing X by 37 produces the same slopes, but not the same intercept, as multiplying Y by 37

      Comment


      • #4
        Why not just:
        Code:
        sysuse auto
        regress mpg weight foreign
        lincom 37*weight 
        lincom 37*foreign

        Comment


        • #5
          Or here is an example using ereturn:
          Code:
          sysuse auto
          regress mpg weight foreign
          matrix b37=37*e(b)
          matrix V37=37^2*e(V)
          ereturn post b37 V37, dof(`=e(df_r)')
          ereturn display

          Comment


          • #6
            Originally posted by paulvonhippel View Post
            Indeed, dividing every X by 37 would do it -- or, even simpler, multiplying Y by 37.*
            Hm, pretty obvious but that never occurred to me. Thanks for the hint.

            As for

            Originally posted by paulvonhippel View Post
            But transforming variables makes some folks uneasy, as you've noticed.
            Well, do you need to tell them? If results are the same, tell them you multiplied the coefficient vector if that makes them more comfortable. Or, even better from an educational point of view, tell them you did the equivalent of multiplying the coefficient vector. I mean, it's not like Stata literally implements \((X^{\prime}X)^{-1}(X^{\prime}y)\) to obtain the \(b\) vector; yet that is what is documented.

            Personally, I would feel much more uneasy if you told me you mangled with Stata's returned results.
            Last edited by daniel klein; 07 May 2024, 03:45.

            Comment


            • #7
              I've wrapped Phil Clayton 's clever approach in the program below. The only problem is that it erases every e() macro except for the ones named in the ereturn list command.
              Any solution for that most appreciated! I suspect this would be easy for folks who understand e() macros better than I do.

              Code:
              cap program drop multiply_coefficients_by
              program define multiply_coefficients_by
                  args `multiplier'
                  matrix b`multiplier'=37*e(b)
                  matrix V`multiplier'=37^2*e(V)
                   ereturn post b`multiplier'  V`multiplier', dof(`=e(df_r)')
                  ereturn display
              end
              
              cls
              sysuse auto
              regress mpg weight foreign
              ereturn list
              // Look at all those e() macros!
              
              multiply_coefficients_by 37
              ereturn list
              // Every e() macro has disappeared except for e(b) and e(V)

              Comment


              • #8
                Originally posted by paulvonhippel View Post
                I've wrapped Phil Clayton 's clever approach in the program below. The only problem is that it erases every e() macro except for the ones named in the ereturn list command.
                Any solution for that most appreciated! I suspect this would be easy for folks who understand e() macros better than I do.
                Here is an improved version of your command:

                Code:
                program define multiply_coefficients_by , eclass // <- added
                    
                    args multiplier // <- changed
                    
                    confirm number `multiplier' // <- new
                    
                    tempname bprime Vprime // <- new
                    
                    matrix `bprime'=`multiplier'*e(b)   // <- changed
                    matrix `Vprime'=`multiplier'^2*e(V) // <- changed
                    
                    ereturn repost b = `bprime'  V = `Vprime' // <- changed
                    
                    ereturn display
                    
                end
                Regarding your original question, I changed ereturn post to ereturn repost and adjusted the syntax. I also ...
                • added eclass to the program definition (not sure why Stata let's me ereturn post something even if I do not)
                • corrected the syntax for args which expects local macro names, not their (undefined) contents
                • added minimal argument verification; you must specify a number as the multiplier
                • used temporary objects to avoid overwriting existing matrices that happen to be named e37 or V37
                I have not adjusted the other e()-results -- which is what you wanted. I think that's probably a bad idea because Stata will now allow any permitted post-estimation after regress and there is a good chance that some of them might be invalid with mangled matrices in place. This is why I said, I am usually pretty nervous when people tell me that they mangled with Stata's returned results. I'd rather have them multiply variables, which I still think is much easier to understand.
                Last edited by daniel klein; 08 May 2024, 13:04.

                Comment


                • #9
                  I'm attaching an ado and help file for a new command called multiply_coefficients_by. The guts are the code in daniel klein 's most recent post in this thread. The helpfile includes an example that uses the command after regress, and a student and I have also used it after xtreg with good results. In principle it should work after any command that stores regression estimates in e(b) and e(V).

                  Daniel, you expressed concern about this invalidating other post-estimation commands. I'm less nervous since it seems to me all the values in ereturn list remain valid after the rescaling. Can you find a statistic in ereturn list that's wrong and would invalidate later post-estimation commands?

                  Best,
                  Paul
                  Attached Files

                  Comment


                  • #10
                    Originally posted by paulvonhippel View Post
                    Daniel, you expressed concern about this invalidating other post-estimation commands. I'm less nervous since it seems to me all the values in ereturn list remain valid after the rescaling. Can you find a statistic in ereturn list that's wrong and would invalidate later post-estimation commands?
                    Perhaps I am a bit too pessimistic, especially after linear models. However, the help for post-estimation commands allowed after regress lists dfbeta and estat hettest as the first two post-estimation commands. The rescaled coefficients will affect both post-estimation commands, and I am not sure whether their results are still valid in any sense. Generally speaking, it should be obvious that any post-estimation commands based on predicted values, such as margins, will also be affected by rescaling the coefficients. The fix is simple in most cases: back-transform the results of the post-estimation command, i.e., divide by the multiplier. Yet, I believe there is potential for misinterpreting results. As for non-linear models, I have not given that much thought. Average marginal effects (AME) after, say logit, should be pretty off after rescaling. I guess things could get quite complex for commands such as gsem.

                    Comment


                    • #11
                      Yes, I see your point. After regress, the existing command rescales e(b) and e(V), but the following should be rescaled as well: e(rmse), e(mss), e(rss)
                      And the list of parameters that would need to be rescaled after xtreg is different.

                      Maybe it is easier just to multiply the dependent variable.

                      Comment


                      • #12
                        Here's a program that automates the approach we've been talking about. It multiplies the dependent variable by a constant, reruns the regression, and then returns the dependent variable to its original state.
                        It's slower because it reruns the analysis instead of just transforming the results, and it's limited to linear models. But it affects all the e() macros correctly.

                        Code:
                        capture program drop multiply_coefficients_by
                        program define multiply_coefficients_by
                            args multiplier
                            replace `e(depvar)' = `e(depvar)' * `multiplier'
                            `e(cmdline)'
                            replace `e(depvar)' = `e(depvar)' / `multiplier'
                        end
                        
                        sysuse auto, clear
                        regress mpg weight foreign
                        
                        multiply_coefficients_by 37

                        Comment


                        • #13
                          Perhaps I misunderstood what you want to achieve, but why do you not simply restore the results of the first analysis?
                          Code:
                          capture program drop multiply_coefficients_by
                          program define multiply_coefficients_by
                              tempname est
                              args multiplier
                              est sto `est'
                              replace `e(depvar)' = `e(depvar)' * `multiplier'
                              `e(cmdline)'
                              qui est res `est'
                          end

                          Comment


                          • #14
                            Dirk is asking the right question. The best implementation will depend on the goal. If this is just a reporting issue then esttab (SSC) already does what you want; here is the example from your help:

                            Code:
                            . regress mpg gear_ratio
                            
                                  Source |       SS           df       MS      Number of obs   =        74
                            -------------+----------------------------------   F(1, 72)        =     44.07
                                   Model |  927.719285         1  927.719285   Prob > F        =    0.0000
                                Residual |  1515.74017        72  21.0519469   R-squared       =    0.3797
                            -------------+----------------------------------   Adj R-squared   =    0.3711
                                   Total |  2443.45946        73  33.4720474   Root MSE        =    4.5882
                            
                            ------------------------------------------------------------------------------
                                     mpg | Coefficient  Std. err.      t    P>|t|     [95% conf. interval]
                            -------------+----------------------------------------------------------------
                              gear_ratio |   7.812835   1.176919     6.64   0.000     5.466691    10.15898
                                   _cons |  -2.257346   3.588115    -0.63   0.531    -9.410123    4.895432
                            ------------------------------------------------------------------------------
                            
                            . esttab , se transform(@*.425 .425)
                            
                            ----------------------------
                                                  (1)  
                                                  mpg  
                            ----------------------------
                            gear_ratio          3.320***
                                              (0.500)  
                            
                            _cons              -0.959  
                                              (1.525)  
                            ----------------------------
                            N                      74  
                            ----------------------------
                            Standard errors in parentheses
                            * p<0.05, ** p<0.01, *** p<0.001

                            Alternatively, it may be best to leave e() (almost) alone. Here is one approach:

                            Code:
                            program define multiply_coefficients_by , eclass
                                
                                version 18
                                
                                args multiplier
                                
                                confirm number `multiplier'
                                
                                tempname bprime Vprime
                                
                                matrix `bprime'=`multiplier'*e(b)
                                matrix `Vprime'=`multiplier'^2*e(V)
                                
                                _coef_table ,                 ///
                                    coeftitle("Rescaled")     ///
                                    coeftitle2("Coefficient") ///
                                    bmatrix(`bprime')         ///
                                    vmatrix(`Vprime')
                                
                                ereturn matrix b_rescaled = `bprime'
                                ereturn matrix V_rescaled = `Vprime'
                                
                            end
                            which yields

                            Code:
                            (output omitted)
                            . multiply_coefficients_by .425
                            ------------------------------------------------------------------------------
                                         |   Rescaled
                                     mpg | Coefficient  Std. err.      t    P>|t|     [95% conf. interval]
                            -------------+----------------------------------------------------------------
                              gear_ratio |   3.320455   .5001905     6.64   0.000     2.323343    4.317567
                                   _cons |  -.9593719   1.524949    -0.63   0.531    -3.999302    2.080559
                            ------------------------------------------------------------------------------

                            Note that the rescaled coefficients and covariance matrix are added to e() as e(b_rescaled) and e(V_rescaled). You could pass those to estab or similar commands.


                            Or, just restore e() exactly as it was:

                            Code:
                            program define multiply_coefficients_by , eclass
                                
                                version 18
                                
                                args multiplier
                                
                                confirm number `multiplier'
                                
                                tempname e_results bprime Vprime
                                
                                _estimates hold `e_results' , copy restore
                                
                                matrix `bprime'=`multiplier'*e(b)
                                matrix `Vprime'=`multiplier'^2*e(V)
                                
                                ereturn repost b = `bprime' V = `Vprime'
                                
                                ereturn display
                                display as txt "Note: coefficients and standard errors rescaled by " ///
                                    as res %-9.0g `multiplier'
                                
                            end
                            which yields

                            Code:
                            (output omitted)
                            . multiply_coefficients_by .425
                            ------------------------------------------------------------------------------
                                     mpg | Coefficient  Std. err.      t    P>|t|     [95% conf. interval]
                            -------------+----------------------------------------------------------------
                              gear_ratio |   3.320455   .5001905     6.64   0.000     2.323343    4.317567
                                   _cons |  -.9593719   1.524949    -0.63   0.531    -3.999302    2.080559
                            ------------------------------------------------------------------------------
                            Note: coefficients and standard errors rescaled by .425
                            Last edited by daniel klein; 10 May 2024, 02:25.

                            Comment


                            • #15
                              Below is what I consider my final contribution software-wise to this interesting discussion. This version of the command rescales the coefficients and standard errors, displays the (rescaled) results, including a note about rescaling, restores the original estimation results, and adds e(multiplier), e(b_rescaled), and e(V_rescaled). It also adds r(multiplier) and r(table_rescaled) but leaves the original r() results otherwise.


                              Code:
                              program define multiply_coefficients_by , eclass
                                  
                                  version 18
                                  
                                  args multiplier void
                                  
                                  if (`"`void'"' != "") ///
                                      error 198
                                  
                                  confirm number `multiplier'
                                  
                                  tempname b V b_rescaled V_rescaled r_results r_table_rescaled
                                  
                                  matrix `b' = e(b)
                                  matrix `V' = e(V)
                                  
                                  matrix `b_rescaled' = `b'*`multiplier'
                                  matrix `V_rescaled' = `V'*`multiplier'
                                  
                                  nobreak {
                                      
                                      _return hold `r_results'
                                      
                                      ereturn scalar multiplier = `multiplier'
                                      ereturn matrix b_rescaled = `b_rescaled' , copy
                                      ereturn matrix V_rescaled = `V_rescaled' , copy
                                      
                                      ereturn repost b = `b_rescaled' V = `V_rescaled'
                                      
                                      ereturn display
                                      display as txt "Note: coefficients and standard errors rescaled by " ///
                                          as res  %-9.0g `multiplier'
                                      
                                      ereturn repost b = `b' V = `V'
                                      
                                      matrix `r_table_rescaled' = r(table)
                                      
                                      _return restore `r_results'
                                      
                                      mata {
                                          
                                          st_numscalar("r(multiplier)",`multiplier')
                                          st_matrix("r(table_rescaled)", st_matrix("`r_table_rescaled'"))
                                          st_matrixcolstripe("r(table_rescaled)", st_matrixcolstripe("r(table)"))
                                          st_matrixrowstripe("r(table_rescaled)", st_matrixrowstripe("r(table)"))
                                          
                                      }
                                      
                                  }
                                  
                              end
                              Last edited by daniel klein; 10 May 2024, 04:11.

                              Comment

                              Working...
                              X